Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IF: Create a new action receipt digest for Savanna blocks and move the digest computation to action_trace #2326

Merged
merged 13 commits into from
Mar 25, 2024
Merged
3 changes: 2 additions & 1 deletion benchmark/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ struct interface_in_benchmark {
// build transaction context from the packed transaction
timer = std::make_unique<platform_timer>();
trx_timer = std::make_unique<transaction_checktime_timer>(*timer);
trx_ctx = std::make_unique<transaction_context>(*chain->control.get(), *ptrx, ptrx->id(), std::move(*trx_timer));
trx_ctx = std::make_unique<transaction_context>(*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
Expand Down
20 changes: 10 additions & 10 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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);
heifner marked this conversation as resolved.
Show resolved Hide resolved

finalize_trace( trace, start );

Expand Down Expand Up @@ -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 );
}
heifner marked this conversation as resolved.
Show resolved Hide resolved
}

} /// exec()
Expand Down Expand Up @@ -1105,4 +1105,4 @@ bool apply_context::should_use_eos_vm_oc()const {
}


} } /// eosio::chain
} /// eosio::chain
2 changes: 1 addition & 1 deletion libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
110 changes: 61 additions & 49 deletions libraries/chain/controller.cpp

Large diffs are not rendered by default.

17 changes: 3 additions & 14 deletions libraries/chain/include/eosio/chain/action_receipt.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

#include <eosio/chain/types.hpp>
#include <eosio/chain/action.hpp>

namespace eosio { namespace chain {
namespace eosio::chain {

/**
* For each action dispatched this receipt is generated
Expand All @@ -15,20 +16,8 @@ namespace eosio { namespace chain {
flat_map<account_name,uint64_t> 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) )
4 changes: 2 additions & 2 deletions libraries/chain/include/eosio/chain/incremental_merkle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/include/eosio/chain/merkle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<digest_type> ids );
digest_type legacy_merkle( deque<digest_type>&& ids );

/**
* Calculates the merkle root of a set of digests. Does not manipulate the digests.
*/
digest_type calculate_merkle( deque<digest_type> ids );
digest_type calculate_merkle( deque<digest_type>&& ids );

} } /// eosio::chain
41 changes: 39 additions & 2 deletions libraries/chain/include/eosio/chain/trace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <eosio/chain/action_receipt.hpp>
#include <eosio/chain/block.hpp>

namespace eosio { namespace chain {
namespace eosio::chain {

struct account_delta {
account_delta( const account_name& n, int64_t d):account(n),delta(d){}
Expand Down Expand Up @@ -45,6 +45,43 @@ namespace eosio { namespace chain {
std::optional<fc::exception> except;
std::optional<uint64_t> error_code;
std::vector<char> 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);

{
linh2931 marked this conversation as resolved.
Show resolved Hide resolved
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 {
Expand Down Expand Up @@ -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) )
Expand Down
50 changes: 48 additions & 2 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_t> digests_l; // legacy
std::optional<digests_t> 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_t, size_t> size() const {
return { digests_l ? digests_l->size() : 0, digests_s ? digests_s->size() : 0 };
}

void resize(std::pair<size_t, size_t> 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);
Expand All @@ -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();
Expand Down Expand Up @@ -140,8 +187,7 @@ namespace eosio { namespace chain {

fc::time_point published;


deque<digest_type> executed_action_receipt_digests;
action_digests_t executed_action_receipts;
flat_set<account_name> bill_to_accounts;
flat_set<account_name> validate_ram_usage;

Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/merkle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ bool is_canonical_right(const digest_type& val) {
}


digest_type legacy_merkle(deque<digest_type> ids) {
digest_type legacy_merkle(deque<digest_type>&& ids) {
if( 0 == ids.size() ) { return digest_type(); }

while( ids.size() > 1 ) {
Expand All @@ -49,7 +49,7 @@ digest_type legacy_merkle(deque<digest_type> ids) {
return ids.front();
}

digest_type calculate_merkle( deque<digest_type> ids ) {
digest_type calculate_merkle( deque<digest_type>&& ids ) {
if( 0 == ids.size() ) { return digest_type(); }

while( ids.size() > 1 ) {
Expand Down
6 changes: 4 additions & 2 deletions libraries/chain/transaction_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include <chrono>

namespace eosio { namespace chain {
namespace eosio::chain {

transaction_checktime_timer::transaction_checktime_timer(platform_timer& timer)
: expired(timer.expired), _timer(timer) {
Expand Down Expand Up @@ -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)
Expand All @@ -47,6 +48,7 @@ namespace eosio { namespace chain {
,undo_session()
,trace(std::make_shared<transaction_trace>())
,start(s)
,executed_action_receipts(store_which)
,transaction_timer(std::move(tmr))
,trx_type(type)
,net_usage(trace->net_usage)
Expand Down Expand Up @@ -828,4 +830,4 @@ namespace eosio { namespace chain {
}


} } /// eosio::chain
} /// eosio::chain
15 changes: 8 additions & 7 deletions unittests/api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
14 changes: 8 additions & 6 deletions unittests/restart_chain_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Loading