From dadd0774eeed483a83d110df0e45d3f34cd1a17a Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Tue, 19 Mar 2024 14:13:19 -0400 Subject: [PATCH 01/12] Add new Savanna action digest (wip). --- libraries/chain/apply_context.cpp | 4 +- .../include/eosio/chain/action_receipt.hpp | 17 ++------ libraries/chain/include/eosio/chain/trace.hpp | 41 ++++++++++++++++++- unittests/api_tests.cpp | 15 +++---- unittests/restart_chain_tests.cpp | 14 ++++--- 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 75d42dbe35..0ab815970c 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -184,10 +184,10 @@ 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() ); - finalize_trace( trace, start ); + trx_context.executed_action_receipt_digests.emplace_back( trace.digest_legacy() ); + if ( control.contracts_console() ) { print_debug(receiver, trace); } 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/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/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() From 9c703672558070972d5fd4bca9ac36f918dacc67 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Tue, 19 Mar 2024 14:15:07 -0400 Subject: [PATCH 02/12] merge `origin/hotstuff_integration` --- libraries/appbase | 2 +- libraries/eos-vm | 2 +- libraries/libfc/libraries/bn256 | 2 +- tests/abieos | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/appbase b/libraries/appbase index d7a7580dd7..b75b31e14f 160000 --- a/libraries/appbase +++ b/libraries/appbase @@ -1 +1 @@ -Subproject commit d7a7580dd7ff1d8e7979157abc869865a3a43220 +Subproject commit b75b31e14f966fa3de6246e120dcba36c6ce5264 diff --git a/libraries/eos-vm b/libraries/eos-vm index ee0b142058..33e91ebf90 160000 --- a/libraries/eos-vm +++ b/libraries/eos-vm @@ -1 +1 @@ -Subproject commit ee0b142058212073a78f71872dd54160ca69eb14 +Subproject commit 33e91ebf90088152477b7e7795cf5c871e70cb5c diff --git a/libraries/libfc/libraries/bn256 b/libraries/libfc/libraries/bn256 index b5adbb76d4..eae77bf03d 160000 --- a/libraries/libfc/libraries/bn256 +++ b/libraries/libfc/libraries/bn256 @@ -1 +1 @@ -Subproject commit b5adbb76d456e85385296a1388ba18f6f07d9d9e +Subproject commit eae77bf03dcf02579e967b0749ed5c175bd06c5a diff --git a/tests/abieos b/tests/abieos index ae6854ea7b..815fca5fb3 160000 --- a/tests/abieos +++ b/tests/abieos @@ -1 +1 @@ -Subproject commit ae6854ea7bad22f3dc4554a60124319af7e6cd30 +Subproject commit 815fca5fb3cd632eaffff098b14809a99229bebc From 84cc1f771731d0425ed7e97b335abf622afdb19d Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Tue, 19 Mar 2024 16:22:43 -0400 Subject: [PATCH 03/12] Revert "merge `origin/hotstuff_integration`" This reverts commit 9c703672558070972d5fd4bca9ac36f918dacc67. --- libraries/appbase | 2 +- libraries/eos-vm | 2 +- libraries/libfc/libraries/bn256 | 2 +- tests/abieos | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/appbase b/libraries/appbase index b75b31e14f..d7a7580dd7 160000 --- a/libraries/appbase +++ b/libraries/appbase @@ -1 +1 @@ -Subproject commit b75b31e14f966fa3de6246e120dcba36c6ce5264 +Subproject commit d7a7580dd7ff1d8e7979157abc869865a3a43220 diff --git a/libraries/eos-vm b/libraries/eos-vm index 33e91ebf90..ee0b142058 160000 --- a/libraries/eos-vm +++ b/libraries/eos-vm @@ -1 +1 @@ -Subproject commit 33e91ebf90088152477b7e7795cf5c871e70cb5c +Subproject commit ee0b142058212073a78f71872dd54160ca69eb14 diff --git a/libraries/libfc/libraries/bn256 b/libraries/libfc/libraries/bn256 index eae77bf03d..b5adbb76d4 160000 --- a/libraries/libfc/libraries/bn256 +++ b/libraries/libfc/libraries/bn256 @@ -1 +1 @@ -Subproject commit eae77bf03dcf02579e967b0749ed5c175bd06c5a +Subproject commit b5adbb76d456e85385296a1388ba18f6f07d9d9e diff --git a/tests/abieos b/tests/abieos index 815fca5fb3..ae6854ea7b 160000 --- a/tests/abieos +++ b/tests/abieos @@ -1 +1 @@ -Subproject commit 815fca5fb3cd632eaffff098b14809a99229bebc +Subproject commit ae6854ea7bad22f3dc4554a60124319af7e6cd30 From b4c445defd91b595de8a78f751d40137ff4bc3da Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Thu, 21 Mar 2024 10:10:33 -0400 Subject: [PATCH 04/12] Support optional computation and storage of two `action_digest` variants. --- libraries/chain/apply_context.cpp | 19 ++- libraries/chain/controller.cpp | 143 ++++++++++++------ .../eosio/chain/transaction_context.hpp | 3 +- libraries/chain/transaction_context.cpp | 1 + 4 files changed, 111 insertions(+), 55 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 0ab815970c..09db434fb1 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -186,7 +186,10 @@ void apply_context::exec_one() finalize_trace( trace, start ); - trx_context.executed_action_receipt_digests.emplace_back( trace.digest_legacy() ); + if (trx_context.executed_action_receipt_digests_l) + trx_context.executed_action_receipt_digests_l->emplace_back( trace.digest_legacy() ); + if (trx_context.executed_action_receipt_digests_s) + trx_context.executed_action_receipt_digests_s->emplace_back( trace.digest_savanna() ); if ( control.contracts_console() ) { print_debug(receiver, trace); @@ -218,17 +221,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() diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 851c20ae54..4c0b0c06e1 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,26 @@ struct building_block { // -------------------------------------------------------------------------------- struct building_block_common { using checksum_or_digests = std::variant; + enum class store_action_digests { legacy, savanna, both }; + 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; + std::optional action_receipt_digests_l; // legacy + std::optional action_receipt_digests_s; // savanna std::optional new_finalizer_policy; - building_block_common(const vector& new_protocol_feature_activations) : + building_block_common(const vector& new_protocol_feature_activations, store_action_digests sad) : new_protocol_feature_activations(new_protocol_feature_activations) - {} + { + if (sad == store_action_digests::legacy || sad == store_action_digests::both) + action_receipt_digests_l = digests_t{}; + + if (sad == store_action_digests::savanna || sad == store_action_digests::both) + action_receipt_digests_s = digests_t{}; + } bool is_protocol_feature_activated(const digest_type& digest, const flat_set& activated_features) const { if (activated_features.find(digest) != activated_features.end()) @@ -407,20 +416,39 @@ struct building_block { auto orig_trx_metas_size = pending_trx_metas.size(); auto orig_trx_receipt_digests_size = std::holds_alternative(trx_mroot_or_receipt_digests) ? std::get(trx_mroot_or_receipt_digests).size() : 0; - auto orig_action_receipt_digests_size = action_receipt_digests.size(); + auto orig_action_receipt_digests_l_size = action_receipt_digests_l ? action_receipt_digests_l->size() : 0; + auto orig_action_receipt_digests_s_size = action_receipt_digests_s ? action_receipt_digests_s->size() : 0; return [this, orig_trx_receipts_size, orig_trx_metas_size, orig_trx_receipt_digests_size, - orig_action_receipt_digests_size]() + orig_action_receipt_digests_l_size, + orig_action_receipt_digests_s_size]() { pending_trx_receipts.resize(orig_trx_receipts_size); pending_trx_metas.resize(orig_trx_metas_size); if (std::holds_alternative(trx_mroot_or_receipt_digests)) std::get(trx_mroot_or_receipt_digests).resize(orig_trx_receipt_digests_size); - action_receipt_digests.resize(orig_action_receipt_digests_size); + if (action_receipt_digests_l) + action_receipt_digests_l->resize(orig_action_receipt_digests_l_size); + if (action_receipt_digests_s) + action_receipt_digests_s->resize(orig_action_receipt_digests_s_size); }; } + + void initialize_action_receipts(transaction_context& trx_context) const { + if (action_receipt_digests_l) + trx_context.executed_action_receipt_digests_l = digests_t{}; + if (action_receipt_digests_s) + trx_context.executed_action_receipt_digests_s = digests_t{}; + } + + void store_trx_action_receipts(transaction_context& trx_context) { + if (action_receipt_digests_l) + fc::move_append( *action_receipt_digests_l, std::move(*trx_context.executed_action_receipt_digests_l) ); + if (action_receipt_digests_s) + fc::move_append( *action_receipt_digests_s, std::move(*trx_context.executed_action_receipt_digests_s) ); + } }; // -------------------------------------------------------------------------------- @@ -429,10 +457,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, + store_action_digests sad) + : building_block_common(new_protocol_feature_activations, sad), pending_block_header_state(prev.next(when, num_prev_blocks_to_confirm)) {} @@ -453,8 +482,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, store_action_digests sad) + : building_block_common(input.new_protocol_feature_activations, sad) , parent (parent) , timestamp(input.timestamp) , active_producer_authority{input.producer, @@ -491,12 +520,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, + building_block_common::store_action_digests::legacy)) {} // 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, building_block_common::store_action_digests::savanna)) {} bool is_legacy() const { return std::holds_alternative(v); } @@ -585,8 +615,20 @@ 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); + std::optional& action_receipt_digests_l() { + return std::visit([](auto& bb) -> std::optional& { return bb.action_receipt_digests_l; }, v); + } + + std::optional& action_receipt_digests_s() { + return std::visit([](auto& bb) -> std::optional& { return bb.action_receipt_digests_s; }, v); + } + + void initialize_action_receipts(transaction_context& trx_context) const { + return std::visit([&](const auto& bb) { return bb.initialize_action_receipts(trx_context); }, v); + } + + void store_trx_action_receipts(transaction_context& trx_context) { + return std::visit([&](auto& bb) { return bb.store_trx_action_receipts(trx_context); }, v); } const producer_authority_schedule& active_producers() const { @@ -660,7 +702,8 @@ 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_l = action_receipt_digests_l(); + auto& action_receipts_s = action_receipt_digests_s(); return std::visit( overloaded{ [&](building_block_legacy& bb) -> assembled_block { @@ -670,11 +713,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_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_l))); }}, trx_mroot_or_receipt_digests()); @@ -690,7 +733,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_l)} }; }, [&](building_block_if& bb) -> assembled_block { @@ -699,11 +742,11 @@ 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_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_s))); }}, trx_mroot_or_receipt_digests()); @@ -2174,6 +2217,10 @@ 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; + + auto& bb = std::get(pending->_block_stage); + bb.initialize_action_receipts(trx_context); + transaction_trace_ptr trace = trx_context.trace; auto handle_exception = [&](const auto& e) @@ -2193,8 +2240,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.store_trx_action_receipts(trx_context); // store action_digests for this trx into building_block trx_context.squash(); restore.cancel(); @@ -2342,6 +2389,9 @@ struct controller_impl { trx_context.enforce_whiteblacklist = gtrx.sender.empty() ? true : !sender_avoids_whitelist_blacklist_enforcement( gtrx.sender ); trace = trx_context.trace; + auto& bb = std::get(pending->_block_stage); + bb.initialize_action_receipts(trx_context); + auto handle_exception = [&](const auto& e) { cpu_time_to_bill_us = trx_context.update_billed_cpu_time( fc::time_point::now() ); @@ -2379,8 +2429,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.store_trx_action_receipts(trx_context); // store action_digests for this trx into building_block trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta ); @@ -2554,6 +2603,9 @@ struct controller_impl { trx_context.subjective_cpu_bill_us = subjective_cpu_bill_us; trace = trx_context.trace; + auto& bb = std::get(pending->_block_stage); + bb.initialize_action_receipts(trx_context); + auto handle_exception =[&](const auto& e) { trace->error_code = controller::convert_exception_to_error_code( e ); @@ -2589,7 +2641,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 +2657,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.store_trx_action_receipts(trx_context); // store action_digests for this trx into building_block + + 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() ) { @@ -3013,8 +3064,8 @@ struct controller_impl { // Calculate Merkel 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((*cb.action_receipt_digests_savanna)); auto new_head = std::make_shared(*head, action_mroot); @@ -3280,7 +3331,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/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp index 806e75d9dd..3f6803810e 100644 --- a/libraries/chain/include/eosio/chain/transaction_context.hpp +++ b/libraries/chain/include/eosio/chain/transaction_context.hpp @@ -141,7 +141,8 @@ namespace eosio { namespace chain { fc::time_point published; - deque executed_action_receipt_digests; + std::optional executed_action_receipt_digests_l; + std::optional executed_action_receipt_digests_s; flat_set bill_to_accounts; flat_set validate_ram_usage; diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 262d7995a7..a458200e58 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -47,6 +47,7 @@ namespace eosio { namespace chain { ,undo_session() ,trace(std::make_shared()) ,start(s) + ,executed_action_receipt_digests_l(digests_t{}) ,transaction_timer(std::move(tmr)) ,trx_type(type) ,net_usage(trace->net_usage) From 528c089e345c2bb48ec888a03a4849a8d4ab7fa8 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Thu, 21 Mar 2024 10:38:54 -0400 Subject: [PATCH 05/12] Construct `executed_action_receipt_digests_*` empty by default. --- libraries/chain/transaction_context.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index a458200e58..262d7995a7 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -47,7 +47,6 @@ namespace eosio { namespace chain { ,undo_session() ,trace(std::make_shared()) ,start(s) - ,executed_action_receipt_digests_l(digests_t{}) ,transaction_timer(std::move(tmr)) ,trx_type(type) ,net_usage(trace->net_usage) From 6cfb3fbda9fa8c83752c3ff98c58ee9f69b5f0d7 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Thu, 21 Mar 2024 14:10:15 -0400 Subject: [PATCH 06/12] Rename functions. --- libraries/chain/controller.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 4c0b0c06e1..405fdab18e 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -436,14 +436,14 @@ struct building_block { }; } - void initialize_action_receipts(transaction_context& trx_context) const { + void update_transaction_context_to_specify_needed_action_digests(transaction_context& trx_context) const { if (action_receipt_digests_l) trx_context.executed_action_receipt_digests_l = digests_t{}; if (action_receipt_digests_s) trx_context.executed_action_receipt_digests_s = digests_t{}; } - void store_trx_action_receipts(transaction_context& trx_context) { + void move_action_digests_from_transaction_context(transaction_context& trx_context) { if (action_receipt_digests_l) fc::move_append( *action_receipt_digests_l, std::move(*trx_context.executed_action_receipt_digests_l) ); if (action_receipt_digests_s) @@ -623,12 +623,12 @@ struct building_block { return std::visit([](auto& bb) -> std::optional& { return bb.action_receipt_digests_s; }, v); } - void initialize_action_receipts(transaction_context& trx_context) const { - return std::visit([&](const auto& bb) { return bb.initialize_action_receipts(trx_context); }, v); + void update_transaction_context_to_specify_needed_action_digests(transaction_context& trx_context) const { + return std::visit([&](const auto& bb) { return bb.update_transaction_context_to_specify_needed_action_digests(trx_context); }, v); } - void store_trx_action_receipts(transaction_context& trx_context) { - return std::visit([&](auto& bb) { return bb.store_trx_action_receipts(trx_context); }, v); + void move_action_digests_from_transaction_context(transaction_context& trx_context) { + return std::visit([&](auto& bb) { return bb.move_action_digests_from_transaction_context(trx_context); }, v); } const producer_authority_schedule& active_producers() const { @@ -2219,7 +2219,7 @@ struct controller_impl { trx_context.enforce_whiteblacklist = enforce_whiteblacklist; auto& bb = std::get(pending->_block_stage); - bb.initialize_action_receipts(trx_context); + bb.update_transaction_context_to_specify_needed_action_digests(trx_context); transaction_trace_ptr trace = trx_context.trace; @@ -2241,7 +2241,7 @@ struct controller_impl { trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::soft_fail, trx_context.billed_cpu_time_us, trace->net_usage ); - bb.store_trx_action_receipts(trx_context); // store action_digests for this trx into building_block + bb.move_action_digests_from_transaction_context(trx_context); // store action_digests for this trx into building_block trx_context.squash(); restore.cancel(); @@ -2390,7 +2390,7 @@ struct controller_impl { trace = trx_context.trace; auto& bb = std::get(pending->_block_stage); - bb.initialize_action_receipts(trx_context); + bb.update_transaction_context_to_specify_needed_action_digests(trx_context); auto handle_exception = [&](const auto& e) { @@ -2429,7 +2429,7 @@ struct controller_impl { trx_context.billed_cpu_time_us, trace->net_usage ); - bb.store_trx_action_receipts(trx_context); // store action_digests for this trx into building_block + bb.move_action_digests_from_transaction_context(trx_context); // store action_digests for this trx into building_block trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta ); @@ -2604,7 +2604,7 @@ struct controller_impl { trace = trx_context.trace; auto& bb = std::get(pending->_block_stage); - bb.initialize_action_receipts(trx_context); + bb.update_transaction_context_to_specify_needed_action_digests(trx_context); auto handle_exception =[&](const auto& e) { @@ -2657,7 +2657,7 @@ struct controller_impl { } if ( !trx->is_read_only() ) { - bb.store_trx_action_receipts(trx_context); // store action_digests for this trx into building_block + bb.move_action_digests_from_transaction_context(trx_context); // store action_digests for this trx into building_block if ( !trx->is_dry_run() ) { // call the accept signal but only once for this transaction From 2799ca72b1bbe42092c70384672fb329ed24b0a8 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 22 Mar 2024 10:22:46 -0400 Subject: [PATCH 07/12] Use struct to store two versions of `action_receipt_digests` --- benchmark/bls.cpp | 3 +- libraries/chain/apply_context.cpp | 8 +- libraries/chain/controller.cpp | 111 ++++++------------ .../eosio/chain/incremental_merkle.hpp | 4 +- .../chain/include/eosio/chain/merkle.hpp | 4 +- .../eosio/chain/transaction_context.hpp | 44 ++++++- libraries/chain/merkle.cpp | 4 +- libraries/chain/transaction_context.cpp | 2 + 8 files changed, 91 insertions(+), 89 deletions(-) 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 09db434fb1..473c137ffd 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -186,10 +186,10 @@ void apply_context::exec_one() finalize_trace( trace, start ); - if (trx_context.executed_action_receipt_digests_l) - trx_context.executed_action_receipt_digests_l->emplace_back( trace.digest_legacy() ); - if (trx_context.executed_action_receipt_digests_s) - trx_context.executed_action_receipt_digests_s->emplace_back( trace.digest_savanna() ); + if (trx_context.executed_action_receipts.digests_l) + trx_context.executed_action_receipts.digests_l->emplace_back( trace.digest_legacy() ); + if (trx_context.executed_action_receipts.digests_s) + trx_context.executed_action_receipts.digests_s->emplace_back( trace.digest_savanna() ); if ( control.contracts_console() ) { print_debug(receiver, trace); diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 405fdab18e..54993a365e 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -381,25 +381,20 @@ struct building_block { // -------------------------------------------------------------------------------- struct building_block_common { using checksum_or_digests = std::variant; - enum class store_action_digests { legacy, savanna, both }; 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{}}; - std::optional action_receipt_digests_l; // legacy - std::optional action_receipt_digests_s; // savanna + action_digests_t action_receipt_digests; std::optional new_finalizer_policy; - building_block_common(const vector& new_protocol_feature_activations, store_action_digests sad) : - new_protocol_feature_activations(new_protocol_feature_activations) + building_block_common(const vector& new_protocol_feature_activations, + action_digests_t::store_which_t sad) : + new_protocol_feature_activations(new_protocol_feature_activations), + action_receipt_digests(sad) { - if (sad == store_action_digests::legacy || sad == store_action_digests::both) - action_receipt_digests_l = digests_t{}; - - if (sad == store_action_digests::savanna || sad == store_action_digests::both) - action_receipt_digests_s = digests_t{}; } bool is_protocol_feature_activated(const digest_type& digest, const flat_set& activated_features) const { @@ -416,39 +411,20 @@ struct building_block { auto orig_trx_metas_size = pending_trx_metas.size(); auto orig_trx_receipt_digests_size = std::holds_alternative(trx_mroot_or_receipt_digests) ? std::get(trx_mroot_or_receipt_digests).size() : 0; - auto orig_action_receipt_digests_l_size = action_receipt_digests_l ? action_receipt_digests_l->size() : 0; - auto orig_action_receipt_digests_s_size = action_receipt_digests_s ? action_receipt_digests_s->size() : 0; + auto orig_action_receipt_digests_size = action_receipt_digests.size(); return [this, orig_trx_receipts_size, orig_trx_metas_size, orig_trx_receipt_digests_size, - orig_action_receipt_digests_l_size, - orig_action_receipt_digests_s_size]() + orig_action_receipt_digests_size]() { pending_trx_receipts.resize(orig_trx_receipts_size); pending_trx_metas.resize(orig_trx_metas_size); if (std::holds_alternative(trx_mroot_or_receipt_digests)) std::get(trx_mroot_or_receipt_digests).resize(orig_trx_receipt_digests_size); - if (action_receipt_digests_l) - action_receipt_digests_l->resize(orig_action_receipt_digests_l_size); - if (action_receipt_digests_s) - action_receipt_digests_s->resize(orig_action_receipt_digests_s_size); + action_receipt_digests.resize(orig_action_receipt_digests_size); }; } - - void update_transaction_context_to_specify_needed_action_digests(transaction_context& trx_context) const { - if (action_receipt_digests_l) - trx_context.executed_action_receipt_digests_l = digests_t{}; - if (action_receipt_digests_s) - trx_context.executed_action_receipt_digests_s = digests_t{}; - } - - void move_action_digests_from_transaction_context(transaction_context& trx_context) { - if (action_receipt_digests_l) - fc::move_append( *action_receipt_digests_l, std::move(*trx_context.executed_action_receipt_digests_l) ); - if (action_receipt_digests_s) - fc::move_append( *action_receipt_digests_s, std::move(*trx_context.executed_action_receipt_digests_s) ); - } }; // -------------------------------------------------------------------------------- @@ -460,7 +436,7 @@ struct building_block { block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector& new_protocol_feature_activations, - store_action_digests sad) + action_digests_t::store_which_t sad) : building_block_common(new_protocol_feature_activations, sad), pending_block_header_state(prev.next(when, num_prev_blocks_to_confirm)) {} @@ -482,7 +458,7 @@ 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, store_action_digests sad) + building_block_if(const block_state& parent, const building_block_input& input, action_digests_t::store_which_t sad) : building_block_common(input.new_protocol_feature_activations, sad) , parent (parent) , timestamp(input.timestamp) @@ -521,12 +497,12 @@ struct building_block { 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, - building_block_common::store_action_digests::legacy)) + 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, building_block_common::store_action_digests::savanna)) + v(building_block_if(prev, input, action_digests_t::store_which_t::savanna)) {} bool is_legacy() const { return std::holds_alternative(v); } @@ -615,20 +591,8 @@ struct building_block { [](auto& bb) -> building_block_common::checksum_or_digests& { return bb.trx_mroot_or_receipt_digests; }, v); } - std::optional& action_receipt_digests_l() { - return std::visit([](auto& bb) -> std::optional& { return bb.action_receipt_digests_l; }, v); - } - - std::optional& action_receipt_digests_s() { - return std::visit([](auto& bb) -> std::optional& { return bb.action_receipt_digests_s; }, v); - } - - void update_transaction_context_to_specify_needed_action_digests(transaction_context& trx_context) const { - return std::visit([&](const auto& bb) { return bb.update_transaction_context_to_specify_needed_action_digests(trx_context); }, v); - } - - void move_action_digests_from_transaction_context(transaction_context& trx_context) { - return std::visit([&](auto& bb) { return bb.move_action_digests_from_transaction_context(trx_context); }, 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 { @@ -702,8 +666,7 @@ struct building_block { bool validating, std::optional validating_qc_data, const block_state_ptr& validating_bsp) { - auto& action_receipts_l = action_receipt_digests_l(); - auto& action_receipts_s = action_receipt_digests_s(); + auto& action_receipts = action_receipt_digests(); return std::visit( overloaded{ [&](building_block_legacy& bb) -> assembled_block { @@ -713,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_l)); }); + 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_l))); + return std::make_pair(trx_checksum, legacy_merkle(std::move(*action_receipts.digests_l))); }}, trx_mroot_or_receipt_digests()); @@ -733,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_l)} + std::move(bb.action_receipt_digests.digests_s)} }; }, [&](building_block_if& bb) -> assembled_block { @@ -742,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_s)); }); + 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_s))); + return std::make_pair(trx_checksum, calculate_merkle(std::move(*action_receipts.digests_s))); }}, trx_mroot_or_receipt_digests()); @@ -2204,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); @@ -2218,9 +2184,6 @@ struct controller_impl { trx_context.billed_cpu_time_us = billed_cpu_time_us; trx_context.enforce_whiteblacklist = enforce_whiteblacklist; - auto& bb = std::get(pending->_block_stage); - bb.update_transaction_context_to_specify_needed_action_digests(trx_context); - transaction_trace_ptr trace = trx_context.trace; auto handle_exception = [&](const auto& e) @@ -2241,7 +2204,7 @@ struct controller_impl { trace->receipt = push_receipt( gtrx.trx_id, transaction_receipt::soft_fail, trx_context.billed_cpu_time_us, trace->net_usage ); - bb.move_action_digests_from_transaction_context(trx_context); // store action_digests for this trx into building_block + bb.action_receipt_digests().append(std::move(trx_context.executed_action_receipts)); trx_context.squash(); restore.cancel(); @@ -2378,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; @@ -2389,9 +2353,6 @@ struct controller_impl { trx_context.enforce_whiteblacklist = gtrx.sender.empty() ? true : !sender_avoids_whitelist_blacklist_enforcement( gtrx.sender ); trace = trx_context.trace; - auto& bb = std::get(pending->_block_stage); - bb.update_transaction_context_to_specify_needed_action_digests(trx_context); - auto handle_exception = [&](const auto& e) { cpu_time_to_bill_us = trx_context.update_billed_cpu_time( fc::time_point::now() ); @@ -2429,7 +2390,7 @@ struct controller_impl { trx_context.billed_cpu_time_us, trace->net_usage ); - bb.move_action_digests_from_transaction_context(trx_context); // store action_digests for this trx into building_block + bb.action_receipt_digests().append(std::move(trx_context.executed_action_receipts)); trace->account_ram_delta = account_delta( gtrx.payer, trx_removal_ram_delta ); @@ -2590,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; } @@ -2603,9 +2567,6 @@ struct controller_impl { trx_context.subjective_cpu_bill_us = subjective_cpu_bill_us; trace = trx_context.trace; - auto& bb = std::get(pending->_block_stage); - bb.update_transaction_context_to_specify_needed_action_digests(trx_context); - auto handle_exception =[&](const auto& e) { trace->error_code = controller::convert_exception_to_error_code( e ); @@ -2657,7 +2618,7 @@ struct controller_impl { } if ( !trx->is_read_only() ) { - bb.move_action_digests_from_transaction_context(trx_context); // store action_digests for this trx into building_block + 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 @@ -2965,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) { @@ -3062,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_savanna); - auto action_mroot = calculate_merkle((*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); 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/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp index 3f6803810e..81a9855017 100644 --- a/libraries/chain/include/eosio/chain/transaction_context.hpp +++ b/libraries/chain/include/eosio/chain/transaction_context.hpp @@ -33,6 +33,45 @@ 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)); + } + + 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 +82,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,9 +180,7 @@ namespace eosio { namespace chain { fc::time_point published; - - std::optional executed_action_receipt_digests_l; - std::optional executed_action_receipt_digests_s; + 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..d03b539f88 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -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 sad, 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(sad) ,transaction_timer(std::move(tmr)) ,trx_type(type) ,net_usage(trace->net_usage) From 5e895c4dafb7c82f73346ee38bc730ecf8eec529 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 22 Mar 2024 10:30:34 -0400 Subject: [PATCH 08/12] Simplify two namespaces. --- libraries/chain/apply_context.cpp | 4 ++-- libraries/chain/transaction_context.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 473c137ffd..c323a7fbf9 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()) { @@ -1108,4 +1108,4 @@ bool apply_context::should_use_eos_vm_oc()const { } -} } /// eosio::chain +} /// eosio::chain diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index d03b539f88..76e9354af0 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) { @@ -830,4 +830,4 @@ namespace eosio { namespace chain { } -} } /// eosio::chain +} /// eosio::chain From 7a22f7ec5048b84eb7fe56b86ce7b1f2208f28a3 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 22 Mar 2024 10:35:48 -0400 Subject: [PATCH 09/12] rename `sad` into `store_which`. --- libraries/chain/controller.cpp | 12 ++++++------ libraries/chain/transaction_context.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 54993a365e..5cf44caecf 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -391,9 +391,9 @@ struct building_block { std::optional new_finalizer_policy; building_block_common(const vector& new_protocol_feature_activations, - action_digests_t::store_which_t sad) : + action_digests_t::store_which_t store_which) : new_protocol_feature_activations(new_protocol_feature_activations), - action_receipt_digests(sad) + action_receipt_digests(store_which) { } @@ -436,8 +436,8 @@ struct building_block { block_timestamp_type when, uint16_t num_prev_blocks_to_confirm, const vector& new_protocol_feature_activations, - action_digests_t::store_which_t sad) - : building_block_common(new_protocol_feature_activations, sad), + 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)) {} @@ -458,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, action_digests_t::store_which_t sad) - : building_block_common(input.new_protocol_feature_activations, sad) + 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, diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 76e9354af0..03cfb55d32 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -39,7 +39,7 @@ namespace eosio::chain { const packed_transaction& t, const transaction_id_type& trx_id, transaction_checktime_timer&& tmr, - action_digests_t::store_which_t sad, + action_digests_t::store_which_t store_which, fc::time_point s, transaction_metadata::trx_type type) :control(c) @@ -48,7 +48,7 @@ namespace eosio::chain { ,undo_session() ,trace(std::make_shared()) ,start(s) - ,executed_action_receipts(sad) + ,executed_action_receipts(store_which) ,transaction_timer(std::move(tmr)) ,trx_type(type) ,net_usage(trace->net_usage) From 26f72bd21b56a5d6fa6b1c44d256836778fab0a9 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 22 Mar 2024 10:57:52 -0400 Subject: [PATCH 10/12] Encapsulate use of `action_digests_t` better. --- libraries/chain/apply_context.cpp | 5 +---- .../chain/include/eosio/chain/transaction_context.hpp | 7 +++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index c323a7fbf9..cc7f44f9f0 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -186,10 +186,7 @@ void apply_context::exec_one() finalize_trace( trace, start ); - if (trx_context.executed_action_receipts.digests_l) - trx_context.executed_action_receipts.digests_l->emplace_back( trace.digest_legacy() ); - if (trx_context.executed_action_receipts.digests_s) - trx_context.executed_action_receipts.digests_s->emplace_back( trace.digest_savanna() ); + trx_context.executed_action_receipts.compute_and_append_digests_from(trace); if ( control.contracts_console() ) { print_debug(receiver, trace); diff --git a/libraries/chain/include/eosio/chain/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp index 81a9855017..525794e929 100644 --- a/libraries/chain/include/eosio/chain/transaction_context.hpp +++ b/libraries/chain/include/eosio/chain/transaction_context.hpp @@ -53,6 +53,13 @@ namespace eosio { namespace chain { 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; From 1b92f0236f01ff6a5ddbd7c84031a9620b57f045 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 22 Mar 2024 11:26:38 -0400 Subject: [PATCH 11/12] Move back `finalize_trace` after the digest computation. --- libraries/chain/apply_context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index cc7f44f9f0..aba88fbc61 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -184,10 +184,10 @@ void apply_context::exec_one() r.auth_sequence[auth.actor] = next_auth_sequence( auth.actor ); } - finalize_trace( trace, start ); - trx_context.executed_action_receipts.compute_and_append_digests_from(trace); + finalize_trace( trace, start ); + if ( control.contracts_console() ) { print_debug(receiver, trace); } From cc657914ba1c3b7f808fdcbb38cc4f3720c04b06 Mon Sep 17 00:00:00 2001 From: greg7mdp Date: Fri, 22 Mar 2024 12:00:50 -0400 Subject: [PATCH 12/12] Remove outdated comment. --- libraries/chain/block_header_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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,