8#include "crypto/sha256.h"
28 static constexpr size_t elements_in_dynamic_fee_transaction = 12;
29 static constexpr size_t elements_in_access_list_transaction = 11;
30 static constexpr size_t elements_in_legacy_transaction = 9;
33 && rlp_tx.size() != elements_in_dynamic_fee_transaction) {
37 && rlp_tx.size() != elements_in_access_list_transaction) {
41 && rlp_tx.size() != elements_in_legacy_transaction) {
49 const std::shared_ptr<logging::log>& logger,
50 const std::shared_ptr<cbdc::parsec::agent::runner::evm_tx>& tx)
51 -> std::optional<rlp_value> {
53 std::memcpy(&type_byte, buf.data_at(0), 1);
54 size_t rlp_offset = 0;
55 if(type_byte >= 1 && type_byte <= 2) {
61 buf_cpy.append(buf.data_at(rlp_offset), buf.size() - rlp_offset);
63 if(!maybe_rlp_tx.has_value()) {
66 auto rlp_tx = maybe_rlp_tx.value();
70 logger->error(
"tx is not valid rlp");
79 const std::shared_ptr<logging::log>& logger,
82 std::shared_ptr<cbdc::parsec::agent::runner::evm_tx>> {
83 auto tx = std::make_shared<cbdc::parsec::agent::runner::evm_tx>();
85 if(!maybe_rlp_tx.has_value()) {
88 auto rlp_tx = maybe_rlp_tx.value();
90 auto element =
size_t{};
94 = rlp_tx.value_at(element++).value<evmc::uint256be>();
97 logger->error(
"tx is wrong chain ID");
103 tx->m_nonce = rlp_tx.value_at(element++).value<evmc::uint256be>();
107 = rlp_tx.value_at(element++).value<evmc::uint256be>();
109 = rlp_tx.value_at(element++).value<evmc::uint256be>();
112 = rlp_tx.value_at(element++).value<evmc::uint256be>();
114 tx->m_gas_limit = rlp_tx.value_at(element++).value<evmc::uint256be>();
115 auto to = rlp_tx.value_at(element++);
117 tx->m_to = to.value<evmc::address>();
119 tx->m_value = rlp_tx.value_at(element++).value<evmc::uint256be>();
120 auto data = rlp_tx.value_at(element++);
121 tx->m_input.resize(data.size());
122 std::memcpy(tx->m_input.data(), data.data(), data.size());
126 auto rlp_access_list = rlp_tx.value_at(element++);
133 tx->m_sig.m_v = rlp_tx.value_at(element++).value<evmc::uint256be>();
136 if(small_v >= eip155_v_offset) {
137 auto tx_chain_id = (small_v - eip155_v_offset) / 2;
138 if(tx_chain_id != chain_id) {
140 logger->error(
"tx is wrong chain ID (",
142 ") where expected (",
150 tx->m_sig.m_r = rlp_tx.value_at(element++).value<evmc::uint256be>();
151 tx->m_sig.m_s = rlp_tx.value_at(element++).value<evmc::uint256be>();
162 data_buf.extend(tx.m_input.size());
163 std::memcpy(data_buf.data(), tx.m_input.data(), tx.m_input.size());
166 if(tx.m_to.has_value()) {
175 ser << std::byte(tx.m_type);
176 rlp_tx.push_back(
make_rlp_value(evmc::uint256be(chain_id),
true));
187 rlp_tx.push_back(to);
195 rlp_tx.push_back(
make_rlp_value(evmc::uint256be(chain_id),
true));
198 }
else if(!for_sighash) {
210 std::shared_ptr<cbdc::parsec::agent::runner::evm_dryrun_tx>> {
217 = std::make_shared<cbdc::parsec::agent::runner::evm_dryrun_tx>();
218 drtx->m_tx = *tx.value();
221 drtx->m_from = maybe_from.value();
227 -> std::optional<evmc::address> {
228 if(!addr.empty() && addr.isString()) {
229 auto addr_str = addr.asString();
230 if(addr_str.size() > 2) {
235 maybe_addr_buf.value());
237 return maybe_addr.value();
246 -> std::optional<evmc::uint256be> {
252 return maybe_val.value();
259 -> std::optional<cbdc::buffer> {
260 if(!val.empty() && val.isString()) {
261 auto val_str = val.asString();
262 if(val_str.size() > 2) {
273 return maybe_ui256.value();
279 std::shared_ptr<cbdc::parsec::agent::runner::evm_tx>> {
280 if(!param.isString()) {
283 auto params_str = param.asString();
285 if(!maybe_raw_tx.has_value()) {
289 const std::shared_ptr<logging::log> nolog =
nullptr;
290 return tx_decode(maybe_raw_tx.value(), nolog);
295 std::shared_ptr<cbdc::parsec::agent::runner::evm_tx>> {
296 auto tx = std::make_shared<cbdc::parsec::agent::runner::evm_tx>();
298 if(!json[
"type"].empty() && json[
"type"].isNumeric()) {
299 tx->m_type =
static_cast<evm_tx_type>(json[
"type"].asInt());
304 tx->m_to = maybe_to.value();
324 tx->m_input.resize(maybe_input->size());
325 std::memcpy(tx->m_input.data(),
327 maybe_input->size());
338 const std::shared_ptr<secp256k1_context>& ctx)
340 auto res = Json::Value();
342 evmc::uint256be(
static_cast<uint64_t
>(tx.m_type)));
344 if(tx.m_to.has_value()) {
345 res[
"to"] =
"0x" +
to_hex(tx.m_to.value());
358 if(!tx.m_input.empty()) {
360 buf.extend(tx.m_input.size());
361 std::memcpy(buf.data(), tx.m_input.data(), tx.m_input.size());
362 res[
"input"] = buf.to_hex_prefixed();
376 res[
"chainId"] =
to_hex_trimmed(evmc::uint256be(opencbdc_chain_id));
379 if(maybe_from_addr) {
380 res[
"from"] =
"0x" +
to_hex(maybe_from_addr.value());
387 const std::shared_ptr<secp256k1_context>& ctx)
389 auto res = Json::Value();
391 auto txid =
tx_id(rcpt.m_tx);
393 res[
"transaction"] =
tx_to_json(rcpt.m_tx, ctx);
394 res[
"from"] = res[
"transaction"][
"from"];
395 res[
"to"] = res[
"transaction"][
"to"];
396 if(rcpt.m_create_address.has_value()) {
397 res[
"contractAddress"]
398 =
"0x" +
to_hex(rcpt.m_create_address.value());
402 res[
"logs"] = Json::Value(Json::arrayValue);
403 res[
"status"] = rcpt.m_success ?
"0x1" :
"0x0";
406 constexpr auto bits_in_32_bytes = 256;
407 bloom.extend(bits_in_32_bytes);
408 for(
auto& l : rcpt.m_logs) {
409 res[
"logs"].append(
tx_log_to_json(l, rcpt.m_ticket_number, txid));
411 for(
auto& t : l.m_topics) {
416 res[
"logsBloom"] = bloom.to_hex_prefixed();
418 if(!rcpt.m_output_data.empty()) {
420 buf.extend(rcpt.m_output_data.size());
421 std::memcpy(buf.data(),
422 rcpt.m_output_data.data(),
423 rcpt.m_output_data.size());
424 res[
"output_data"] = buf.to_hex_prefixed();
427 res[
"success"] =
"0x1";
428 res[
"transactionIndex"] =
"0x0";
429 res[
"transactionHash"] =
"0x" +
to_string(txid);
430 auto tn256 = evmc::uint256be(rcpt.m_ticket_number);
431 res[
"blockHash"] =
"0x" +
to_hex(tn256);
439 auto res = Json::Value();
440 res[
"address"] =
"0x" +
to_hex(log.m_addr);
441 if(!log.m_data.empty()) {
443 buf.extend(log.m_data.size());
444 std::memcpy(buf.data(), log.m_data.data(), log.m_data.size());
445 res[
"data"] = buf.to_hex_prefixed();
449 res[
"topics"] = Json::Value(Json::arrayValue);
450 for(
auto& t : log.m_topics) {
451 res[
"topics"].append(
"0x" +
to_hex(t));
454 auto tn256 = evmc::uint256be(tn);
455 res[
"blockHash"] =
"0x" +
to_hex(tn256);
458 res[
"transactionIndex"] =
"0x0";
460 res[
"logIndex"] =
"0x0";
466 auto res = Json::Value(Json::arrayValue);
467 for(
auto& tuple : al) {
468 auto json_tuple = Json::Value();
469 json_tuple[
"address"] =
to_hex(tuple.m_address);
470 json_tuple[
"storageKeys"] = Json::Value(Json::arrayValue);
471 for(
auto& k : tuple.m_storage_keys) {
472 json_tuple[
"storageKeys"].append(
to_hex(k));
474 res.append(json_tuple);
Serializer implementation for buffer.
Buffer to store and retrieve byte data.
static auto from_hex(const std::string &hex) -> std::optional< cbdc::buffer >
Creates a new buffer from the provided hex string.
parsec::ticket_machine::ticket_number_type ticket_number_type
Type alias for a ticket number.
This class contains a value that can be serialized into, or was deserialized from,...
auto tx_to_json(cbdc::parsec::agent::runner::evm_tx &tx, const std::shared_ptr< secp256k1_context > &ctx) -> Json::Value
Encodes the given transaction into a eth-RPC compatible representation in JSON - as Json::Value.
auto raw_tx_from_json(const Json::Value ¶m) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_tx > >
Converts a given Json::Value to an evm_tx.
auto to_hex_trimmed(const evmc::bytes32 &b, const std::string &prefix) -> std::string
auto address_from_json(const Json::Value &addr) -> std::optional< evmc::address >
Converts a given Json::Value to an evmc::address.
auto tx_encode(const cbdc::parsec::agent::runner::evm_tx &tx, uint64_t chain_id, bool for_sighash) -> cbdc::buffer
Converts the given transaction to an RLP encoded buffer conforming to Ethereums conventions.
auto tx_log_to_json(cbdc::parsec::agent::runner::evm_log &log, interface::ticket_number_type tn, cbdc::hash_t txid) -> Json::Value
Encodes the given transaction log into a eth-RPC compatible representation in JSON - as Json::Value.
auto check_tx_decode(const cbdc::buffer &buf, const std::shared_ptr< logging::log > &logger, const std::shared_ptr< cbdc::parsec::agent::runner::evm_tx > &tx) -> std::optional< rlp_value >
auto tx_receipt_to_json(cbdc::parsec::agent::runner::evm_tx_receipt &rcpt, const std::shared_ptr< secp256k1_context > &ctx) -> Json::Value
Encodes the given transaction receipt into a eth-RPC compatible representation in JSON - as Json::Val...
auto to_hex(const evmc::address &addr) -> std::string
auto check_signature(const cbdc::parsec::agent::runner::evm_tx &tx, const std::shared_ptr< secp256k1_context > &ctx, uint64_t chain_id) -> std::optional< evmc::address >
Checks the signature of an EVM transaction.
auto buffer_from_json(const Json::Value &val) -> std::optional< cbdc::buffer >
Converts a given Json::Value to a cbdc::buffer.
auto dryrun_tx_from_json(const Json::Value &json, uint64_t chain_id) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_dryrun_tx > >
Converts a given Json::Value to an evm_dryrun_tx.
auto tx_from_json(const Json::Value &json, uint64_t) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_tx > >
Converts a given Json::Value to an evm_tx.
auto is_valid_rlp_tx(evm_tx_type type, const rlp_value &rlp_tx) -> bool
auto uint256be_from_json(const Json::Value &val) -> std::optional< evmc::uint256be >
Converts a given Json::Value to an evmc::uint256be.
evm_tx_type
 EVM transaction types.
auto access_list_to_json(cbdc::parsec::agent::runner::evm_access_list &al) -> Json::Value
Encodes the given access list into a eth-RPC compatible representation in JSON - as Json::Value.
auto tx_decode(const cbdc::buffer &buf, const std::shared_ptr< logging::log > &logger, uint64_t chain_id) -> std::optional< std::shared_ptr< cbdc::parsec::agent::runner::evm_tx > >
Converts a given buffer to an evm_tx.
std::vector< evm_access_tuple > evm_access_list
Type alias for a list of storage key accesses.
auto uint256be_or_default(const Json::Value &val, evmc::uint256be def) -> evmc::uint256be
Converts a given Json::Value to an evmc::uint256be, returning a default value if none could be decode...
void add_to_bloom(cbdc::buffer &bloom, const cbdc::buffer &entry)
Adds an entry to a bloom value.
auto to_uint64(const evmc::uint256be &v) -> uint64_t
Converts an uint256be to a uint64_t, ignoring higher order bits.
auto tx_id(const cbdc::parsec::agent::runner::evm_tx &tx, uint64_t chain_id) -> cbdc::hash_t
Calculate ethereum-compatible txid.
auto rlp_decode_access_list(const rlp_value &rlp) -> std::optional< parsec::agent::runner::evm_access_list >
Decodes an access list from and rlp_value of type rlp_value_type::array.
auto rlp_encode_access_list(const parsec::agent::runner::evm_access_list &access_list) -> rlp_value
RLP encodes an access list.
auto from_buffer(nuraft::buffer &buf) -> std::optional< T >
Deserialize object of given type from a nuraft::buffer.
std::array< unsigned char, cbdc::hash_size > hash_t
SHA256 hash container.
auto make_rlp_value(const T &obj, bool trim_leading_zeroes=false) -> rlp_value
Turns an existing value into an rlp_value by first serializing it as a cbdc::buffer,...
@ buffer
A singular RLP value (byte array)
@ array
A collection of RLP values.
auto keccak_data(const void *data, size_t len) -> hash_t
Calculates the Keccak256 hash of the specified data.
auto to_string(const hash_t &val) -> std::string
Converts a hash to a hexadecimal string.
auto make_buffer(const T &obj) -> std::enable_if_t< std::is_same_v< B, nuraft::ptr< nuraft::buffer > >, nuraft::ptr< nuraft::buffer > >
Serialize object into nuraft::buffer using a cbdc::nuraft_serializer.
EVM transaction receipt type.