diff --git a/benchmark/bls.cpp b/benchmark/bls.cpp index 4c86e78ba1..2178c17ba8 100644 --- a/benchmark/bls.cpp +++ b/benchmark/bls.cpp @@ -70,7 +70,8 @@ struct interface_in_benchmark { // build transaction context from the packed transaction timer = std::make_unique(); trx_timer = std::make_unique(*timer); - trx_ctx = std::make_unique(*chain->control.get(), *ptrx, ptrx->id(), std::move(*trx_timer)); + trx_ctx = std::make_unique(*chain->control.get(), *ptrx, ptrx->id(), std::move(*trx_timer), + action_digests_t::store_which_t::legacy); trx_ctx->max_transaction_time_subjective = fc::microseconds::maximum(); trx_ctx->init_for_input_trx( ptrx->get_unprunable_size(), ptrx->get_prunable_size() ); trx_ctx->exec(); // this is required to generate action traces to be used by apply_context constructor diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 75d42dbe35..aba88fbc61 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -14,7 +14,7 @@ using boost::container::flat_set; -namespace eosio { namespace chain { +namespace eosio::chain { static inline void print_debug(account_name receiver, const action_trace& ar) { if (!ar.console.empty()) { @@ -184,7 +184,7 @@ void apply_context::exec_one() r.auth_sequence[auth.actor] = next_auth_sequence( auth.actor ); } - trx_context.executed_action_receipt_digests.emplace_back( r.digest() ); + trx_context.executed_action_receipts.compute_and_append_digests_from(trace); finalize_trace( trace, start ); @@ -218,17 +218,17 @@ void apply_context::exec() exec_one(); } - if( _cfa_inline_actions.size() > 0 || _inline_actions.size() > 0 ) { + if( !_cfa_inline_actions.empty() || !_inline_actions.empty() ) { EOS_ASSERT( recurse_depth < control.get_global_properties().configuration.max_inline_action_depth, transaction_exception, "max inline action depth per transaction reached" ); - } - for( uint32_t ordinal : _cfa_inline_actions ) { - trx_context.execute_action( ordinal, recurse_depth + 1 ); - } + for( uint32_t ordinal : _cfa_inline_actions ) { + trx_context.execute_action( ordinal, recurse_depth + 1 ); + } - for( uint32_t ordinal : _inline_actions ) { - trx_context.execute_action( ordinal, recurse_depth + 1 ); + for( uint32_t ordinal : _inline_actions ) { + trx_context.execute_action( ordinal, recurse_depth + 1 ); + } } } /// exec() @@ -1105,4 +1105,4 @@ bool apply_context::should_use_eos_vm_oc()const { } -} } /// eosio::chain +} /// eosio::chain diff --git a/libraries/chain/block_header_state.cpp b/libraries/chain/block_header_state.cpp index b51ddc50df..7879555842 100644 --- a/libraries/chain/block_header_state.cpp +++ b/libraries/chain/block_header_state.cpp @@ -81,7 +81,7 @@ block_header_state block_header_state::next(block_header_state_input& input) con // header // ------ result.header = { - .timestamp = input.timestamp, // [greg todo] do we have to do the slot++ stuff from the legacy version? + .timestamp = input.timestamp, .producer = input.producer, .confirmed = 0, .previous = input.parent_id, diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 851c20ae54..5cf44caecf 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -158,7 +158,7 @@ struct completed_block { // to be used during Legacy to Savanna transistion where action_mroot // needs to be converted from Legacy merkle to Savanna merkle - std::optional action_receipt_digests; + std::optional action_receipt_digests_savanna; bool is_legacy() const { return std::holds_alternative(bsp.internal()); } @@ -229,7 +229,7 @@ struct assembled_block { std::optional new_producer_authority_cache; // Passed to completed_block, to be used by Legacy to Savanna transisition - std::optional action_receipt_digests; + std::optional action_receipt_digests_savanna; }; // -------------------------------------------------------------------------------- @@ -317,9 +317,9 @@ struct assembled_block { v); } - std::optional get_action_receipt_digests() const { + std::optional get_action_receipt_digests_savanna() const { return std::visit( - overloaded{[](const assembled_block_legacy& ab) -> std::optional { return ab.action_receipt_digests; }, + overloaded{[](const assembled_block_legacy& ab) -> std::optional { return ab.action_receipt_digests_savanna; }, [](const assembled_block_if& ab) -> std::optional { return {}; }}, v); } @@ -365,7 +365,7 @@ struct assembled_block { std::move(ab.pending_block_header_state), std::move(ab.unsigned_block), std::move(ab.trx_metas), pfs, validator, signer); - return completed_block{block_handle{std::move(bsp)}, std::move(ab.action_receipt_digests)}; + return completed_block{block_handle{std::move(bsp)}, std::move(ab.action_receipt_digests_savanna)}; }, [&](assembled_block_if& ab) { auto bsp = std::make_shared(ab.bhs, std::move(ab.trx_metas), @@ -381,17 +381,21 @@ struct building_block { // -------------------------------------------------------------------------------- struct building_block_common { using checksum_or_digests = std::variant; + const vector new_protocol_feature_activations; size_t num_new_protocol_features_that_have_activated = 0; deque pending_trx_metas; deque pending_trx_receipts; checksum_or_digests trx_mroot_or_receipt_digests {digests_t{}}; - digests_t action_receipt_digests; + action_digests_t action_receipt_digests; std::optional new_finalizer_policy; - building_block_common(const vector& new_protocol_feature_activations) : - new_protocol_feature_activations(new_protocol_feature_activations) - {} + building_block_common(const vector& new_protocol_feature_activations, + action_digests_t::store_which_t store_which) : + new_protocol_feature_activations(new_protocol_feature_activations), + action_receipt_digests(store_which) + { + } bool is_protocol_feature_activated(const digest_type& digest, const flat_set& activated_features) const { if (activated_features.find(digest) != activated_features.end()) @@ -429,10 +433,11 @@ struct building_block { std::optional new_pending_producer_schedule; building_block_legacy( const block_header_state_legacy& prev, - block_timestamp_type when, - uint16_t num_prev_blocks_to_confirm, - const vector& new_protocol_feature_activations) - : building_block_common(new_protocol_feature_activations), + block_timestamp_type when, + uint16_t num_prev_blocks_to_confirm, + const vector& new_protocol_feature_activations, + action_digests_t::store_which_t store_which) + : building_block_common(new_protocol_feature_activations, store_which), pending_block_header_state(prev.next(when, num_prev_blocks_to_confirm)) {} @@ -453,8 +458,8 @@ struct building_block { const proposer_policy_ptr active_proposer_policy; // Cached: parent.get_next_active_proposer_policy(timestamp) const uint32_t block_num; // Cached: parent.block_num() + 1 - building_block_if(const block_state& parent, const building_block_input& input) - : building_block_common(input.new_protocol_feature_activations) + building_block_if(const block_state& parent, const building_block_input& input, action_digests_t::store_which_t store_which) + : building_block_common(input.new_protocol_feature_activations, store_which) , parent (parent) , timestamp(input.timestamp) , active_producer_authority{input.producer, @@ -491,12 +496,13 @@ struct building_block { // legacy constructor building_block(const block_header_state_legacy& prev, block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector& new_protocol_feature_activations) : - v(building_block_legacy(prev, when, num_prev_blocks_to_confirm, new_protocol_feature_activations)) + v(building_block_legacy(prev, when, num_prev_blocks_to_confirm, new_protocol_feature_activations, + action_digests_t::store_which_t::both)) // [todo] should be both only when transition starts {} // if constructor building_block(const block_state& prev, const building_block_input& input) : - v(building_block_if(prev, input)) + v(building_block_if(prev, input, action_digests_t::store_which_t::savanna)) {} bool is_legacy() const { return std::holds_alternative(v); } @@ -585,8 +591,8 @@ struct building_block { [](auto& bb) -> building_block_common::checksum_or_digests& { return bb.trx_mroot_or_receipt_digests; }, v); } - digests_t& action_receipt_digests() { - return std::visit([](auto& bb) -> digests_t& { return bb.action_receipt_digests; }, v); + action_digests_t& action_receipt_digests() { + return std::visit([](auto& bb) -> action_digests_t& { return bb.action_receipt_digests; }, v); } const producer_authority_schedule& active_producers() const { @@ -660,7 +666,7 @@ struct building_block { bool validating, std::optional validating_qc_data, const block_state_ptr& validating_bsp) { - digests_t& action_receipts = action_receipt_digests(); + auto& action_receipts = action_receipt_digests(); return std::visit( overloaded{ [&](building_block_legacy& bb) -> assembled_block { @@ -670,11 +676,11 @@ struct building_block { auto trx_merkle_fut = post_async_task(ioc, [&]() { return legacy_merkle(std::move(trx_receipts)); }); auto action_merkle_fut = - post_async_task(ioc, [&]() { return legacy_merkle(std::move(action_receipts)); }); + post_async_task(ioc, [&]() { return legacy_merkle(std::move(*action_receipts.digests_l)); }); return std::make_pair(trx_merkle_fut.get(), action_merkle_fut.get()); }, [&](const checksum256_type& trx_checksum) { - return std::make_pair(trx_checksum, legacy_merkle(std::move(action_receipts))); + return std::make_pair(trx_checksum, legacy_merkle(std::move(*action_receipts.digests_l))); }}, trx_mroot_or_receipt_digests()); @@ -690,7 +696,7 @@ struct building_block { std::move(bb.pending_block_header_state), std::move(bb.pending_trx_metas), std::move(block_ptr), std::move(bb.new_pending_producer_schedule), - std::move(bb.action_receipt_digests)} + std::move(bb.action_receipt_digests.digests_s)} }; }, [&](building_block_if& bb) -> assembled_block { @@ -699,11 +705,12 @@ struct building_block { overloaded{[&](digests_t& trx_receipts) { // calculate the two merkle roots in separate threads auto trx_merkle_fut = post_async_task(ioc, [&]() { return calculate_merkle(std::move(trx_receipts)); }); - auto action_merkle_fut = post_async_task(ioc, [&]() { return calculate_merkle(std::move(action_receipts)); }); + auto action_merkle_fut = + post_async_task(ioc, [&]() { return calculate_merkle(std::move(*action_receipts.digests_s)); }); return std::make_pair(trx_merkle_fut.get(), action_merkle_fut.get()); }, [&](const checksum256_type& trx_checksum) { - return std::make_pair(trx_checksum, calculate_merkle(std::move(action_receipts))); + return std::make_pair(trx_checksum, calculate_merkle(std::move(*action_receipts.digests_s))); }}, trx_mroot_or_receipt_digests()); @@ -2161,9 +2168,11 @@ struct controller_impl { etrx.set_reference_block( chain_head.id() ); } + auto& bb = std::get(pending->_block_stage); + transaction_checktime_timer trx_timer(timer); const packed_transaction trx( std::move( etrx ) ); - transaction_context trx_context( self, trx, trx.id(), std::move(trx_timer), start ); + transaction_context trx_context( self, trx, trx.id(), std::move(trx_timer), bb.action_receipt_digests().store_which(), start ); if (auto dm_logger = get_deep_mind_logger(trx_context.is_transient())) { dm_logger->on_onerror(etrx); @@ -2174,6 +2183,7 @@ struct controller_impl { trx_context.explicit_billed_cpu_time = explicit_billed_cpu_time; trx_context.billed_cpu_time_us = billed_cpu_time_us; trx_context.enforce_whiteblacklist = enforce_whiteblacklist; + transaction_trace_ptr trace = trx_context.trace; auto handle_exception = [&](const auto& e) @@ -2193,8 +2203,8 @@ struct controller_impl { auto restore = make_block_restore_point(); trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::soft_fail, trx_context.billed_cpu_time_us, trace->net_usage ); - auto& bb = std::get(pending->_block_stage); - fc::move_append( bb.action_receipt_digests(), std::move(trx_context.executed_action_receipt_digests) ); + + bb.action_receipt_digests().append(std::move(trx_context.executed_action_receipts)); trx_context.squash(); restore.cancel(); @@ -2331,9 +2341,10 @@ struct controller_impl { in_trx_requiring_checks = true; uint32_t cpu_time_to_bill_us = billed_cpu_time_us; + auto& bb = std::get(pending->_block_stage); transaction_checktime_timer trx_timer( timer ); - transaction_context trx_context( self, *trx->packed_trx(), gtrx.trx_id, std::move(trx_timer) ); + transaction_context trx_context( self, *trx->packed_trx(), gtrx.trx_id, std::move(trx_timer), bb.action_receipt_digests().store_which() ); trx_context.leeway = fc::microseconds(0); // avoid stealing cpu resource trx_context.block_deadline = block_deadline; trx_context.max_transaction_time_subjective = max_transaction_time; @@ -2379,8 +2390,7 @@ struct controller_impl { trx_context.billed_cpu_time_us, trace->net_usage ); - fc::move_append( std::get(pending->_block_stage).action_receipt_digests(), - std::move(trx_context.executed_action_receipt_digests) ); + bb.action_receipt_digests().append(std::move(trx_context.executed_action_receipts)); trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta ); @@ -2541,9 +2551,12 @@ struct controller_impl { } } + auto& bb = std::get(pending->_block_stage); + const signed_transaction& trn = trx->packed_trx()->get_signed_transaction(); transaction_checktime_timer trx_timer(timer); - transaction_context trx_context(self, *trx->packed_trx(), trx->id(), std::move(trx_timer), start, trx->get_trx_type()); + transaction_context trx_context(self, *trx->packed_trx(), trx->id(), std::move(trx_timer), + bb.action_receipt_digests().store_which(), start, trx->get_trx_type()); if ((bool)subjective_cpu_leeway && is_speculative_block()) { trx_context.leeway = *subjective_cpu_leeway; } @@ -2589,7 +2602,6 @@ struct controller_impl { auto restore = make_block_restore_point( trx->is_read_only() ); - auto& bb = std::get(pending->_block_stage); trx->billed_cpu_time_us = trx_context.billed_cpu_time_us; if (!trx->implicit() && !trx->is_read_only()) { transaction_receipt::status_enum s = (trx_context.delay == fc::seconds(0)) @@ -2606,17 +2618,17 @@ struct controller_impl { } if ( !trx->is_read_only() ) { - fc::move_append( bb.action_receipt_digests(), - std::move(trx_context.executed_action_receipt_digests) ); - if ( !trx->is_dry_run() ) { - // call the accept signal but only once for this transaction - if (!trx->accepted) { - trx->accepted = true; - } - - dmlog_applied_transaction(trace, &trn); - emit(applied_transaction, std::tie(trace, trx->packed_trx())); - } + bb.action_receipt_digests().append(std::move(trx_context.executed_action_receipts)); + + if ( !trx->is_dry_run() ) { + // call the accept signal but only once for this transaction + if (!trx->accepted) { + trx->accepted = true; + } + + dmlog_applied_transaction(trace, &trn); + emit(applied_transaction, std::tie(trace, trx->packed_trx())); + } } if ( trx->is_transient() ) { @@ -2914,7 +2926,7 @@ struct controller_impl { EOS_ASSERT( std::holds_alternative(pending->_block_stage), block_validate_exception, "cannot call commit_block until pending block is completed" ); - const auto& cb = std::get(pending->_block_stage); + auto& cb = std::get(pending->_block_stage); if (s != controller::block_status::irreversible) { auto add_completed_block = [&](auto& forkdb) { @@ -3011,10 +3023,10 @@ struct controller_impl { assert(std::holds_alternative(chain_head.internal())); block_state_legacy_ptr head = std::get(chain_head.internal()); // will throw if called after transistion - // Calculate Merkel tree root in Savanna way so that it is stored in + // Calculate Merkle tree root in Savanna way so that it is stored in // Leaf Node when building block_state. - assert(cb.action_receipt_digests); - auto action_mroot = calculate_merkle((*cb.action_receipt_digests)); + assert(cb.action_receipt_digests_savanna); + auto action_mroot = calculate_merkle(std::move(*cb.action_receipt_digests_savanna)); auto new_head = std::make_shared(*head, action_mroot); @@ -3280,7 +3292,7 @@ struct controller_impl { bsp->set_trxs_metas( ab.extract_trx_metas(), !skip_auth_checks ); } // create completed_block with the existing block_state as we just verified it is the same as assembled_block - pending->_block_stage = completed_block{ block_handle{bsp}, ab.get_action_receipt_digests() }; + pending->_block_stage = completed_block{ block_handle{bsp}, ab.get_action_receipt_digests_savanna() }; br = pending->_block_report; // copy before commit block destroys pending commit_block(s); diff --git a/libraries/chain/include/eosio/chain/action_receipt.hpp b/libraries/chain/include/eosio/chain/action_receipt.hpp index 4afe35371d..b921b115be 100644 --- a/libraries/chain/include/eosio/chain/action_receipt.hpp +++ b/libraries/chain/include/eosio/chain/action_receipt.hpp @@ -1,8 +1,9 @@ #pragma once #include +#include -namespace eosio { namespace chain { +namespace eosio::chain { /** * For each action dispatched this receipt is generated @@ -15,20 +16,8 @@ namespace eosio { namespace chain { flat_map auth_sequence; fc::unsigned_int code_sequence = 0; ///< total number of setcodes fc::unsigned_int abi_sequence = 0; ///< total number of setabis - - digest_type digest()const { - digest_type::encoder e; - fc::raw::pack(e, receiver); - fc::raw::pack(e, act_digest); - fc::raw::pack(e, global_sequence); - fc::raw::pack(e, recv_sequence); - fc::raw::pack(e, auth_sequence); - fc::raw::pack(e, code_sequence); - fc::raw::pack(e, abi_sequence); - return e.result(); - } }; -} } /// namespace eosio::chain +} /// namespace eosio::chain FC_REFLECT( eosio::chain::action_receipt, (receiver)(act_digest)(global_sequence)(recv_sequence)(auth_sequence)(code_sequence)(abi_sequence) ) diff --git a/libraries/chain/include/eosio/chain/incremental_merkle.hpp b/libraries/chain/include/eosio/chain/incremental_merkle.hpp index 1f157d20f7..224f5754b3 100644 --- a/libraries/chain/include/eosio/chain/incremental_merkle.hpp +++ b/libraries/chain/include/eosio/chain/incremental_merkle.hpp @@ -56,7 +56,7 @@ constexpr int clz_power_2(uint64_t value) { * @param node_count - the number of nodes in the implied tree * @return the max depth of the minimal tree that stores them */ -constexpr int calcluate_max_depth(uint64_t node_count) { +constexpr int calculate_max_depth(uint64_t node_count) { if (node_count == 0) { return 0; } @@ -166,7 +166,7 @@ class incremental_merkle_impl { */ const DigestType& append(const DigestType& digest) { bool partial = false; - auto max_depth = detail::calcluate_max_depth(_node_count + 1); + auto max_depth = detail::calculate_max_depth(_node_count + 1); auto current_depth = max_depth - 1; auto index = _node_count; auto top = digest; diff --git a/libraries/chain/include/eosio/chain/merkle.hpp b/libraries/chain/include/eosio/chain/merkle.hpp index f7cbc0ae68..70932926da 100644 --- a/libraries/chain/include/eosio/chain/merkle.hpp +++ b/libraries/chain/include/eosio/chain/merkle.hpp @@ -19,11 +19,11 @@ namespace eosio { namespace chain { * Uses make_canonical_pair which before hashing sets the first bit of the previous hashes * to 0 or 1 to indicate the side it is on. */ - digest_type legacy_merkle( deque ids ); + digest_type legacy_merkle( deque&& ids ); /** * Calculates the merkle root of a set of digests. Does not manipulate the digests. */ - digest_type calculate_merkle( deque ids ); + digest_type calculate_merkle( deque&& ids ); } } /// eosio::chain diff --git a/libraries/chain/include/eosio/chain/trace.hpp b/libraries/chain/include/eosio/chain/trace.hpp index 22957918b2..b615afc079 100644 --- a/libraries/chain/include/eosio/chain/trace.hpp +++ b/libraries/chain/include/eosio/chain/trace.hpp @@ -4,7 +4,7 @@ #include #include -namespace eosio { namespace chain { +namespace eosio::chain { struct account_delta { account_delta( const account_name& n, int64_t d):account(n),delta(d){} @@ -45,6 +45,43 @@ namespace eosio { namespace chain { std::optional except; std::optional error_code; std::vector return_value; + + digest_type digest_savanna() const { + assert(!!receipt); + const action_receipt& r = *receipt; + + digest_type::encoder e; + fc::raw::pack(e, r.receiver); + fc::raw::pack(e, r.recv_sequence); + fc::raw::pack(e, act.account); + fc::raw::pack(e, act.name); + fc::raw::pack(e, r.act_digest); + + { + digest_type::encoder e2; + fc::raw::pack(e2, r.global_sequence); + fc::raw::pack(e2, r.auth_sequence); + fc::raw::pack(e2, r.code_sequence); + fc::raw::pack(e2, r.abi_sequence); + fc::raw::pack(e, e2.result()); + } + return e.result(); + } + + digest_type digest_legacy()const { + assert(!!receipt); + const action_receipt& r = *receipt; + + digest_type::encoder e; + fc::raw::pack(e, r.receiver); + fc::raw::pack(e, r.act_digest); + fc::raw::pack(e, r.global_sequence); + fc::raw::pack(e, r.recv_sequence); + fc::raw::pack(e, r.auth_sequence); + fc::raw::pack(e, r.code_sequence); + fc::raw::pack(e, r.abi_sequence); + return e.result(); + } }; struct transaction_trace { @@ -80,7 +117,7 @@ namespace eosio { namespace chain { auth.permission == eosio::chain::config::active_name; } -} } /// namespace eosio::chain +} /// namespace eosio::chain FC_REFLECT( eosio::chain::account_delta, (account)(delta) ) diff --git a/libraries/chain/include/eosio/chain/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp index 806e75d9dd..525794e929 100644 --- a/libraries/chain/include/eosio/chain/transaction_context.hpp +++ b/libraries/chain/include/eosio/chain/transaction_context.hpp @@ -33,6 +33,52 @@ namespace eosio { namespace chain { friend controller_impl; }; + struct action_digests_t { + enum class store_which_t { legacy, savanna, both }; + + std::optional digests_l; // legacy + std::optional digests_s; // savanna + + action_digests_t(store_which_t sw) { + if (sw == store_which_t::legacy || sw == store_which_t::both) + digests_l = digests_t{}; + if (sw == store_which_t::savanna || sw == store_which_t::both) + digests_s = digests_t{}; + } + + void append(action_digests_t&& o) { + if (digests_l) + fc::move_append(*digests_l, std::move(*o.digests_l)); + if (digests_s) + fc::move_append(*digests_s, std::move(*o.digests_s)); + } + + void compute_and_append_digests_from(action_trace& trace) { + if (digests_l) + digests_l->emplace_back(trace.digest_legacy()); + if (digests_s) + digests_s->emplace_back(trace.digest_savanna()); + } + + store_which_t store_which() const { + if (digests_l && digests_s) + return store_which_t::both; + if (digests_l) + return store_which_t::legacy; + assert(digests_s); + return store_which_t::savanna; + } + + std::pair size() const { + return { digests_l ? digests_l->size() : 0, digests_s ? digests_s->size() : 0 }; + } + + void resize(std::pair sz) { + if (digests_l) digests_l->resize(sz.first); + if (digests_s) digests_s->resize(sz.second); + } + }; + class transaction_context { private: void init( uint64_t initial_net_usage); @@ -43,6 +89,7 @@ namespace eosio { namespace chain { const packed_transaction& t, const transaction_id_type& trx_id, // trx_id diff than t.id() before replace_deferred transaction_checktime_timer&& timer, + action_digests_t::store_which_t sad, fc::time_point start = fc::time_point::now(), transaction_metadata::trx_type type = transaction_metadata::trx_type::input); ~transaction_context(); @@ -140,8 +187,7 @@ namespace eosio { namespace chain { fc::time_point published; - - deque executed_action_receipt_digests; + action_digests_t executed_action_receipts; flat_set bill_to_accounts; flat_set validate_ram_usage; diff --git a/libraries/chain/merkle.cpp b/libraries/chain/merkle.cpp index de3468e7f7..fc3ed100f5 100644 --- a/libraries/chain/merkle.cpp +++ b/libraries/chain/merkle.cpp @@ -32,7 +32,7 @@ bool is_canonical_right(const digest_type& val) { } -digest_type legacy_merkle(deque ids) { +digest_type legacy_merkle(deque&& ids) { if( 0 == ids.size() ) { return digest_type(); } while( ids.size() > 1 ) { @@ -49,7 +49,7 @@ digest_type legacy_merkle(deque ids) { return ids.front(); } -digest_type calculate_merkle( deque ids ) { +digest_type calculate_merkle( deque&& ids ) { if( 0 == ids.size() ) { return digest_type(); } while( ids.size() > 1 ) { diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 262d7995a7..03cfb55d32 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -11,7 +11,7 @@ #include -namespace eosio { namespace chain { +namespace eosio::chain { transaction_checktime_timer::transaction_checktime_timer(platform_timer& timer) : expired(timer.expired), _timer(timer) { @@ -39,6 +39,7 @@ namespace eosio { namespace chain { const packed_transaction& t, const transaction_id_type& trx_id, transaction_checktime_timer&& tmr, + action_digests_t::store_which_t store_which, fc::time_point s, transaction_metadata::trx_type type) :control(c) @@ -47,6 +48,7 @@ namespace eosio { namespace chain { ,undo_session() ,trace(std::make_shared()) ,start(s) + ,executed_action_receipts(store_which) ,transaction_timer(std::move(tmr)) ,trx_type(type) ,net_usage(trace->net_usage) @@ -828,4 +830,4 @@ namespace eosio { namespace chain { } -} } /// eosio::chain +} /// eosio::chain diff --git a/unittests/api_tests.cpp b/unittests/api_tests.cpp index a25e96f0ad..1dd2fbb5a5 100644 --- a/unittests/api_tests.cpp +++ b/unittests/api_tests.cpp @@ -907,16 +907,17 @@ BOOST_AUTO_TEST_CASE(light_validation_skip_cfa) try { BOOST_CHECK(*trace->receipt == *other_trace->receipt); BOOST_CHECK_EQUAL(2, other_trace->action_traces.size()); + auto check_action_traces = [](const auto& t, const auto& ot) { + BOOST_CHECK_EQUAL("", ot.console); // cfa not executed for light validation (trusted producer) + BOOST_CHECK_EQUAL(t.receipt->global_sequence, ot.receipt->global_sequence); + BOOST_CHECK_EQUAL(t.digest_legacy(), ot.digest_legacy()); // digest_legacy because test doesn't switch to Savanna + }; + BOOST_CHECK(other_trace->action_traces.at(0).context_free); // cfa - BOOST_CHECK_EQUAL("", other_trace->action_traces.at(0).console); // cfa not executed for light validation (trusted producer) - BOOST_CHECK_EQUAL(trace->action_traces.at(0).receipt->global_sequence, other_trace->action_traces.at(0).receipt->global_sequence); - BOOST_CHECK_EQUAL(trace->action_traces.at(0).receipt->digest(), other_trace->action_traces.at(0).receipt->digest()); + check_action_traces(trace->action_traces.at(0), other_trace->action_traces.at(0)); BOOST_CHECK(!other_trace->action_traces.at(1).context_free); // non-cfa - BOOST_CHECK_EQUAL("", other_trace->action_traces.at(1).console); - BOOST_CHECK_EQUAL(trace->action_traces.at(1).receipt->global_sequence, other_trace->action_traces.at(1).receipt->global_sequence); - BOOST_CHECK_EQUAL(trace->action_traces.at(1).receipt->digest(), other_trace->action_traces.at(1).receipt->digest()); - + check_action_traces(trace->action_traces.at(1), other_trace->action_traces.at(1)); other.close(); diff --git a/unittests/restart_chain_tests.cpp b/unittests/restart_chain_tests.cpp index 913a72902a..d60fe80ef8 100644 --- a/unittests/restart_chain_tests.cpp +++ b/unittests/restart_chain_tests.cpp @@ -226,15 +226,17 @@ BOOST_AUTO_TEST_CASE(test_light_validation_restart_from_block_log) { BOOST_CHECK(*trace->receipt == *other_trace->receipt); BOOST_CHECK_EQUAL(2u, other_trace->action_traces.size()); + auto check_action_traces = [](const auto& t, const auto& ot) { + BOOST_CHECK_EQUAL("", ot.console); // cfa not executed for replay + BOOST_CHECK_EQUAL(t.receipt->global_sequence, ot.receipt->global_sequence); + BOOST_CHECK_EQUAL(t.digest_legacy(), ot.digest_legacy()); // digest_legacy because test doesn't switch to Savanna + }; + BOOST_CHECK(other_trace->action_traces.at(0).context_free); // cfa - BOOST_CHECK_EQUAL("", other_trace->action_traces.at(0).console); // cfa not executed for replay - BOOST_CHECK_EQUAL(trace->action_traces.at(0).receipt->global_sequence, other_trace->action_traces.at(0).receipt->global_sequence); - BOOST_CHECK_EQUAL(trace->action_traces.at(0).receipt->digest(), other_trace->action_traces.at(0).receipt->digest()); + check_action_traces(trace->action_traces.at(0), other_trace->action_traces.at(0)); BOOST_CHECK(!other_trace->action_traces.at(1).context_free); // non-cfa - BOOST_CHECK_EQUAL("", other_trace->action_traces.at(1).console); - BOOST_CHECK_EQUAL(trace->action_traces.at(1).receipt->global_sequence, other_trace->action_traces.at(1).receipt->global_sequence); - BOOST_CHECK_EQUAL(trace->action_traces.at(1).receipt->digest(), other_trace->action_traces.at(1).receipt->digest()); + check_action_traces(trace->action_traces.at(1), other_trace->action_traces.at(1)); } BOOST_AUTO_TEST_SUITE_END()