Skip to content

Commit

Permalink
Merge branch 'GH-2048-persist-if-fork-db' of https://github.com/Antel…
Browse files Browse the repository at this point in the history
…opeIO/leap into GH-2048-persist-if-fork-db
  • Loading branch information
heifner committed Jan 20, 2024
2 parents e07d937 + d31be4f commit 9310754
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 47 deletions.
107 changes: 67 additions & 40 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,24 @@ struct completed_block {
}

const producer_authority_schedule* next_producers() const {
return std::visit(overloaded{
[](const block_state_legacy_ptr& bsp) -> const producer_authority_schedule* { return bsp->pending_schedule_auth();},
[](const block_state_ptr& bsp) -> const producer_authority_schedule* {
return bsp->proposer_policies.empty() ? nullptr : &bsp->proposer_policies.begin()->second->proposer_schedule;
}
}, bsp);
return std::visit(overloaded{[](const block_state_legacy_ptr& bsp) -> const producer_authority_schedule* {
return bsp->pending_schedule_auth();
},
[](const block_state_ptr& bsp) -> const producer_authority_schedule* {
return bsp->proposer_policies.empty()
? nullptr
: &bsp->proposer_policies.begin()->second->proposer_schedule;
}},
bsp);
}

const producer_authority_schedule* pending_producers_legacy() const {
return std::visit(overloaded{
[](const block_state_legacy_ptr& bsp) -> const producer_authority_schedule* { return &bsp->pending_schedule.schedule; },
[](const block_state_ptr&) -> const producer_authority_schedule* { return nullptr; }
}, bsp);
return std::visit(
overloaded{[](const block_state_legacy_ptr& bsp) -> const producer_authority_schedule* {
return &bsp->pending_schedule.schedule;
},
[](const block_state_ptr&) -> const producer_authority_schedule* { return nullptr; }},
bsp);
}

