Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
bc78038
Update `peer_keys_db` to use the ro transaction result.
greg7mdp Mar 28, 2025
696f02b
Implement `get_top_producer_keys` and factorize dup. code.
greg7mdp Mar 31, 2025
dba098c
Add code to test the ro action `getpeerkeys`
greg7mdp Mar 31, 2025
63731f2
Make the `getpeerkeys` return type nicer.
greg7mdp Mar 31, 2025
b1e64cc
Checkin state before trying to avoid table changes in `~system_contra…
greg7mdp Apr 1, 2025
00b9582
To avoid the non-readonly destructor, implement `getpeerkeys` in sepa…
greg7mdp Apr 1, 2025
ac600cf
Update `getpeerkeys` result type to match system contracts.
greg7mdp Apr 3, 2025
4b9364a
Update peer keys on `accepted_block`.
greg7mdp Apr 3, 2025
328d2fe
Undo whitespace change
greg7mdp Apr 3, 2025
1bd34ed
implement `get_peer_info`
greg7mdp Apr 3, 2025
70edeab
Need to find the right location in the code to call `update_peer_keys`
greg7mdp Apr 3, 2025
b07e4d5
Merge branch 'main' of github.com:AntelopeIO/spring into gh_1183_3
greg7mdp Apr 4, 2025
27075d6
Update contracts and tests to match `eos-system-contracts`
greg7mdp Apr 4, 2025
b58e9c1
Remove outdated comment.
greg7mdp Apr 4, 2025
bce86eb
Merge branch 'main' of github.com:AntelopeIO/spring into gh_1183_3
greg7mdp Apr 4, 2025
383be15
GH-1170 Also interrupt speculative trxs
heifner Apr 7, 2025
8fc5690
GH-1170 Rename interrupt_apply_block_transaction() to interrupt_trans…
heifner Apr 7, 2025
77c2123
Push wasm file compiled with cdt @ commit #b949569188f9d8bfaec8d40fa0…
greg7mdp Apr 7, 2025
486a383
GH-1170 Use debug log since this now happens rather often
heifner Apr 8, 2025
e52a9b5
GH-1170 Call interrupt when receiving a new head block
heifner Apr 8, 2025
e77158a
GH-1170 Call receive_block before process_block as receive_block can …
heifner Apr 8, 2025
7e70919
Move `update_peer_keys` when we have a `building_block.
greg7mdp Apr 8, 2025
8f36e60
Merge branch 'main' of github.com:AntelopeIO/spring into gh_1183_3
greg7mdp Apr 8, 2025
bdbe42f
Call ro action from producer_plugin.
greg7mdp Apr 8, 2025
d440317
test
greg7mdp Apr 8, 2025
b3f3693
Be tolerant of the `getpeerkeys` action not being available in some i…
greg7mdp Apr 8, 2025
9c783fd
Update `push_transaction` params, ignore exceptions.
greg7mdp Apr 8, 2025
2052737
Merge branch 'GH-1323-interrupt-read-only-trx' into GH-1170-interrupt…
heifner Apr 8, 2025
17aa0db
GH-1170 Only interrupt after savanna active as interrupt during trans…
heifner Apr 9, 2025
ba2c739
GH-1170 Improve log message
heifner Apr 9, 2025
f1faaf8
Merge branch 'GH-1323-interrupt-read-only-trx' into GH-1170-interrupt…
heifner Apr 10, 2025
611e264
Merge branch 'GH-1323-interrupt-read-only-trx' into GH-1170-interrupt…
heifner Apr 11, 2025
f694d61
Update a couple comments.
greg7mdp Apr 11, 2025
68bc98b
Merge branch 'main' into gh_1183_3
greg7mdp Apr 11, 2025
b18a03d
Merge branch 'GH-1323-interrupt-read-only-trx' into GH-1170-interrupt…
heifner Apr 14, 2025
6342b5d
Update comments referring to top-50 producers.
greg7mdp Apr 14, 2025
406d928
Add comment in `peer_keys` test contract.
greg7mdp Apr 14, 2025
e80a6e5
Remove outdated comment.
greg7mdp Apr 14, 2025
fab51ad
Merge branch 'main' into GH-1170-interrupt-spec-trx
heifner Apr 14, 2025
ca9c2f1
Allow a max of 20ms for getpeerkeys
greg7mdp Apr 14, 2025
53770de
Merge branch 'main' of github.com:AntelopeIO/spring into gh_1183_3
greg7mdp Apr 14, 2025
a42f0b8
Merge branch 'gh_1183_3' of github.com:AntelopeIO/spring into gh_1183_3
greg7mdp Apr 14, 2025
9ca911a
Give `run_readonly_transactions` a more descriptive name.
greg7mdp Apr 14, 2025
a2cc5aa
GH-1344 Disable pause production since test needs to rely on producti…
heifner Apr 14, 2025
59e9336
rename function to `update_peer_keys`.
greg7mdp Apr 14, 2025
de28545
Remove producers not in top-50 anymore from `_peer_info_map`.
greg7mdp Apr 14, 2025
48f5064
Merge pull request #1369 from AntelopeIO/GH-1344-test-fix-1.1
heifner Apr 16, 2025
93c0f9c
Merge remote-tracking branch 'spring/release/1.1' into GH-1344-test-f…
heifner Apr 16, 2025
b5949aa
GH-1170 remove duplicate code
heifner Apr 16, 2025
c1ac619
Merge pull request #1383 from AntelopeIO/GH-1344-test-fix-main
heifner Apr 16, 2025
f2e0543
Address PR comments.
greg7mdp Apr 16, 2025
88a9855
Merge branch 'main' of github.com:AntelopeIO/spring into gh_1183_3
greg7mdp Apr 16, 2025
99febb5
Merge pull request #1316 from AntelopeIO/gh_1183_3
greg7mdp Apr 16, 2025
2f236ca
Merge pull request #1330 from AntelopeIO/GH-1170-interrupt-spec-trx
heifner Apr 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 83 additions & 29 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,57 @@ struct controller_impl {
apply_handlers[receiver][make_pair(contract,action)] = v;
}

