From d9e926e0f19b267804516f33d96ba30e477efe4b Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 17 Jul 2024 17:32:42 -0700 Subject: [PATCH] use old state (-5 blocks) in pillar blocks --- for_devs/local-net | 2 +- .../config_jsons/default/default_genesis.json | 4 +- libraries/config/include/config/hardfork.hpp | 4 +- libraries/config/src/hardfork.cpp | 4 ++ .../consensus/include/pbft/pbft_manager.hpp | 7 ++ .../pillar_chain/pillar_chain_manager.hpp | 8 ++- .../src/final_chain/final_chai_impl.cpp | 6 +- .../consensus/src/pbft/pbft_manager.cpp | 71 +++++++++++-------- .../src/pillar_chain/pillar_chain_manager.cpp | 20 +++--- tests/test_util/src/test_util.cpp | 1 - 10 files changed, 78 insertions(+), 49 deletions(-) diff --git a/for_devs/local-net b/for_devs/local-net index 9292441ff0..8add8bec84 100755 --- a/for_devs/local-net +++ b/for_devs/local-net @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.11 +#!/usr/bin/env python3 import click import subprocess diff --git a/libraries/cli/include/cli/config_jsons/default/default_genesis.json b/libraries/cli/include/cli/config_jsons/default/default_genesis.json index 90ce1d6eb7..322d177b10 100644 --- a/libraries/cli/include/cli/config_jsons/default/default_genesis.json +++ b/libraries/cli/include/cli/config_jsons/default/default_genesis.json @@ -116,8 +116,8 @@ "generated_rewards": "0x0" }, "ficus_hf": { - "block_num": 48, - "pillar_blocks_interval": 16, + "block_num": 20, + "pillar_blocks_interval": 10, "bridge_contract_address": "0xcAF2b453FE8382a4B8110356DF0508f6d71F22BF" } } diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp index 2b176bf5d1..1e1c95c5b6 100644 --- a/libraries/config/include/config/hardfork.hpp +++ b/libraries/config/include/config/hardfork.hpp @@ -40,8 +40,8 @@ Json::Value enc_json(const AspenHardfork& obj); void dec_json(const Json::Value& json, AspenHardfork& obj); struct FicusHardforkConfig { - uint64_t block_num{0}; - uint64_t pillar_blocks_interval{100}; // [periods] how often is the new pillar block created + uint64_t block_num{10}; + uint64_t pillar_blocks_interval{10}; // [periods] how often is the new pillar block created taraxa::addr_t bridge_contract_address; // [address] of the bridge contract bool isFicusHardfork(taraxa::PbftPeriod period) const; diff --git a/libraries/config/src/hardfork.cpp b/libraries/config/src/hardfork.cpp index 417ff4a06b..be7768564b 100644 --- a/libraries/config/src/hardfork.cpp +++ b/libraries/config/src/hardfork.cpp @@ -74,6 +74,10 @@ void FicusHardforkConfig::validate(uint32_t delegation_delay) const { return; } + if (block_num < delegation_delay) { + throw taraxa::ConfigException("ficus_hf.block_num must be >= dpos.delegation_delay"); + } + if (pillar_blocks_interval <= 1) { throw taraxa::ConfigException("ficus_hf.pillar_blocks_interval must be > 1"); } diff --git a/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp b/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp index ba157cb2de..04ef10314b 100644 --- a/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp +++ b/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp @@ -548,6 +548,13 @@ class PbftManager { */ void printVotingSummary() const; + /** + * @brief Creates pillar block (and pillar vote in case node is eligible to vote & is not syncing) + * + * @param period + */ + void processPillarBlock(PbftPeriod period); + std::atomic stopped_ = true; // Multiple proposed pbft blocks could have same dag block anchor at same period so this cache improves retrieval of diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index e99a16ec85..918142c110 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -44,10 +44,16 @@ class PillarChainManager { /** * @Process Creates new pillar block * + * @param period * @param block_header + * @param bridge_root + * @param bridge_epoch + * * @return pillar block in case block was created, otherwise nullptr */ - std::shared_ptr createPillarBlock(const std::shared_ptr& block_header); + std::shared_ptr createPillarBlock(PbftPeriod period, + const std::shared_ptr& block_header, + const h256& bridge_root, const h256& bridge_epoch); /** * @brief Generate and place pillar vote for provided pillar_block_hash in case the whole pillar block is present and diff --git a/libraries/core_libs/consensus/src/final_chain/final_chai_impl.cpp b/libraries/core_libs/consensus/src/final_chain/final_chai_impl.cpp index 2d35bf26b7..4c77e95324 100644 --- a/libraries/core_libs/consensus/src/final_chain/final_chai_impl.cpp +++ b/libraries/core_libs/consensus/src/final_chain/final_chai_impl.cpp @@ -128,7 +128,10 @@ bool FinalChainImpl::isNeedToFinalize(EthBlockNumber blk_num) const { std::vector FinalChainImpl::makeSystemTransactions(PbftPeriod blk_num) { std::vector system_transactions; - if (kHardforksConfig.ficus_hf.isPillarBlockPeriod(blk_num)) { + // Make system transactions blocks sooner than next pillar block period, + // e.g.: if pillar block period is 100, this will return true for period 100 - delegation_delay() == 95, 195, 295, + // etc... + if (kHardforksConfig.ficus_hf.isPillarBlockPeriod(blk_num + delegation_delay())) { if (const auto bridge_contract = get_account(kHardforksConfig.ficus_hf.bridge_contract_address); bridge_contract) { if (bridge_contract->code_size && isNeedToFinalize(blk_num - 1)) { auto finalize_trx = make_bridge_finalization_transaction(); @@ -136,6 +139,7 @@ std::vector FinalChainImpl::makeSystemTransactions(PbftPeriod } } } + return system_transactions; } diff --git a/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp b/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp index abfce2f9c8..7a8c0ec2b1 100644 --- a/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp +++ b/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp @@ -1682,39 +1682,11 @@ void PbftManager::finalize_(PeriodData &&period_data, std::vector &&finali } } - const auto period = period_data.pbft_blk->getPeriod(); auto result = final_chain_->finalize(std::move(period_data), std::move(finalized_dag_blk_hashes), std::move(anchor_block)); - bool is_pillar_block_period = kGenesisConfig.state.hardforks.ficus_hf.isPillarBlockPeriod(period); - if (synchronous_processing || is_pillar_block_period) { + if (synchronous_processing) { result.wait(); - - if (!is_pillar_block_period) { - return; - } - - // Create new pillar block - const auto finalization_data = result.get(); - const auto pillar_block = pillar_chain_mgr_->createPillarBlock(finalization_data->final_chain_blk); - - // Check if node is eligible to vote for pillar block - // Note: No need to catch ErrFutureBlock because pillar block is create only after pbft block with is - // finalized Note: period is used instead of period -1 because at this moment, block with period was - // already finalized - if (final_chain_->dpos_is_eligible(period, node_addr_)) { - if (pillar_block) { - // Pillar votes are created in the next period (thus period + 1), this is optimization to create & broadcast it - // a bit faster - const auto pillar_vote = pillar_chain_mgr_->genAndPlacePillarVote(period + 1, pillar_block->getHash(), node_sk_, - periodDataQueueEmpty()); - if (pillar_vote) { - last_placed_pillar_vote_period_ = pillar_vote->getPeriod(); - } - } else { - LOG(log_er_) << "Unable to vote for pillar block with period " << period << ". Block was not created"; - } - } } } @@ -1812,9 +1784,50 @@ bool PbftManager::pushPbftBlock_(PeriodData &&period_data, std::vectorgetPbftChainSize()); + processPillarBlock(pbft_period); + } + return true; } +void PbftManager::processPillarBlock(PbftPeriod current_pbft_chain_size) { + // Pillar block use state from current_pbft_chain_size - final_chain_->delegation_delay(), e.g. block with period 32 + // uses state from period 27. + PbftPeriod request_period = current_pbft_chain_size - final_chain_->delegation_delay(); + // advancePeriod() -> resetConsensus() -> waitForPeriodFinalization() makes sure block request_period was already + // finalized + assert(final_chain_->last_block_number() >= request_period); + + const auto block_header = final_chain_->block_header(request_period); + const auto bridge_root = final_chain_->get_bridge_root(request_period); + const auto bridge_epoch = final_chain_->get_bridge_epoch(request_period); + + // Create pillar block + const auto pillar_block = + pillar_chain_mgr_->createPillarBlock(current_pbft_chain_size, block_header, bridge_root, bridge_epoch); + + // Optimization - creates pillar vote right after pillar block was created, otherwise pillar votes are created during + // next period pbft voting Check if node is eligible to vote for pillar block No need to catch ErrFutureBlock, + // waitForPeriodFinalization() makes sure it does not happen + if (final_chain_->dpos_is_eligible(current_pbft_chain_size, node_addr_)) { + if (pillar_block) { + // Pillar votes are created in the next period (+ 1), this is optimization to create & broadcast it a bit faster + const auto pillar_vote = pillar_chain_mgr_->genAndPlacePillarVote( + current_pbft_chain_size + 1, pillar_block->getHash(), node_sk_, periodDataQueueEmpty()); + if (pillar_vote) { + last_placed_pillar_vote_period_ = pillar_vote->getPeriod(); + } + } else { + LOG(log_er_) << "Unable to vote for pillar block with period " << current_pbft_chain_size + << ". Block was not created"; + } + } +} + PbftPeriod PbftManager::pbftSyncingPeriod() const { return std::max(sync_queue_.getPeriod(), pbft_chain_->getPbftChainSize()); } diff --git a/libraries/core_libs/consensus/src/pillar_chain/pillar_chain_manager.cpp b/libraries/core_libs/consensus/src/pillar_chain/pillar_chain_manager.cpp index 005adc460f..aa1535367b 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_chain_manager.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_chain_manager.cpp @@ -44,15 +44,14 @@ PillarChainManager::PillarChainManager(const FicusHardforkConfig& ficus_hf_confi } std::shared_ptr PillarChainManager::createPillarBlock( - const std::shared_ptr& block_header) { - const auto block_num = block_header->number; - + PbftPeriod period, const std::shared_ptr& block_header, const h256& bridge_root, + const h256& bridge_epoch) { blk_hash_t previous_pillar_block_hash{}; // null block hash - auto new_vote_counts = final_chain_->dpos_validators_vote_counts(block_num); + auto new_vote_counts = final_chain_->dpos_validators_vote_counts(period); std::vector votes_count_changes; // First ever pillar block - if (block_num == kFicusHfConfig.firstPillarBlockPeriod()) { + if (period == kFicusHfConfig.firstPillarBlockPeriod()) { // First pillar block - use all current votes counts as changes votes_count_changes.reserve(new_vote_counts.size()); std::transform(new_vote_counts.begin(), new_vote_counts.end(), std::back_inserter(votes_count_changes), @@ -64,7 +63,7 @@ std::shared_ptr PillarChainManager::createPillarBlock( const auto last_finalized_pillar_block = getLastFinalizedPillarBlock(); // This should never happen !!! if (!last_finalized_pillar_block) { - LOG(log_er_) << "Empty last finalized pillar block, new pillar block period " << block_num; + LOG(log_er_) << "Empty last finalized pillar block, new pillar block period " << period; assert(false); return nullptr; } @@ -73,7 +72,7 @@ std::shared_ptr PillarChainManager::createPillarBlock( // which is always called once in a time // This should never happen !!! if (current_pillar_block_vote_counts_.empty()) { - LOG(log_er_) << "Empty current pillar block vote counts, new pillar block period " << block_num; + LOG(log_er_) << "Empty current pillar block vote counts, new pillar block period " << period; assert(false); return nullptr; } @@ -84,11 +83,8 @@ std::shared_ptr PillarChainManager::createPillarBlock( votes_count_changes = getOrderedValidatorsVoteCountsChanges(new_vote_counts, current_pillar_block_vote_counts_); } - h256 bridge_root = final_chain_->get_bridge_root(block_num); - u256 bridge_epoch = final_chain_->get_bridge_epoch(block_num); - const auto pillar_block = - std::make_shared(block_num, block_header->state_root, previous_pillar_block_hash, bridge_root, - bridge_epoch, std::move(votes_count_changes)); + const auto pillar_block = std::make_shared(period, block_header->state_root, previous_pillar_block_hash, + bridge_root, bridge_epoch, std::move(votes_count_changes)); // Check if some pillar block was not skipped if (!isValidPillarBlock(pillar_block)) { diff --git a/tests/test_util/src/test_util.cpp b/tests/test_util/src/test_util.cpp index fe6c43b215..c0eda415de 100644 --- a/tests/test_util/src/test_util.cpp +++ b/tests/test_util/src/test_util.cpp @@ -221,7 +221,6 @@ NodesTest::NodesTest() { taraxa::NodeConfig{"7b1fcf0ec1078320117b96e9e9ad9032c06d030cf4024a598347a4623a14a421d4f030cf25ef368ab394a45e9" "20e14b57a259a09c41767dd50d1da27b627412a", "127.0.0.1", 10003}); - cfg.genesis.state.hardforks.ficus_hf.block_num = 0; cfg.validate(); node_cfgs.emplace_back(cfg);