bool is_protocol_feature_activated(const digest_type& digest) const {
Expand Down Expand Up @@ -285,27 +290,27 @@ struct assembled_block {
}

const producer_authority_schedule* next_producers() const {
return std::visit(overloaded{
[](const assembled_block_dpos& ab) -> const producer_authority_schedule* {
return ab.new_producer_authority_cache.has_value() ? &ab.new_producer_authority_cache.value() : nullptr;
},
[](const assembled_block_if& ab) -> const producer_authority_schedule* {
return ab.bhs.proposer_policies.empty() ? nullptr : &ab.bhs.proposer_policies.begin()->second->proposer_schedule;
}
},
return std::visit(overloaded{[](const assembled_block_dpos& ab) -> const producer_authority_schedule* {
return ab.new_producer_authority_cache.has_value()
? &ab.new_producer_authority_cache.value()
: nullptr;
},
[](const assembled_block_if& ab) -> const producer_authority_schedule* {
return ab.bhs.proposer_policies.empty()
? nullptr
: &ab.bhs.proposer_policies.begin()->second->proposer_schedule;
}},
v);
}

const producer_authority_schedule* pending_producers_legacy() const {
return std::visit(overloaded{
[](const assembled_block_dpos& ab) -> const producer_authority_schedule* {
return ab.new_producer_authority_cache.has_value() ? &ab.new_producer_authority_cache.value() : nullptr;
},
[](const assembled_block_if&) -> const producer_authority_schedule* {
return nullptr;
}
},
v);
return std::visit(
overloaded{[](const assembled_block_dpos& ab) -> const producer_authority_schedule* {
return ab.new_producer_authority_cache.has_value() ? &ab.new_producer_authority_cache.value()
: nullptr;
},
[](const assembled_block_if&) -> const producer_authority_schedule* { return nullptr; }},
v);
}

const block_signing_authority& pending_block_signing_authority() const {
Expand Down Expand Up @@ -843,12 +848,27 @@ struct controller_impl {
int64_t set_proposed_producers( vector<producer_authority> producers );
int64_t set_proposed_producers_legacy( vector<producer_authority> producers );

uint32_t head_block_num() const { return fork_db.apply<uint32_t>([](const auto& forkdb) { return forkdb.chain_head->block_num(); }); }
block_timestamp_type head_block_time() const { return fork_db.apply<block_timestamp_type>([](const auto& forkdb) { return forkdb.chain_head->timestamp(); }); }
account_name head_block_producer() const { return fork_db.apply<account_name>([](const auto& forkdb) { return forkdb.chain_head->producer(); }); }
const block_id_type& head_block_id() const { return fork_db.apply<const block_id_type&>([](const auto& forkdb) -> const block_id_type& { return forkdb.chain_head->id(); }); }
const block_header& head_block_header() const { return fork_db.apply<const block_header&>([](const auto& forkdb) -> const block_header& { return forkdb.chain_head->header; }); }
const signed_block_ptr& head_block() const { return fork_db.apply<const signed_block_ptr&>([](const auto& forkdb) -> const signed_block_ptr& { return forkdb.chain_head->block; }); }
uint32_t head_block_num() const {
return fork_db.apply<uint32_t>([](const auto& forkdb) { return forkdb.chain_head->block_num(); });
}
block_timestamp_type head_block_time() const {
return fork_db.apply<block_timestamp_type>([](const auto& forkdb) { return forkdb.chain_head->timestamp(); });
}
account_name head_block_producer() const {
return fork_db.apply<account_name>([](const auto& forkdb) { return forkdb.chain_head->producer(); });
}
const block_id_type& head_block_id() const {
return fork_db.apply<const block_id_type&>(
[](const auto& forkdb) -> const block_id_type& { return forkdb.chain_head->id(); });
}
const block_header& head_block_header() const {
return fork_db.apply<const block_header&>(
[](const auto& forkdb) -> const block_header& { return forkdb.chain_head->header; });
}
const signed_block_ptr& head_block() const {
return fork_db.apply<const signed_block_ptr&>(
[](const auto& forkdb) -> const signed_block_ptr& { return forkdb.chain_head->block; });
}

protocol_feature_activation_set_ptr head_activated_protocol_features() const {
return fork_db.apply<protocol_feature_activation_set_ptr>([](const auto& forkdb) {
Expand Down Expand Up @@ -925,15 +945,18 @@ struct controller_impl {
}

uint32_t fork_db_head_block_num() const {
return fork_db.apply<uint32_t>([&](const auto& forkdb) { return fork_db_head(forkdb, irreversible_mode())->block_num(); } );
return fork_db.apply<uint32_t>(
[&](const auto& forkdb) { return fork_db_head(forkdb, irreversible_mode())->block_num(); });
}

block_id_type fork_db_head_block_id() const {
return fork_db.apply<block_id_type>([&](const auto& forkdb) { return fork_db_head(forkdb, irreversible_mode())->id(); } );
return fork_db.apply<block_id_type>(
[&](const auto& forkdb) { return fork_db_head(forkdb, irreversible_mode())->id(); });
}

uint32_t fork_db_head_irreversible_blocknum() const {
return fork_db.apply<uint32_t>([&](const auto& forkdb) { return fork_db_head(forkdb, irreversible_mode())->irreversible_blocknum(); });
return fork_db.apply<uint32_t>(
[&](const auto& forkdb) { return fork_db_head(forkdb, irreversible_mode())->irreversible_blocknum(); });
}

// --------------- access fork_db root ----------------------------------------------------------------------
Expand All @@ -959,11 +982,13 @@ struct controller_impl {
typename ForkDB::bsp_t prev = forkdb.get_block( forkdb.chain_head->previous() );

if( !prev ) {
EOS_ASSERT( forkdb.root()->id() == forkdb.chain_head->previous(), block_validate_exception, "attempt to pop beyond last irreversible block" );
EOS_ASSERT( forkdb.root()->id() == forkdb.chain_head->previous(), block_validate_exception,
"attempt to pop beyond last irreversible block" );
prev = forkdb.root();
}

EOS_ASSERT( forkdb.chain_head->block, block_validate_exception, "attempting to pop a block that was sparsely loaded from a snapshot");
EOS_ASSERT( forkdb.chain_head->block, block_validate_exception,
"attempting to pop a block that was sparsely loaded from a snapshot");
forkdb.chain_head = prev;

return prev->block_num();
Expand Down Expand Up @@ -1407,8 +1432,10 @@ struct controller_impl {
}

void startup(std::function<void()> shutdown, std::function<bool()> check_shutdown) {
EOS_ASSERT( db.revision() >= 1, database_exception, "This version of controller::startup does not work with a fresh state database." );
EOS_ASSERT( fork_db_has_head(), fork_database_exception, "No existing fork database despite existing chain state. Replay required." );
EOS_ASSERT( db.revision() >= 1, database_exception,
"This version of controller::startup does not work with a fresh state database." );
EOS_ASSERT( fork_db_has_head(), fork_database_exception,
"No existing fork database despite existing chain state. Replay required." );

this->shutdown = std::move(shutdown);
uint32_t lib_num = fork_db_root_block_num();
Expand Down
21 changes: 14 additions & 7 deletions libraries/chain/fork_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ namespace eosio::chain {
for( auto b = new_root; b; ) {
blocks_to_remove.emplace_back( b->previous() );
b = get_block_impl( blocks_to_remove.back() );
EOS_ASSERT( b || blocks_to_remove.back() == root->id(), fork_database_exception, "invariant violation: orphaned branch was present in forked database" );
EOS_ASSERT( b || blocks_to_remove.back() == root->id(), fork_database_exception,
"invariant violation: orphaned branch was present in forked database" );
}

// The new root block should be erased from the fork database index individually rather than with the remove method,
Expand Down Expand Up @@ -331,15 +332,20 @@ namespace eosio::chain {
EOS_ASSERT( prev_bh, unlinkable_block_exception,
"unlinkable block", ("id", n->id())("previous", n->previous()) );

if( validate ) {
if (validate) {
try {
const auto& exts = n->header_exts;

if( exts.count(protocol_feature_activation::extension_id()) > 0 ) {
const auto& new_protocol_features = std::get<protocol_feature_activation>(exts.lower_bound(protocol_feature_activation::extension_id())->second).protocol_features;
validator( n->timestamp(), static_cast<bs*>(prev_bh.get())->get_activated_protocol_features()->protocol_features, new_protocol_features );
if (exts.count(protocol_feature_activation::extension_id()) > 0) {
const auto& pfa = exts.lower_bound(protocol_feature_activation::extension_id())->second;
const auto& new_protocol_features = std::get<protocol_feature_activation>(pfa).protocol_features;
validator(n->timestamp(),
static_cast<bs*>(prev_bh.get())->get_activated_protocol_features()->protocol_features,
new_protocol_features);
}
} EOS_RETHROW_EXCEPTIONS( fork_database_exception, "serialized fork database is incompatible with configured protocol features" )
}
EOS_RETHROW_EXCEPTIONS(fork_database_exception,
"serialized fork database is incompatible with configured protocol features")
}

auto inserted = index.insert(n);
Expand Down Expand Up @@ -589,7 +595,8 @@ namespace eosio::chain {
// determine file type, validate totem
uint32_t totem = 0;
fc::raw::unpack( ds, totem );
EOS_ASSERT( totem == fork_database_legacy_t::legacy_magic_number || totem == fork_database_if_t::magic_number, fork_database_exception,
EOS_ASSERT( totem == fork_database_legacy_t::legacy_magic_number ||
totem == fork_database_if_t::magic_number, fork_database_exception,
"Fork database file '${filename}' has unexpected magic number: ${actual_totem}. Expected ${t1} or ${t2}",
("filename", fork_db_file)
("actual_totem", totem)("t1", fork_database_legacy_t::legacy_magic_number)("t2", fork_database_if_t::magic_number)
Expand Down

0 comments on commit 9310754

Please sign in to comment.