void set_trx_expiration(signed_transaction& trx) {
if (is_builtin_activated(builtin_protocol_feature_t::no_duplicate_deferred_id)) {
trx.expiration = time_point_sec();
trx.ref_block_num = 0;
trx.ref_block_prefix = 0;
} else {
trx.expiration = time_point_sec{
pending_block_time() + fc::microseconds(999'999)}; // Round up to nearest second to avoid appearing expired
trx.set_reference_block(chain_head.id());
}
}

getpeerkeys_res_t get_top_producer_keys(fc::time_point deadline) {
try {
auto get_getpeerkeys_transaction = [&]() {
auto perms = vector<permission_level>{};
action act(perms, config::system_account_name, "getpeerkeys"_n, {});
signed_transaction trx;

trx.actions.emplace_back(std::move(act));
set_trx_expiration(trx);
return trx;
};

auto metadata = transaction_metadata::create_no_recover_keys(
std::make_shared<packed_transaction>(get_getpeerkeys_transaction()),
transaction_metadata::trx_type::read_only);

// allow a max of 20ms for getpeerkeys
auto trace = push_transaction(metadata, deadline, fc::milliseconds(20), 0, false, 0);

if( trace->except_ptr )
std::rethrow_exception(trace->except_ptr);
if( trace->except)
throw *trace->except;
getpeerkeys_res_t res;
if (!trace->action_traces.empty()) {
const auto& act_trace = trace->action_traces[0];
const auto& retval = act_trace.return_value;
if (!retval.empty()) {
// in some tests, the system contract is not set and the return value is empty.
fc::datastream<const char*> ds(retval.data(), retval.size());
fc::raw::unpack(ds, res);
}
}

return res;
}
FC_LOG_AND_RETHROW()
}

controller_impl( const controller::config& cfg, controller& s, protocol_feature_set&& pfs, const chain_id_type& chain_id )
:rnh(),
self(s),
Expand Down Expand Up @@ -1322,9 +1373,6 @@ struct controller_impl {
const auto& [ block, id] = t;
wasmif.current_lib(block->block_num());
vote_processor.notify_lib(block->block_num());

// update peer public keys from chainbase db
peer_keys_db.update_peer_keys(self, block->block_num());
});

#define SET_APP_HANDLER( receiver, contract, action) \
Expand Down Expand Up @@ -2623,14 +2671,7 @@ struct controller_impl {
// Deliver onerror action containing the failed deferred transaction directly back to the sender.
etrx.actions.emplace_back( vector<permission_level>{{gtrx.sender, config::active_name}},
onerror( gtrx.sender_id, gtrx.packed_trx.data(), gtrx.packed_trx.size() ) );
if( is_builtin_activated( builtin_protocol_feature_t::no_duplicate_deferred_id ) ) {
etrx.expiration = time_point_sec();
etrx.ref_block_num = 0;
etrx.ref_block_prefix = 0;
} else {
etrx.expiration = time_point_sec{pending_block_time() + fc::microseconds(999'999)}; // Round up to nearest second to avoid appearing expired
etrx.set_reference_block( chain_head.id() );
}
set_trx_expiration(etrx);

auto& bb = std::get<building_block>(pending->_block_stage);

Expand Down Expand Up @@ -3339,9 +3380,20 @@ struct controller_impl {
}

guard_pending.cancel();

return onblock_trace;
} /// start_block

void update_peer_keys(fc::time_point deadline) {
try {
// update peer public keys from chainbase db using a readonly trx
auto block_num = chain_head.block_num();
if (block_num % 120 == 0) { // update once/minute
peer_keys_db.update_peer_keys(get_top_producer_keys(deadline));
}
} FC_LOG_AND_DROP()
}

void assemble_block(bool validating, std::optional<qc_data_t> validating_qc_data, const block_state_ptr& validating_bsp)
{
EOS_ASSERT( pending, block_validate_exception, "it is not valid to finalize when there is no pending block");
Expand Down Expand Up @@ -4554,12 +4606,13 @@ struct controller_impl {
return applied_trxs;
}

void interrupt_apply_block_transaction() {
// Only interrupt transaction if applying a block. Speculative trxs already have a deadline set so they
// have limited run time already. This is to allow killing a long-running transaction in a block being
// validated.
if (!replaying && applying_block) {
ilog("Interrupting apply block");
void interrupt_transaction() {
// Do not interrupt during replay. ctrl-c during replay is handled at block boundaries.
// Interrupt both speculative trxs and trxs while applying a block.
// This is to allow killing a long-running transaction in a block being validated during apply block.
// This also allows killing a trx when a block is received to prioritize block validation.
if (!replaying) {
dlog("Interrupting trx...");
main_thread_timer.interrupt_timer();
}
}
Expand Down Expand Up @@ -4788,14 +4841,7 @@ struct controller_impl {

signed_transaction trx;
trx.actions.emplace_back(std::move(on_block_act));
if( is_builtin_activated( builtin_protocol_feature_t::no_duplicate_deferred_id ) ) {
trx.expiration = time_point_sec();
trx.ref_block_num = 0;
trx.ref_block_prefix = 0;
} else {
trx.expiration = time_point_sec{pending_block_time() + fc::microseconds(999'999)}; // Round up to nearest second to avoid appearing expired
trx.set_reference_block( chain_head.id() );
}
set_trx_expiration(trx);

return trx;
}
Expand Down Expand Up @@ -5293,6 +5339,10 @@ transaction_trace_ptr controller::start_block( block_timestamp_type when,
bs, std::optional<block_id_type>(), deadline );
}

void controller::update_peer_keys(fc::time_point deadline) {
my->update_peer_keys(deadline);
}

void controller::assemble_and_complete_block( const signer_callback_type& signer_callback ) {
validate_db_available_size();

Expand Down Expand Up @@ -5338,8 +5388,8 @@ deque<transaction_metadata_ptr> controller::abort_block() {
return my->abort_block();
}

void controller::interrupt_apply_block_transaction() {
my->interrupt_apply_block_transaction();
void controller::interrupt_transaction() {
my->interrupt_transaction();
}

boost::asio::io_context& controller::get_thread_pool() {
Expand Down Expand Up @@ -5793,8 +5843,12 @@ void controller::set_peer_keys_retrieval_active(bool active) {
my->peer_keys_db.set_active(active);
}

std::optional<public_key_type> controller::get_peer_key(name n) const {
return my->peer_keys_db.get_peer_key(n);
peer_info_t controller::get_peer_info(name n) const {
return my->peer_keys_db.get_peer_info(n);
}

getpeerkeys_res_t controller::get_top_producer_keys(fc::time_point deadline) {
return my->get_top_producer_keys(deadline);
}

db_read_mode controller::get_read_mode()const {
Expand Down
25 changes: 23 additions & 2 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,23 @@ namespace eosio::chain {
class resource_limits_manager;
};

// vector, sorted by rank, of the top-50 producers by `total_votes` (whether
// active or not) and their peer key if populated on-chain.
// -------------------------------------------------------------------------
struct peerkeys_t {
name producer_name;
std::optional<public_key_type> peer_key;
};
using getpeerkeys_res_t = std::vector<peerkeys_t>;

struct peer_info_t {
// rank by `total_votes` of all producers, active or not, may not match schedule rank
uint32_t rank{std::numeric_limits<uint32_t>::max()};
std::optional<public_key_type> key;

bool operator==(const peer_info_t&) const = default;
};

struct controller_impl;
using chainbase::database;
using chainbase::pinnable_mapped_file;
Expand Down Expand Up @@ -209,7 +226,7 @@ namespace eosio::chain {
deque<transaction_metadata_ptr> abort_block();

/// Expected to be called from signal handler, or producer_plugin
void interrupt_apply_block_transaction();
void interrupt_transaction();

/**
*
Expand All @@ -230,6 +247,7 @@ namespace eosio::chain {
void assemble_and_complete_block( const signer_callback_type& signer_callback );
void sign_block( const signer_callback_type& signer_callback );
void commit_block();
void update_peer_keys(fc::time_point deadline);
void testing_allow_voting(bool val);
bool get_testing_allow_voting_flag();
void set_async_voting(async_t val);
Expand Down Expand Up @@ -428,7 +446,8 @@ namespace eosio::chain {
chain_id_type get_chain_id()const;

void set_peer_keys_retrieval_active(bool active);
std::optional<public_key_type> get_peer_key(name n) const; // thread safe
peer_info_t get_peer_info(name n) const; // thread safe
getpeerkeys_res_t get_top_producer_keys(fc::time_point deadline); // must be called from main thread

// thread safe
db_read_mode get_read_mode()const;
Expand Down Expand Up @@ -518,3 +537,5 @@ namespace eosio::chain {
}; // controller

} /// eosio::chain

FC_REFLECT(eosio::chain::peerkeys_t, (producer_name)(peer_key))
26 changes: 13 additions & 13 deletions libraries/chain/include/eosio/chain/peer_keys_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@ namespace eosio::chain {
*/
class peer_keys_db_t {
public:
struct v0_data { // must match the one in eosio.system.hpp
std::optional<public_key_type> pubkey;
};

using peer_key_map_t = boost::unordered_flat_map<name, public_key_type, std::hash<name>>;
using peer_key_map_t = boost::unordered_flat_map<name, peer_info_t, std::hash<name>>;
using new_peers_t = flat_set<name>;

peer_keys_db_t();

void set_active(bool b) { _active = b; }

// must be called from main thread
size_t update_peer_keys(const controller& chain, uint32_t lib_number);

// safe to be called from any thread
std::optional<public_key_type> get_peer_key(name n) const;
// return the new peers either:
// - added to the top selected producers (according to "getpeerkeys"_n in system contracts)
// - removed from the top selected producers
// - whose key changed
// since the last call to update_peer_keys
// ---------------------------------------
new_peers_t update_peer_keys(const getpeerkeys_res_t& v);

// safe to be called from any thread
size_t size() const;
// peers no longer in top selected producers will have a rank of std::numeric_limits<uint32_t>::max()
// ----------------------------------------------------------------------------------
peer_info_t get_peer_info(name n) const;

private:
std::optional<uint64_t> _get_version(const chainbase::database& db);

bool _active = false; // if not active (the default), no update occurs
uint32_t _block_num = 0; // below map includes keys registered up to _block_num (inclusive)
mutable fc::mutex _m;
peer_key_map_t _peer_key_map GUARDED_BY(_m);
peer_key_map_t _peer_info_map GUARDED_BY(_m);
};

} // namespace eosio::chain

FC_REFLECT(eosio::chain::peer_keys_db_t::v0_data, (pubkey))
Loading
Loading