Skip to content

Commit

Permalink
Merge pull request #2113 from AntelopeIO/GH-2048-persist-if-fork-db
Browse files Browse the repository at this point in the history
IF: Support load of fork database after instant-finality is enabled
  • Loading branch information
heifner authored Jan 21, 2024
2 parents c7a249d + 9310754 commit 7284414
Show file tree
Hide file tree
Showing 9 changed files with 747 additions and 675 deletions.
5 changes: 5 additions & 0 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

namespace eosio::chain {

// moved this warning out of header so it only uses once
#warning TDDO https://github.com/AntelopeIO/leap/issues/2080
// digest_type compute_finalizer_digest() const { return id; };


producer_authority block_header_state::get_scheduled_producer(block_timestamp_type t) const {
return detail::get_scheduled_producer(active_proposer_policy->proposer_schedule.producers, t);
}
Expand Down
1,028 changes: 484 additions & 544 deletions libraries/chain/controller.cpp

Large diffs are not rendered by default.

246 changes: 142 additions & 104 deletions libraries/chain/fork_database.cpp

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,6 @@ namespace eosio::chain {

const chainbase::database& db()const;

const fork_database_legacy& fork_db()const;

const account_object& get_account( account_name n )const;
const global_property_object& get_global_properties()const;
const dynamic_global_property_object& get_dynamic_global_properties()const;
Expand Down Expand Up @@ -249,7 +247,7 @@ namespace eosio::chain {
block_state_legacy_ptr head_block_state_legacy()const;

uint32_t fork_db_head_block_num()const;
const block_id_type& fork_db_head_block_id()const;
block_id_type fork_db_head_block_id()const;

time_point pending_block_time()const;
block_timestamp_type pending_block_timestamp()const;
Expand Down
120 changes: 104 additions & 16 deletions libraries/chain/include/eosio/chain/fork_database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,35 @@ namespace eosio::chain {
struct fork_database_impl;

/**
* @class fork_database
* @class fork_database_t
* @brief manages light-weight state for all potential unconfirmed forks
*
* As new blocks are received, they are pushed into the fork database. The fork
* database tracks the longest chain and the last irreversible block number. All
* blocks older than the last irreversible block are freed after emitting the
* irreversible signal.
*
* An internal mutex is used to provide thread-safety.
* Not thread safe, thread safety provided by fork_database below.
* fork_database should be used instead of fork_database_t directly as it manages
* the different supported types.
*/
template<class bsp> // either block_state_legacy_ptr or block_state_ptr
class fork_database {
class fork_database_t {
public:
static constexpr uint32_t legacy_magic_number = 0x30510FDB;
static constexpr uint32_t magic_number = 0x4242FDB;

using bs = bsp::element_type;
using bhsp = bs::bhsp_t;
using bhs = bhsp::element_type;
using bsp_t = bsp;
using branch_type = deque<bsp>;
using branch_type_pair = pair<branch_type, branch_type>;

explicit fork_database( const std::filesystem::path& data_dir );
~fork_database();

std::filesystem::path get_data_dir() const;
explicit fork_database_t(uint32_t magic_number = legacy_magic_number);

void open( validator_t& validator );
void close();
void open( const std::filesystem::path& fork_db_file, validator_t& validator );
void close( const std::filesystem::path& fork_db_file );

bhsp get_block_header( const block_id_type& id ) const;
bsp get_block( const block_id_type& id ) const;
Expand Down Expand Up @@ -70,6 +72,9 @@ namespace eosio::chain {
bsp head() const;
bsp pending_head() const;

// only accessed by main thread, no mutex protection
bsp chain_head;

/**
* Returns the sequence of block states resulting from trimming the branch from the
* root block (exclusive) to the block with an id of `h` (inclusive) by removing any
Expand All @@ -95,15 +100,98 @@ namespace eosio::chain {

void mark_valid( const bsp& h );

static const uint32_t magic_number;

static const uint32_t min_supported_version;
static const uint32_t max_supported_version;

private:
unique_ptr<fork_database_impl<bsp>> my;
};

using fork_database_legacy = fork_database<block_state_legacy_ptr>;

using fork_database_legacy_t = fork_database_t<block_state_legacy_ptr>;
using fork_database_if_t = fork_database_t<block_state_ptr>;

/**
* Provides thread safety on fork_database_t and provide mechanism for opening the correct type
* as well as switching from legacy (old dpos) to instant-finality.
*
* All methods assert until open() is closed.
*/
class fork_database {
mutable std::recursive_mutex m;
const std::filesystem::path data_dir;
std::variant<fork_database_t<block_state_legacy_ptr>, fork_database_t<block_state_ptr>> vforkdb;
public:
explicit fork_database(const std::filesystem::path& data_dir);
~fork_database(); // close on destruction

void open( validator_t& validator );
void close();

void switch_from_legacy();

// see fork_database_t::fetch_branch(forkdb->head()->id())
std::vector<signed_block_ptr> fetch_branch_from_head();

template <class R, class F>
R apply(const F& f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit([&](auto& forkdb) { f(forkdb); }, vforkdb);
else
return std::visit([&](auto& forkdb) -> R { return f(forkdb); }, vforkdb);
}

template <class R, class F>
R apply(const F& f) const {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit([&](const auto& forkdb) { f(forkdb); }, vforkdb);
else
return std::visit([&](const auto& forkdb) -> R { return f(forkdb); }, vforkdb);
}

/// Apply for when only need lambda executed when in instant-finality mode
template <class R, class F>
R apply_if(const F& f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit(overloaded{[&](fork_database_legacy_t&) {},
[&](fork_database_if_t& forkdb) { f(forkdb); }},
vforkdb);
else
return std::visit(overloaded{[&](fork_database_legacy_t&) -> R { return {}; },
[&](fork_database_if_t& forkdb) -> R { return f(forkdb); }},
vforkdb);
}

/// Apply for when only need lambda executed when in legacy mode
template <class R, class F>
R apply_legacy(const F& f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit(overloaded{[&](fork_database_legacy_t& forkdb) { f(forkdb); },
[&](fork_database_if_t&) {}},
vforkdb);
else
return std::visit(overloaded{[&](fork_database_legacy_t& forkdb) -> R { return f(forkdb); },
[&](fork_database_if_t&) -> R { return {}; }},
vforkdb);
}

/// @param legacy_f the lambda to execute if in legacy mode
/// @param if_f the lambda to execute if in instant-finality mode
template <class R, class LegacyF, class IfF>
R apply(const LegacyF& legacy_f, const IfF& if_f) {
std::lock_guard g(m);
if constexpr (std::is_same_v<void, R>)
std::visit(overloaded{[&](fork_database_legacy_t& forkdb) { legacy_f(forkdb); },
[&](fork_database_if_t& forkdb) { if_f(forkdb); }},
vforkdb);
else
return std::visit(overloaded{[&](fork_database_legacy_t& forkdb) -> R { return legacy_f(forkdb); },
[&](fork_database_if_t& forkdb) -> R { return if_f(forkdb); }},
vforkdb);
}

// if we ever support more than one version then need to save min/max in fork_database_t
static constexpr uint32_t min_supported_version = 1;
static constexpr uint32_t max_supported_version = 1;
};
} /// eosio::chain
9 changes: 4 additions & 5 deletions programs/leap-util/actions/blocklog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,18 +266,17 @@ int blocklog_actions::read_log() {
opt->first_block = block_logger.first_block_num();
}

using fork_database_t = fork_database_legacy; // [greg todo] what is it is not a legacy fork_db?
fork_database_t::branch_type fork_db_branch;
std::vector<signed_block_ptr> fork_db_branch;

if(std::filesystem::exists(std::filesystem::path(opt->blocks_dir) / config::reversible_blocks_dir_name / config::forkdb_filename)) {
ilog("opening fork_db");
fork_database_t fork_db(std::filesystem::path(opt->blocks_dir) / config::reversible_blocks_dir_name);
fork_database fork_db(std::filesystem::path(opt->blocks_dir) / config::reversible_blocks_dir_name);

fork_db.open([](block_timestamp_type timestamp,
const flat_set<digest_type>& cur_features,
const vector<digest_type>& new_features) {});

fork_db_branch = fork_db.fetch_branch(fork_db.head()->id());
fork_db_branch = fork_db.fetch_branch_from_head();
if(fork_db_branch.empty()) {
elog("no blocks available in reversible block database: only block_log blocks are available");
} else {
Expand Down Expand Up @@ -336,7 +335,7 @@ int blocklog_actions::read_log() {
for(auto bitr = fork_db_branch.rbegin(); bitr != fork_db_branch.rend() && block_num <= opt->last_block; ++bitr) {
if(opt->as_json_array && contains_obj)
*out << ",";
auto next = (*bitr)->block;
auto& next = *bitr;
print_block(next);
++block_num;
contains_obj = true;
Expand Down
3 changes: 3 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ set_property(TEST nodeos_chainbase_allocation_test PROPERTY LABELS nonparalleliz
add_test(NAME nodeos_startup_catchup_lr_test COMMAND tests/nodeos_startup_catchup.py -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_startup_catchup_lr_test PROPERTY LABELS long_running_tests)

add_test(NAME nodeos_startup_catchup_if_lr_test COMMAND tests/nodeos_startup_catchup.py -p3 --activate-if -v ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_startup_catchup_if_lr_test PROPERTY LABELS long_running_tests)

add_test(NAME nodeos_short_fork_take_over_test COMMAND tests/nodeos_short_fork_take_over_test.py -v --wallet-port 9905 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_short_fork_take_over_test PROPERTY LABELS nonparallelizable_tests)

Expand Down
5 changes: 3 additions & 2 deletions tests/nodeos_startup_catchup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
extraArgs = appArgs.add(flag="--catchup-count", type=int, help="How many catchup-nodes to launch", default=10)
extraArgs = appArgs.add(flag="--txn-gen-nodes", type=int, help="How many transaction generator nodes", default=2)
args = TestHelper.parse_args({"--dump-error-details","--keep-logs","-v","--leave-running",
"-p","--wallet-port","--unshared"}, applicationSpecificArgs=appArgs)
"--activate-if","-p","--wallet-port","--unshared"}, applicationSpecificArgs=appArgs)
Utils.Debug=args.v
pnodes=args.p if args.p > 0 else 1
startedNonProdNodes = args.txn_gen_nodes if args.txn_gen_nodes >= 2 else 2
Expand All @@ -43,6 +43,7 @@
walletPort=args.wallet_port
catchupCount=args.catchup_count if args.catchup_count > 0 else 1
totalNodes=startedNonProdNodes+pnodes+catchupCount
activateIF=args.activate_if

walletMgr=WalletMgr(True, port=walletPort)
testSuccessful=False
Expand All @@ -56,7 +57,7 @@
cluster.setWalletMgr(walletMgr)

Print("Stand up cluster")
if cluster.launch(prodCount=prodCount, onlyBios=False, pnodes=pnodes, totalNodes=totalNodes, totalProducers=pnodes*prodCount,
if cluster.launch(prodCount=prodCount, activateIF=activateIF, onlyBios=False, pnodes=pnodes, totalNodes=totalNodes, totalProducers=pnodes*prodCount,
unstartedNodes=catchupCount, loadSystemContract=True,
maximumP2pPerHost=totalNodes+trxGeneratorCnt) is False:
Utils.errorExit("Failed to stand up eos cluster.")
Expand Down
2 changes: 1 addition & 1 deletion unittests/unapplied_transaction_queue_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ auto create_test_block_state( deque<transaction_metadata_ptr> trx_metas ) {
return bsp;
}

using branch_type_legacy = fork_database<block_state_legacy_ptr>::branch_type;
using branch_type_legacy = fork_database_t<block_state_legacy_ptr>::branch_type;

template<class BRANCH_TYPE>
void add_forked( unapplied_transaction_queue& queue, const BRANCH_TYPE& forked_branch ) {
Expand Down

0 comments on commit 7284414

Please sign in to comment.