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 254f513b8f..ea19cf2112 100644 --- a/libraries/cli/include/cli/config_jsons/default/default_genesis.json +++ b/libraries/cli/include/cli/config_jsons/default/default_genesis.json @@ -75,6 +75,7 @@ "number_of_proposers": "0x14", "dag_blocks_size": "0x32", "ghost_path_move_back": "0x0", + "state_root_recording_delay": "0x3", "lambda_ms": "0x5DC", "gas_limit": "0x3938700" }, diff --git a/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json b/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json index bf9300994a..b28d75537c 100644 --- a/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json @@ -244,6 +244,7 @@ "number_of_proposers": "0x14", "dag_blocks_size": "0x32", "ghost_path_move_back": "0x0", + "state_root_recording_delay": "0x3", "lambda_ms": "0x5DC", "gas_limit": "0x7d2b7500" }, diff --git a/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json b/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json index 248893905c..c5885a1a7c 100644 --- a/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json @@ -267,6 +267,7 @@ "number_of_proposers": "0x14", "dag_blocks_size": "0x32", "ghost_path_move_back": "0x0", + "state_root_recording_delay": "0x3", "lambda_ms": "0x5DC", "gas_limit": "0x7d2b7500" }, diff --git a/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json b/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json index 20ea41a5cc..f5cfae2114 100644 --- a/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json @@ -112,6 +112,7 @@ "number_of_proposers": "0x14", "dag_blocks_size": "0x32", "ghost_path_move_back": "0x0", + "state_root_recording_delay": "0x3", "lambda_ms": "0x5DC", "gas_limit": "0x7d2b7500" }, diff --git a/libraries/common/include/common/constants.hpp b/libraries/common/include/common/constants.hpp index 953ca7e1b2..a549df5021 100644 --- a/libraries/common/include/common/constants.hpp +++ b/libraries/common/include/common/constants.hpp @@ -13,7 +13,7 @@ GLOBAL_CONST(h256, EmptyRLPListSHA3); GLOBAL_CONST(h64, EmptyNonce); GLOBAL_CONST(u256, ZeroU256); -static const blk_hash_t kNullBlockHash = blk_hash_t(0); +static const blk_hash_t kNullBlockHash; constexpr uint16_t kOnePercent = 100; constexpr uint16_t kMaxLevelsPerPeriod = 100; diff --git a/libraries/config/include/config/pbft_config.hpp b/libraries/config/include/config/pbft_config.hpp index 4c2793a274..e0f271fa5c 100644 --- a/libraries/config/include/config/pbft_config.hpp +++ b/libraries/config/include/config/pbft_config.hpp @@ -12,6 +12,7 @@ struct PbftConfig { uint32_t number_of_proposers = 20; uint32_t dag_blocks_size = 0; uint32_t ghost_path_move_back = 0; + uint32_t state_root_recording_delay = 3; uint64_t gas_limit = 0; bytes rlp() const; diff --git a/libraries/config/src/pbft_config.cpp b/libraries/config/src/pbft_config.cpp index 3d8970a763..8001ef0b5f 100644 --- a/libraries/config/src/pbft_config.cpp +++ b/libraries/config/src/pbft_config.cpp @@ -12,6 +12,7 @@ Json::Value enc_json(PbftConfig const& obj) { ret["number_of_proposers"] = dev::toJS(obj.number_of_proposers); ret["dag_blocks_size"] = dev::toJS(obj.dag_blocks_size); ret["ghost_path_move_back"] = dev::toJS(obj.ghost_path_move_back); + ret["state_root_recording_delay"] = dev::toJS(obj.state_root_recording_delay); ret["gas_limit"] = dev::toJS(obj.gas_limit); return ret; } @@ -22,6 +23,7 @@ void dec_json(Json::Value const& json, PbftConfig& obj) { obj.number_of_proposers = dev::jsToInt(json["number_of_proposers"].asString()); obj.dag_blocks_size = dev::jsToInt(json["dag_blocks_size"].asString()); obj.ghost_path_move_back = dev::jsToInt(json["ghost_path_move_back"].asString()); + obj.state_root_recording_delay = dev::jsToInt(json["state_root_recording_delay"].asString()); obj.gas_limit = dev::getUInt(json["gas_limit"]); } @@ -34,6 +36,7 @@ bytes PbftConfig::rlp() const { s << number_of_proposers; s << dag_blocks_size; s << ghost_path_move_back; + s << state_root_recording_delay; s << gas_limit; return s.out(); diff --git a/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp b/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp index e7f2f40876..1baf687d93 100644 --- a/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp +++ b/libraries/core_libs/consensus/include/pbft/pbft_manager.hpp @@ -15,8 +15,6 @@ #include "pbft/proposed_blocks.hpp" #include "pbft/soft_voted_block_data.hpp" -#define NULL_BLOCK_HASH blk_hash_t(0) - namespace taraxa { /** @addtogroup PBFT @@ -314,7 +312,7 @@ class PbftManager : public std::enable_shared_from_this { void resetStep(); /** - * @brief If node receives 2t+1 next votes for some block(including NULL_BLOCK_HASH), advance round to + 1. + * @brief If node receives 2t+1 next votes for some block(including kNullBlockHash), advance round to + 1. * @return true if PBFT round advanced, otherwise false */ bool advanceRound(); @@ -473,7 +471,7 @@ class PbftManager : public std::enable_shared_from_this { * @brief Identify a leader block from all received proposed PBFT blocks for the current round by using minimum * Verifiable Random Function (VRF) output. In filter state, don’t need check vote value correction. * @param round current pbft round - * @param period new pbft period (perriod == chain_size + 1) + * @param period new pbft period (period == chain_size + 1) * @return shared_ptr to leader identified leader block */ // TODO: exchange round <-> period diff --git a/libraries/core_libs/consensus/include/vote_manager/vote_manager.hpp b/libraries/core_libs/consensus/include/vote_manager/vote_manager.hpp index 7c5654d584..88346344ff 100644 --- a/libraries/core_libs/consensus/include/vote_manager/vote_manager.hpp +++ b/libraries/core_libs/consensus/include/vote_manager/vote_manager.hpp @@ -341,7 +341,7 @@ class VoteManager { mutable boost::shared_mutex verified_votes_access_; // >><> - // For next votes we enable 2 votes per round & step, one of which must be vote for NULL_BLOCK_HASH + // For next votes we enable 2 votes per round & step, one of which must be vote for kNullBlockHash std::map DagManager::getGhostPath(const blk_hash_t &source) const { - // No need to check ghost path for NULL_BLOCK_HASH - if (source == NULL_BLOCK_HASH) { + // No need to check ghost path for kNullBlockHash + if (source == kNullBlockHash) { return {}; } @@ -309,9 +307,9 @@ uint DagManager::setDagBlockOrder(blk_hash_t const &new_anchor, PbftPeriod perio return 0; } - if (new_anchor == NULL_BLOCK_HASH) { + if (new_anchor == kNullBlockHash) { period_ = period; - LOG(log_nf_) << "Set new period " << period << " with NULL_BLOCK_HASH anchor"; + LOG(log_nf_) << "Set new period " << period << " with kNullBlockHash anchor"; return 0; } @@ -347,7 +345,7 @@ uint DagManager::setDagBlockOrder(blk_hash_t const &new_anchor, PbftPeriod perio std::unordered_set dag_order_set(dag_order.begin(), dag_order.end()); assert(dag_order_set.count(new_anchor)); - addToDag(new_anchor, blk_hash_t(), vec_blk_t(), 0, true); + addToDag(new_anchor, kNullBlockHash, vec_blk_t(), 0, true); const auto anchor_block_level = getDagBlock(new_anchor)->getLevel(); if (anchor_block_level > dag_expiry_limit_) { @@ -458,7 +456,7 @@ void DagManager::recoverDag() { if (anchor) { anchor_ = anchor; LOG(log_nf_) << "Recover anchor " << anchor_; - addToDag(anchor_, blk_hash_t(), vec_blk_t(), 0, true); + addToDag(anchor_, kNullBlockHash, vec_blk_t(), 0, true); break; } } diff --git a/libraries/core_libs/consensus/src/final_chain/final_chain.cpp b/libraries/core_libs/consensus/src/final_chain/final_chain.cpp index a720157880..d05af8e977 100644 --- a/libraries/core_libs/consensus/src/final_chain/final_chain.cpp +++ b/libraries/core_libs/consensus/src/final_chain/final_chain.cpp @@ -18,7 +18,7 @@ class FinalChainImpl final : public FinalChain { StateAPI state_api_; // It is not prepared to use more then 1 thread. Examine it if you want to change threads count - util::ThreadPool executor_thread_{1}; + boost::asio::thread_pool executor_thread_{1}; std::atomic num_executed_dag_blk_ = 0; std::atomic num_executed_trx_ = 0; @@ -60,7 +60,6 @@ class FinalChainImpl final : public FinalChain { [this](uint64_t blk) { return get_transaction_hashes(blk); }), accounts_cache_(config.final_chain_cache_in_blocks, [this](uint64_t blk, const addr_t& addr) { return state_api_.get_account(blk, addr); }), - total_vote_count_cache_(config.final_chain_cache_in_blocks, [this](uint64_t blk) { return state_api_.dpos_eligible_total_vote_count(blk); }), dpos_vote_count_cache_( @@ -115,15 +114,15 @@ class FinalChainImpl final : public FinalChain { delegation_delay_ = config.genesis.state.dpos.delegation_delay; } - void stop() override { executor_thread_.stop(); } + void stop() override { executor_thread_.join(); } - std::future> finalize(PeriodData&& new_blk, + std::future> finalize(PeriodData&& new_blk, std::vector&& finalized_dag_blk_hashes, finalize_precommit_ext precommit_ext = {}) override { - auto p = std::make_shared>>(); - executor_thread_.post([this, new_blk = std::move(new_blk), - finalized_dag_blk_hashes = std::move(finalized_dag_blk_hashes), - precommit_ext = std::move(precommit_ext), p]() mutable { + auto p = std::make_shared>>(); + boost::asio::post(executor_thread_, [this, new_blk = std::move(new_blk), + finalized_dag_blk_hashes = std::move(finalized_dag_blk_hashes), + precommit_ext = std::move(precommit_ext), p]() mutable { p->set_value(finalize_(std::move(new_blk), std::move(finalized_dag_blk_hashes), precommit_ext)); }); return p->get_future(); @@ -131,8 +130,9 @@ class FinalChainImpl final : public FinalChain { EthBlockNumber delegation_delay() const override { return delegation_delay_; } - std::shared_ptr finalize_(PeriodData&& new_blk, std::vector&& finalized_dag_blk_hashes, - finalize_precommit_ext const& precommit_ext) { + std::shared_ptr finalize_(PeriodData&& new_blk, + std::vector&& finalized_dag_blk_hashes, + finalize_precommit_ext const& precommit_ext) { auto batch = db_->createWriteBatch(); RewardsStats rewards_stats; diff --git a/libraries/core_libs/consensus/src/pbft/pbft_chain.cpp b/libraries/core_libs/consensus/src/pbft/pbft_chain.cpp index d72c01b20c..cdf4eeeebd 100644 --- a/libraries/core_libs/consensus/src/pbft/pbft_chain.cpp +++ b/libraries/core_libs/consensus/src/pbft/pbft_chain.cpp @@ -10,11 +10,7 @@ using namespace std; namespace taraxa { PbftChain::PbftChain(addr_t node_addr, std::shared_ptr db) - : head_hash_(blk_hash_t(0)), - size_(0), - non_empty_size_(0), - last_pbft_block_hash_(blk_hash_t(0)), - db_(std::move(db)) { + : size_(0), non_empty_size_(0), db_(std::move(db)) { LOG_OBJECTS_CREATE("PBFT_CHAIN"); // Get PBFT head from DB auto pbft_head_str = db_->getPbftHead(head_hash_); @@ -88,7 +84,7 @@ PbftBlock PbftChain::getPbftBlockInChain(const taraxa::blk_hash_t& pbft_block_ha void PbftChain::updatePbftChain(blk_hash_t const& pbft_block_hash, blk_hash_t const& anchor_hash) { UniqueLock lock(chain_head_access_); size_++; - if (anchor_hash != NULL_BLOCK_HASH) { + if (anchor_hash != kNullBlockHash) { non_empty_size_++; last_non_null_pbft_dag_anchor_hash_ = anchor_hash; } diff --git a/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp b/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp index 9b7a1b0063..a0078f0efd 100644 --- a/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp +++ b/libraries/core_libs/consensus/src/pbft/pbft_manager.cpp @@ -617,7 +617,7 @@ void PbftManager::initialState() { previous_round_next_voted_null_block_hash_ = next_votes_manager_->haveEnoughVotesForNullBlockHash(); LOG(log_nf_) << "Node initialize at round " << current_pbft_round << ", period " << getPbftPeriod() << ", step " - << current_pbft_step << ". Previous round has enough next votes for NULL_BLOCK_HASH: " << std::boolalpha + << current_pbft_step << ". Previous round has enough next votes for kNullBlockHash: " << std::boolalpha << previous_round_next_voted_null_block_hash_ << ", voted value " << (previous_round_next_voted_value_.has_value() ? previous_round_next_voted_value_->abridged() : "no value") @@ -932,7 +932,7 @@ void PbftManager::proposeBlock_() { if (round == 1 || previous_round_next_voted_null_block_hash_) { if (round > 1) { - LOG(log_nf_) << "Previous round " << round - 1 << " had next voted NULL_BLOCK_HASH"; + LOG(log_nf_) << "Previous round " << round - 1 << " had next voted kNullBlockHash"; } proposed_block_ = proposePbftBlock_(); @@ -1084,7 +1084,7 @@ void PbftManager::firstFinish_() { } else if (round >= 2 && previous_round_next_voted_null_block_hash_) { // Starting value in round 1 is always null block hash... So combined with other condition for next // voting null block hash... - if (auto vote = generateVoteWithWeight(NULL_BLOCK_HASH, PbftVoteTypes::next_vote, period, round, step_); vote) { + if (auto vote = generateVoteWithWeight(kNullBlockHash, PbftVoteTypes::next_vote, period, round, step_); vote) { placeVote(vote, "first finish next vote", nullptr); } } else { @@ -1101,12 +1101,12 @@ void PbftManager::firstFinish_() { } starting_value = {*previous_round_next_voted_value_, std::move(block)}; - } else { // for round == 1, starting value is always NULL_BLOCK_HASH and previous_round_next_voted_null_block_hash_ + } else { // for round == 1, starting value is always kNullBlockHash and previous_round_next_voted_null_block_hash_ // should be == false - // This should never happen as round >= 2 && previous_round_next_voted_block == NULL_BLOCK_HASH is covered in + // This should never happen as round >= 2 && previous_round_next_voted_block == kNullBlockHash is covered in // previous "else if" condition assert(!previous_round_next_voted_null_block_hash_); - starting_value = {NULL_BLOCK_HASH, nullptr}; + starting_value = {kNullBlockHash, nullptr}; } if (auto vote = generateVoteWithWeight(starting_value.first, PbftVoteTypes::next_vote, period, round, step_); @@ -1156,7 +1156,7 @@ void PbftManager::secondFinish_() { if (!already_next_voted_null_block_hash_ && round >= 2 && previous_round_next_voted_null_block_hash_ && !cert_voted_block_for_round_.has_value()) { - if (auto vote = generateVoteWithWeight(NULL_BLOCK_HASH, PbftVoteTypes::next_vote, period, round, step_); vote) { + if (auto vote = generateVoteWithWeight(kNullBlockHash, PbftVoteTypes::next_vote, period, round, step_); vote) { if (placeVote(vote, "second finish next vote", nullptr)) { db_->savePbftMgrStatus(PbftMgrStatus::NextVotedNullBlockHash, true); already_next_voted_null_block_hash_ = true; @@ -1175,15 +1175,19 @@ std::shared_ptr PbftManager::generatePbftBlock(PbftPeriod propose_per std::vector reward_votes_hashes; std::transform(reward_votes.begin(), reward_votes.end(), std::back_inserter(reward_votes_hashes), [](const auto &v) { return v->getHash(); }); - return std::make_shared(prev_blk_hash, anchor_hash, order_hash, propose_period, node_addr_, node_sk_, - std::move(reward_votes_hashes)); + h256 last_state_root; + if (propose_period > config_.state_root_recording_delay) { + last_state_root = final_chain_->block_header(propose_period - config_.state_root_recording_delay)->state_root; + } + return std::make_shared(prev_blk_hash, anchor_hash, order_hash, last_state_root, propose_period, + node_addr_, node_sk_, std::move(reward_votes_hashes)); } -std::shared_ptr PbftManager::generateVote(const blk_hash_t &blockhash, PbftVoteTypes type, PbftPeriod period, +std::shared_ptr PbftManager::generateVote(const blk_hash_t &block_hash, PbftVoteTypes type, PbftPeriod period, PbftRound round, PbftStep step) { // sortition proof VrfPbftSortition vrf_sortition(vrf_sk_, {type, period, round, step}); - return std::make_shared(node_sk_, std::move(vrf_sortition), blockhash); + return std::make_shared(node_sk_, std::move(vrf_sortition), block_hash); } std::pair PbftManager::validateVote(const std::shared_ptr &vote) const { @@ -1319,7 +1323,7 @@ std::shared_ptr PbftManager::generateVoteWithWeight(taraxa::blk_hash_t con blk_hash_t PbftManager::calculateOrderHash(const std::vector &dag_block_hashes) { if (dag_block_hashes.empty()) { - return NULL_BLOCK_HASH; + return kNullBlockHash; } dev::RLPStream order_stream(1); order_stream.appendList(dag_block_hashes.size()); @@ -1331,7 +1335,7 @@ blk_hash_t PbftManager::calculateOrderHash(const std::vector &dag_bl blk_hash_t PbftManager::calculateOrderHash(const std::vector &dag_blocks) { if (dag_blocks.empty()) { - return NULL_BLOCK_HASH; + return kNullBlockHash; } dev::RLPStream order_stream(1); order_stream.appendList(dag_blocks.size()); @@ -1382,7 +1386,7 @@ std::shared_ptr PbftManager::proposePbftBlock_() { auto last_pbft_block_hash = pbft_chain_->getLastPbftBlockHash(); auto last_period_dag_anchor_block_hash = pbft_chain_->getLastNonNullPbftBlockAnchor(); - if (last_period_dag_anchor_block_hash == NULL_BLOCK_HASH) { + if (last_period_dag_anchor_block_hash == kNullBlockHash) { last_period_dag_anchor_block_hash = dag_genesis_block_hash_; } @@ -1391,7 +1395,7 @@ std::shared_ptr PbftManager::proposePbftBlock_() { // Looks like ghost never empty, at least include the last period dag anchor block if (ghost.empty()) { LOG(log_dg_) << "GHOST is empty. No new DAG blocks generated, PBFT propose NULL BLOCK HASH anchor"; - return generatePbftBlock(current_pbft_period, last_pbft_block_hash, NULL_BLOCK_HASH, NULL_BLOCK_HASH); + return generatePbftBlock(current_pbft_period, last_pbft_block_hash, kNullBlockHash, kNullBlockHash); } blk_hash_t dag_block_hash; @@ -1412,7 +1416,7 @@ std::shared_ptr PbftManager::proposePbftBlock_() { if (dag_block_hash == dag_genesis_block_hash_) { LOG(log_dg_) << "No new DAG blocks generated. DAG only has genesis " << dag_block_hash << " PBFT propose NULL BLOCK HASH anchor"; - return generatePbftBlock(current_pbft_period, last_pbft_block_hash, NULL_BLOCK_HASH, NULL_BLOCK_HASH); + return generatePbftBlock(current_pbft_period, last_pbft_block_hash, kNullBlockHash, kNullBlockHash); } // Compare with last dag block hash. If they are same, which means no new dag blocks generated since last round. In @@ -1421,7 +1425,7 @@ std::shared_ptr PbftManager::proposePbftBlock_() { LOG(log_dg_) << "Last period DAG anchor block hash " << dag_block_hash << " No new DAG blocks generated, PBFT propose NULL BLOCK HASH anchor"; LOG(log_dg_) << "Ghost: " << ghost; - return generatePbftBlock(current_pbft_period, last_pbft_block_hash, NULL_BLOCK_HASH, NULL_BLOCK_HASH); + return generatePbftBlock(current_pbft_period, last_pbft_block_hash, kNullBlockHash, kNullBlockHash); } // get DAG block and transaction order @@ -1513,7 +1517,7 @@ std::shared_ptr PbftManager::identifyLeaderBlock_(PbftRound round, Pb } const auto proposed_block_hash = v->getBlockHash(); - if (proposed_block_hash == NULL_BLOCK_HASH) { + if (proposed_block_hash == kNullBlockHash) { LOG(log_er_) << "Propose block hash should not be NULL. Vote " << v; continue; } @@ -1536,7 +1540,7 @@ std::shared_ptr PbftManager::identifyLeaderBlock_(PbftRound round, Pb continue; } - if (leader_block->getPivotDagBlockHash() == NULL_BLOCK_HASH && empty_leader_block == nullptr) { + if (leader_block->getPivotDagBlockHash() == kNullBlockHash && empty_leader_block == nullptr) { empty_leader_block = leader_block; continue; } @@ -1560,6 +1564,20 @@ bool PbftManager::validatePbftBlock(const std::shared_ptr &pbft_block auto const &pbft_block_hash = pbft_block->getBlockHash(); + auto period = pbft_block->getPeriod(); + + { + h256 prev_state_root_hash; + if (period > config_.state_root_recording_delay) { + prev_state_root_hash = final_chain_->block_header(period - config_.state_root_recording_delay)->state_root; + } + if (pbft_block->getPrevStateRoot() != prev_state_root_hash) { + LOG(log_er_) << "Block " << pbft_block_hash << " state root " << pbft_block->getPrevStateRoot() + << " isn't matching actual " << prev_state_root_hash; + return false; + } + } + // Vadliates reward votes if (!vote_mgr_->checkRewardVotes(pbft_block)) { LOG(log_er_) << "Failed verifying reward votes for proposed PBFT block " << pbft_block_hash; @@ -1567,7 +1585,7 @@ bool PbftManager::validatePbftBlock(const std::shared_ptr &pbft_block } auto const &anchor_hash = pbft_block->getPivotDagBlockHash(); - if (anchor_hash == NULL_BLOCK_HASH) { + if (anchor_hash == kNullBlockHash) { return true; } @@ -1617,7 +1635,7 @@ bool PbftManager::pushCertVotedPbftBlockIntoChain_(const std::shared_ptr> &¤t_round_cert_votes) { PeriodData period_data; period_data.pbft_blk = pbft_block; - if (pbft_block->getPivotDagBlockHash() != NULL_BLOCK_HASH) { + if (pbft_block->getPivotDagBlockHash() != kNullBlockHash) { auto dag_order_it = anchor_dag_block_order_cache_.find(pbft_block->getPivotDagBlockHash()); assert(dag_order_it != anchor_dag_block_order_cache_.end()); std::unordered_set trx_set; @@ -1736,7 +1754,7 @@ void PbftManager::finalize_(PeriodData &&period_data, std::vector &&finali auto result = final_chain_->finalize( std::move(period_data), std::move(finalized_dag_blk_hashes), [this, weak_ptr = weak_from_this(), anchor_hash = anchor, period = period_data.pbft_blk->getPeriod()]( - auto const &, auto &batch) { + const auto &, auto &batch) { // Update proposal period DAG levels map auto ptr = weak_ptr.lock(); if (!ptr) return; // it was destroyed @@ -1765,7 +1783,7 @@ bool PbftManager::pushPbftBlock_(PeriodData &&period_data, std::vectorpbftBlockInDb(pbft_block_hash)) { LOG(log_nf_) << "PBFT block: " << pbft_block_hash << " in DB already."; if (cert_voted_block_for_round_.has_value() && (*cert_voted_block_for_round_)->getBlockHash() == pbft_block_hash) { - LOG(log_er_) << "Last cert voted value should be NULL_BLOCK_HASH. Block hash " + LOG(log_er_) << "Last cert voted value should be kNullBlockHash. Block hash " << (*cert_voted_block_for_round_)->getBlockHash() << " has been pushed into chain already"; assert(false); } @@ -1776,7 +1794,7 @@ bool PbftManager::pushPbftBlock_(PeriodData &&period_data, std::vectorgetBlockHash()); auto pbft_period = period_data.pbft_blk->getPeriod(); - auto null_anchor = period_data.pbft_blk->getPivotDagBlockHash() == NULL_BLOCK_HASH; + auto null_anchor = period_data.pbft_blk->getPivotDagBlockHash() == kNullBlockHash; auto batch = db_->createWriteBatch(); @@ -1795,7 +1813,7 @@ bool PbftManager::pushPbftBlock_(PeriodData &&period_data, std::vectoraddLastBlockCertVotesToBatch(cert_votes, reward_votes, batch); // pass pbft with dag blocks and transactions to adjust difficulty - if (period_data.pbft_blk->getPivotDagBlockHash() != NULL_BLOCK_HASH) { + if (period_data.pbft_blk->getPivotDagBlockHash() != kNullBlockHash) { dag_mgr_->sortitionParamsManager().pbftBlockPushed(period_data, batch, pbft_chain_->getPbftChainSizeExcludingEmptyPbftBlocks() + 1); } diff --git a/libraries/core_libs/consensus/src/vote_manager/vote_manager.cpp b/libraries/core_libs/consensus/src/vote_manager/vote_manager.cpp index 85507d4685..771d3db109 100644 --- a/libraries/core_libs/consensus/src/vote_manager/vote_manager.cpp +++ b/libraries/core_libs/consensus/src/vote_manager/vote_manager.cpp @@ -218,16 +218,16 @@ std::pair VoteManager::isUniqueVote(const std::shared_ptrgetType() == PbftVoteTypes::next_vote) { // New second next vote if (found_voter_it->second.second == nullptr) { - // One of the next votes == NULL_BLOCK_HASH -> valid scenario - if (found_voter_it->second.first->getBlockHash() == NULL_BLOCK_HASH && vote->getBlockHash() != NULL_BLOCK_HASH) { + // One of the next votes == kNullBlockHash -> valid scenario + if (found_voter_it->second.first->getBlockHash() == kNullBlockHash && vote->getBlockHash() != kNullBlockHash) { return {true, ""}; - } else if (found_voter_it->second.first->getBlockHash() != NULL_BLOCK_HASH && - vote->getBlockHash() == NULL_BLOCK_HASH) { + } else if (found_voter_it->second.first->getBlockHash() != kNullBlockHash && + vote->getBlockHash() == kNullBlockHash) { return {true, ""}; } } else if (found_voter_it->second.second->getHash() == vote->getHash()) { @@ -276,18 +276,18 @@ bool VoteManager::insertUniqueVote(const std::shared_ptr& vote) { // There was already some vote inserted, check if it is the same vote as we are trying to insert if (inserted_vote.first->second.first->getHash() != vote->getHash()) { - // Next votes (second finishing steps) are special case, where we allow voting for both NULL_BLOCK_HASH and + // Next votes (second finishing steps) are special case, where we allow voting for both kNullBlockHash and // some other specific block hash at the same time -> 2 unique votes per round & step & voter if (vote->getType() == PbftVoteTypes::next_vote && vote->getStep() % 2) { // New second next vote if (inserted_vote.first->second.second == nullptr) { - // One of the next votes == NULL_BLOCK_HASH -> valid scenario - if (inserted_vote.first->second.first->getBlockHash() == NULL_BLOCK_HASH && - vote->getBlockHash() != NULL_BLOCK_HASH) { + // One of the next votes == kNullBlockHash -> valid scenario + if (inserted_vote.first->second.first->getBlockHash() == kNullBlockHash && + vote->getBlockHash() != kNullBlockHash) { inserted_vote.first->second.second = vote; return true; - } else if (inserted_vote.first->second.first->getBlockHash() != NULL_BLOCK_HASH && - vote->getBlockHash() == NULL_BLOCK_HASH) { + } else if (inserted_vote.first->second.first->getBlockHash() != kNullBlockHash && + vote->getBlockHash() == kNullBlockHash) { inserted_vote.first->second.second = vote; return true; } @@ -791,7 +791,7 @@ size_t NextVotesManager::getNextVotesWeight() const { // Assumption is that all votes are validated, in next voting phase, in the same round. // Votes for same voted value are in the same step -// Voted values have maximum 2 PBFT block hashes, NULL_BLOCK_HASH and a non NULL_BLOCK_HASH +// Voted values have maximum 2 PBFT block hashes, kNullBlockHash and a non kNullBlockHash void NextVotesManager::addNextVotes(std::vector> const& next_votes, size_t pbft_2t_plus_1) { if (next_votes.empty()) { return; @@ -860,7 +860,7 @@ void NextVotesManager::addNextVotes(std::vector> const& ne LOG(log_dg_) << "Voted PBFT block hash " << voted_value << " has enough " << voted_value_next_votes_size << " next votes"; - if (voted_value == NULL_BLOCK_HASH) { + if (voted_value == kNullBlockHash) { enough_votes_for_null_block_hash_ = true; } else { if (voted_value_.has_value() && voted_value != *voted_value_) { @@ -928,7 +928,7 @@ void NextVotesManager::updateNextVotes(std::vector> const& LOG(log_nf_) << "Voted PBFT block hash " << it->first << " has " << next_votes_weight_[it->first] << " next votes"; - if (it->first == NULL_BLOCK_HASH) { + if (it->first == kNullBlockHash) { enough_votes_for_null_block_hash_ = true; } else { if (voted_value_.has_value()) { @@ -969,7 +969,7 @@ void NextVotesManager::updateNextVotes(std::vector> const& } // Assumption is that all synced votes are in next voting phase, in the same round. -// Valid voted values have maximum 2 block hash, NULL_BLOCK_HASH and a non NULL_BLOCK_HASH +// Valid voted values have maximum 2 block hash, kNullBlockHash and a non kNullBlockHash void NextVotesManager::updateWithSyncedVotes(std::vector>& next_votes, size_t pbft_2t_plus_1) { if (next_votes.empty()) { LOG(log_er_) << "Synced next votes is empty."; @@ -1065,7 +1065,7 @@ void NextVotesManager::assertError_(std::vector> next_vote return; } - LOG(log_er_) << "There are more than one voted values on non NULL_BLOCK_HASH have 2t+1 next votes."; + LOG(log_er_) << "There are more than one voted values on non kNullBlockHash have 2t+1 next votes."; LOG(log_er_) << "Voted value " << next_votes_1[0]->getBlockHash(); for (auto const& v : next_votes_1) { diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/votes_sync_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/votes_sync_packet_handler.cpp index 6c4a9f26e3..b88e8c73e9 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/votes_sync_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/votes_sync_packet_handler.cpp @@ -23,7 +23,7 @@ void VotesSyncPacketHandler::validatePacketRlpFormat([[maybe_unused]] const Pack } void VotesSyncPacketHandler::process(const PacketData &packet_data, const std::shared_ptr &peer) { - // We already have 2t+1 votes for both NULL_BLOCK_HASH as well as some specific block hash + // We already have 2t+1 votes for both kNullBlockHash as well as some specific block hash if (next_votes_mgr_->enoughNextVotes()) { LOG(log_nf_) << "Already have enought next votes for perevious round."; return; @@ -51,16 +51,16 @@ void VotesSyncPacketHandler::process(const PacketData &packet_data, const std::s } std::vector> next_votes; - blk_hash_t voted_value = NULL_BLOCK_HASH; + blk_hash_t voted_value = kNullBlockHash; const auto next_votes_count = packet_data.rlp_.itemCount(); // It is done in separate cycle because we don't need to process this next_votes if some of checks will fail for (size_t i = 0; i < next_votes_count; i++) { auto vote = std::make_shared(packet_data.rlp_[i].data().toBytes()); - if (voted_value == NULL_BLOCK_HASH && vote->getBlockHash() != NULL_BLOCK_HASH) { - // initialize voted value with first block hash that not equal to NULL_BLOCK_HASH + if (voted_value == kNullBlockHash && vote->getBlockHash() != kNullBlockHash) { + // initialize voted value with first block hash that not equal to kNullBlockHash voted_value = vote->getBlockHash(); - } else if (vote->getBlockHash() != NULL_BLOCK_HASH && voted_value != NULL_BLOCK_HASH && + } else if (vote->getBlockHash() != kNullBlockHash && voted_value != kNullBlockHash && vote->getBlockHash() != voted_value) { // we see different voted value, so bundle is invalid LOG(log_er_) << "Received next votes bundle with unmatched voted values(" << voted_value << ", " diff --git a/libraries/core_libs/storage/src/storage.cpp b/libraries/core_libs/storage/src/storage.cpp index 96fc0e5e35..04b48d05af 100644 --- a/libraries/core_libs/storage/src/storage.cpp +++ b/libraries/core_libs/storage/src/storage.cpp @@ -320,7 +320,7 @@ std::map> DbStorage::getNonfinalizedDagBlocks() { auto i = std::unique_ptr(db_->NewIterator(read_options_, handle(Columns::dag_blocks))); for (i->SeekToFirst(); i->Valid(); i->Next()) { DagBlock block(asBytes(i->value().ToString())); - if (block.getPivot() != blk_hash_t(0)) { + if (block.getPivot() != kNullBlockHash) { res[block.getLevel()].emplace_back(std::move(block)); } } @@ -357,7 +357,7 @@ void DbStorage::updateDagBlockCounters(std::vector blks) { insert(write_batch, Columns::dag_blocks_index, toSlice(level), toSlice(blocks_stream.out())); dag_blocks_count_.fetch_add(1); // Do not count genesis pivot field - if (blk.getPivot() == blk_hash_t(0)) { + if (blk.getPivot() == kNullBlockHash) { dag_edge_count_.fetch_add(blk.getTips().size()); } else { dag_edge_count_.fetch_add(blk.getTips().size() + 1); @@ -389,7 +389,7 @@ void DbStorage::saveDagBlock(DagBlock const& blk, Batch* write_batch_p) { dag_blocks_count_.fetch_add(1); insert(write_batch, Columns::status, toSlice((uint8_t)StatusDbField::DagBlkCount), toSlice(dag_blocks_count_.load())); // Do not count genesis pivot field - if (blk.getPivot() == blk_hash_t(0)) { + if (blk.getPivot() == kNullBlockHash) { dag_edge_count_.fetch_add(blk.getTips().size()); } else { dag_edge_count_.fetch_add(blk.getTips().size() + 1); diff --git a/libraries/types/pbft_block/include/pbft/pbft_block.hpp b/libraries/types/pbft_block/include/pbft/pbft_block.hpp index 182c9b3f35..ccfcd6b8a3 100644 --- a/libraries/types/pbft_block/include/pbft/pbft_block.hpp +++ b/libraries/types/pbft_block/include/pbft/pbft_block.hpp @@ -25,6 +25,7 @@ class PbftBlock { blk_hash_t prev_block_hash_; blk_hash_t dag_block_hash_as_pivot_; blk_hash_t order_hash_; + blk_hash_t prev_state_root_hash_; PbftPeriod period_; // Block index, PBFT head block is period 0, first PBFT block is period 1 uint64_t timestamp_; addr_t beneficiary_; @@ -33,7 +34,8 @@ class PbftBlock { public: PbftBlock(const blk_hash_t& prev_blk_hash, const blk_hash_t& dag_blk_hash_as_pivot, const blk_hash_t& order_hash, - PbftPeriod period, const addr_t& beneficiary, const secret_t& sk, std::vector&& reward_votes_); + const blk_hash_t& prev_state_root, PbftPeriod period, const addr_t& beneficiary, const secret_t& sk, + std::vector&& reward_votes); explicit PbftBlock(dev::RLP const& rlp); explicit PbftBlock(bytes const& RLP); @@ -102,6 +104,8 @@ class PbftBlock { */ auto const& getOrderHash() const { return order_hash_; } + auto const& getPrevStateRoot() const { return prev_state_root_hash_; } + /** * @brief Get period number * @return period number diff --git a/libraries/types/pbft_block/src/pbft_block.cpp b/libraries/types/pbft_block/src/pbft_block.cpp index 9a99096ee0..94668acbee 100644 --- a/libraries/types/pbft_block/src/pbft_block.cpp +++ b/libraries/types/pbft_block/src/pbft_block.cpp @@ -10,17 +10,18 @@ namespace taraxa { PbftBlock::PbftBlock(bytes const& b) : PbftBlock(dev::RLP(b)) {} PbftBlock::PbftBlock(dev::RLP const& rlp) { - util::rlp_tuple(util::RLPDecoderRef(rlp, true), prev_block_hash_, dag_block_hash_as_pivot_, order_hash_, period_, - timestamp_, reward_votes_, signature_); + util::rlp_tuple(util::RLPDecoderRef(rlp, true), prev_block_hash_, dag_block_hash_as_pivot_, order_hash_, + prev_state_root_hash_, period_, timestamp_, reward_votes_, signature_); calculateHash_(); } PbftBlock::PbftBlock(const blk_hash_t& prev_blk_hash, const blk_hash_t& dag_blk_hash_as_pivot, - const blk_hash_t& order_hash, uint64_t period, const addr_t& beneficiary, const secret_t& sk, - std::vector&& reward_votes) + const blk_hash_t& order_hash, const blk_hash_t& prev_state_root, PbftPeriod period, + const addr_t& beneficiary, const secret_t& sk, std::vector&& reward_votes) : prev_block_hash_(prev_blk_hash), dag_block_hash_as_pivot_(dag_blk_hash_as_pivot), order_hash_(order_hash), + prev_state_root_hash_(prev_state_root), period_(period), beneficiary_(beneficiary), reward_votes_(reward_votes) { @@ -61,6 +62,7 @@ Json::Value PbftBlock::getJson() const { json["prev_block_hash"] = prev_block_hash_.toString(); json["dag_block_hash_as_pivot"] = dag_block_hash_as_pivot_.toString(); json["order_hash"] = order_hash_.toString(); + json["prev_state_root_hash"] = prev_state_root_hash_.toString(); json["period"] = (Json::Value::UInt64)period_; json["timestamp"] = (Json::Value::UInt64)timestamp_; json["block_hash"] = block_hash_.toString(); @@ -76,10 +78,11 @@ Json::Value PbftBlock::getJson() const { // Using to setup PBFT block hash void PbftBlock::streamRLP(dev::RLPStream& strm, bool include_sig) const { - strm.appendList(include_sig ? 7 : 6); + strm.appendList(include_sig ? 8 : 7); strm << prev_block_hash_; strm << dag_block_hash_as_pivot_; strm << order_hash_; + strm << prev_state_root_hash_; strm << period_; strm << timestamp_; strm.appendVector(reward_votes_); diff --git a/libraries/types/vote/include/vote/vote.hpp b/libraries/types/vote/include/vote/vote.hpp index 606c5b585f..f27f76711d 100644 --- a/libraries/types/vote/include/vote/vote.hpp +++ b/libraries/types/vote/include/vote/vote.hpp @@ -187,11 +187,11 @@ class Vote { * step, the total votes weights must be greater or equal to PBFT 2t+1. */ struct VotesBundle { - blk_hash_t voted_block_hash{blk_hash_t(0)}; + blk_hash_t voted_block_hash; PbftPeriod votes_period{0}; std::vector> votes; // Greater than 2t+1 votes - VotesBundle() : voted_block_hash(blk_hash_t(0)) {} + VotesBundle() {} VotesBundle(blk_hash_t const& voted_block_hash, std::vector> const& votes) : voted_block_hash(voted_block_hash), votes(votes) {} }; diff --git a/tests/crypto_test.cpp b/tests/crypto_test.cpp index d7011b815a..545dee45e1 100644 --- a/tests/crypto_test.cpp +++ b/tests/crypto_test.cpp @@ -185,7 +185,7 @@ TEST_F(CryptoTest, DISABLED_compute_vdf_solution_cost_time) { uint16_t difficulty_min = 0; uint16_t difficulty_max = 0; uint16_t lambda_bound = 100; - blk_hash_t proposal_dag_block_pivot_hash1 = blk_hash_t(0); + blk_hash_t proposal_dag_block_pivot_hash1; blk_hash_t proposal_dag_block_pivot_hash2 = blk_hash_t("c9524784c4bf29e6facdd94ef7d214b9f512cdfd0f68184432dab85d053cbc69"); blk_hash_t proposal_dag_block_pivot_hash3 = diff --git a/tests/final_chain_test.cpp b/tests/final_chain_test.cpp index 1a20fac8c2..91eb802d74 100644 --- a/tests/final_chain_test.cpp +++ b/tests/final_chain_test.cpp @@ -53,8 +53,9 @@ struct FinalChainTest : WithDataDir { DagBlock dag_blk({}, {}, {}, trx_hashes, {}, {}, secret_t::random()); db->saveDagBlock(dag_blk); std::vector reward_votes_hashes; - auto pbft_block = std::make_shared(blk_hash_t(), blk_hash_t(), blk_hash_t(), 1, addr_t::random(), - dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); + auto pbft_block = + std::make_shared(kNullBlockHash, kNullBlockHash, kNullBlockHash, kNullBlockHash, 1, addr_t::random(), + dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); std::vector> votes; PeriodData period_data(pbft_block, votes); period_data.dag_blocks.push_back(dag_blk); diff --git a/tests/full_node_test.cpp b/tests/full_node_test.cpp index fb6e4944f8..f23a4e19b0 100644 --- a/tests/full_node_test.cpp +++ b/tests/full_node_test.cpp @@ -201,7 +201,7 @@ TEST_F(FullNodeTest, db_test) { EXPECT_EQ(db.getCertVotedBlockInRound(), std::nullopt); // pbft_blocks and cert votes - EXPECT_FALSE(db.pbftBlockInDb(blk_hash_t(0))); + EXPECT_FALSE(db.pbftBlockInDb(kNullBlockHash)); EXPECT_FALSE(db.pbftBlockInDb(blk_hash_t(1))); auto pbft_block1 = make_simple_pbft_block(blk_hash_t(1), 2); auto pbft_block2 = make_simple_pbft_block(blk_hash_t(2), 3); @@ -1503,7 +1503,7 @@ TEST_F(FullNodeTest, clear_period_data) { uint64_t last_anchor_level; for (uint64_t i = 0; i < nodes[0]->getPbftChain()->getPbftChainSize(); i++) { const auto pbft_block = nodes[0]->getDB()->getPbftBlock(i); - if (pbft_block && pbft_block->getPivotDagBlockHash() != NULL_BLOCK_HASH) { + if (pbft_block && pbft_block->getPivotDagBlockHash() != kNullBlockHash) { non_empty_counter++; last_anchor_level = nodes[0]->getDB()->getDagBlock(pbft_block->getPivotDagBlockHash())->getLevel(); } @@ -1511,7 +1511,7 @@ TEST_F(FullNodeTest, clear_period_data) { uint32_t first_over_limit = 0; for (uint64_t i = 0; i < nodes[1]->getPbftChain()->getPbftChainSize(); i++) { const auto pbft_block = nodes[1]->getDB()->getPbftBlock(i); - if (pbft_block && pbft_block->getPivotDagBlockHash() != NULL_BLOCK_HASH) { + if (pbft_block && pbft_block->getPivotDagBlockHash() != kNullBlockHash) { if (nodes[1]->getDB()->getDagBlock(pbft_block->getPivotDagBlockHash())->getLevel() + node_cfgs[0].dag_expiry_limit >= last_anchor_level) { diff --git a/tests/network_test.cpp b/tests/network_test.cpp index b8b3a85846..6c9b1d25c2 100644 --- a/tests/network_test.cpp +++ b/tests/network_test.cpp @@ -164,9 +164,9 @@ TEST_F(NetworkTest, DISABLED_update_peer_chainsize) { auto nw2 = nodes[1]->getNetwork(); std::vector reward_votes{}; - auto pbft_block = - std::make_shared(blk_hash_t(1), blk_hash_t(0), blk_hash_t(0), node1->getPbftManager()->getPbftPeriod(), - node1->getAddress(), node1->getSecretKey(), std::move(reward_votes)); + auto pbft_block = std::make_shared(blk_hash_t(1), kNullBlockHash, kNullBlockHash, kNullBlockHash, + node1->getPbftManager()->getPbftPeriod(), node1->getAddress(), + node1->getSecretKey(), std::move(reward_votes)); auto vote = node1_pbft_mgr->generateVote(pbft_block->getBlockHash(), PbftVoteTypes::propose_vote, pbft_block->getPeriod(), node1_pbft_mgr->getPbftRound() + 1, value_proposal_state); @@ -545,8 +545,8 @@ TEST_F(NetworkTest, node_pbft_sync) { order_stream.appendList(1); order_stream << blk1.getHash(); - PbftBlock pbft_block1(prev_block_hash, blk1.getHash(), dev::sha3(order_stream.out()), period, beneficiary, - node1->getSecretKey(), {}); + PbftBlock pbft_block1(prev_block_hash, blk1.getHash(), dev::sha3(order_stream.out()), kNullBlockHash, period, + beneficiary, node1->getSecretKey(), {}); std::vector> votes_for_pbft_blk1; votes_for_pbft_blk1.emplace_back( node1->getPbftManager()->generateVote(pbft_block1.getBlockHash(), PbftVoteTypes::cert_vote, 1, 1, 3)); @@ -601,8 +601,8 @@ TEST_F(NetworkTest, node_pbft_sync) { dev::RLPStream order_stream2(1); order_stream2.appendList(1); order_stream2 << blk2.getHash(); - PbftBlock pbft_block2(prev_block_hash, blk2.getHash(), dev::sha3(order_stream2.out()), period, beneficiary, - node1->getSecretKey(), {}); + PbftBlock pbft_block2(prev_block_hash, blk2.getHash(), dev::sha3(order_stream2.out()), kNullBlockHash, period, + beneficiary, node1->getSecretKey(), {}); std::vector> votes_for_pbft_blk2; votes_for_pbft_blk2.emplace_back( node1->getPbftManager()->generateVote(pbft_block2.getBlockHash(), PbftVoteTypes::cert_vote, 2, 2, 3)); @@ -711,8 +711,8 @@ TEST_F(NetworkTest, node_pbft_sync_without_enough_votes) { order_stream.appendList(1); order_stream << blk1.getHash(); - PbftBlock pbft_block1(prev_block_hash, blk1.getHash(), dev::sha3(order_stream.out()), period, beneficiary, - node1->getSecretKey(), {}); + PbftBlock pbft_block1(prev_block_hash, blk1.getHash(), dev::sha3(order_stream.out()), kNullBlockHash, period, + beneficiary, node1->getSecretKey(), {}); std::vector> votes_for_pbft_blk1; votes_for_pbft_blk1.emplace_back( node1->getPbftManager()->generateVote(pbft_block1.getBlockHash(), PbftVoteTypes::cert_vote, 1, 1, 3)); @@ -759,8 +759,8 @@ TEST_F(NetworkTest, node_pbft_sync_without_enough_votes) { order_stream2.appendList(1); order_stream2 << blk2.getHash(); - PbftBlock pbft_block2(prev_block_hash, blk2.getHash(), dev::sha3(order_stream2.out()), period, beneficiary, - node1->getSecretKey(), {}); + PbftBlock pbft_block2(prev_block_hash, blk2.getHash(), dev::sha3(order_stream2.out()), kNullBlockHash, period, + beneficiary, node1->getSecretKey(), {}); std::cout << "Use fake votes for the second PBFT block" << std::endl; // node1 put block2 into pbft chain and use fake votes storing into DB (malicious player) // Add fake votes in DB @@ -886,7 +886,7 @@ TEST_F(NetworkTest, pbft_next_votes_sync_in_same_round_1) { node1_next_votes_mgr->updateNextVotes(next_votes1, node1_pbft_2t_plus_1); EXPECT_EQ(node1_next_votes_mgr->getNextVotesWeight(), next_votes1.size()); - // Generate 1 same next votes with node1, voted same value on NULL_BLOCK_HASH + // Generate 1 same next votes with node1, voted same value on kNullBlockHash blk_hash_t voted_pbft_block_hash2(0); auto vote1 = pbft_mgr1->generateVote(voted_pbft_block_hash2, type, period, round, step); vote1->calculateWeight(1, 1, 1); @@ -934,13 +934,12 @@ TEST_F(NetworkTest, pbft_next_votes_sync_in_same_round_2) { auto node2_pbft_2t_plus_1 = pbft_mgr2->getPbftTwoTPlusOne(node2->getPbftChain()->getPbftChainSize()).value(); EXPECT_EQ(node2_pbft_2t_plus_1, 1); - // Node1 generate 1 next vote voted at NULL_BLOCK_HASH - blk_hash_t voted_pbft_block_hash1(blk_hash_t(0)); + // Node1 generate 1 next vote voted at kNullBlockHash PbftVoteTypes type = PbftVoteTypes::next_vote; PbftPeriod period = 1; PbftRound round = 1; PbftStep step = 5; - auto vote1 = pbft_mgr1->generateVote(voted_pbft_block_hash1, type, period, round, step); + auto vote1 = pbft_mgr1->generateVote(kNullBlockHash, type, period, round, step); vote1->calculateWeight(1, 1, 1); std::vector> next_votes1{vote1}; diff --git a/tests/p2p_test.cpp b/tests/p2p_test.cpp index 898a7fb715..1e9dcf31be 100644 --- a/tests/p2p_test.cpp +++ b/tests/p2p_test.cpp @@ -255,7 +255,7 @@ TEST_F(P2PTest, block_propagate) { EXPECT_GT(host1->peer_count(), 0); DagBlock blk(blk_hash_t(1111), 0, {blk_hash_t(222), blk_hash_t(333), blk_hash_t(444)}, - {g_signed_trx_samples[0]->getHash(), g_signed_trx_samples[1]->getHash()}, sig_t(7777), blk_hash_t(0), + {g_signed_trx_samples[0]->getHash(), g_signed_trx_samples[1]->getHash()}, sig_t(7777), kNullBlockHash, addr_t(999)); SharedTransactions transactions{g_signed_trx_samples[0], g_signed_trx_samples[1]}; diff --git a/tests/pbft_chain_test.cpp b/tests/pbft_chain_test.cpp index 61704a4589..35c34a7333 100644 --- a/tests/pbft_chain_test.cpp +++ b/tests/pbft_chain_test.cpp @@ -25,7 +25,8 @@ TEST_F(PbftChainTest, serialize_desiriablize_pbft_block) { blk_hash_t dag_block_hash_as_pivot(45678); PbftPeriod period = 1; addr_t beneficiary(98765); - PbftBlock pbft_block1(prev_block_hash, dag_block_hash_as_pivot, blk_hash_t(), period, beneficiary, sk, {}); + PbftBlock pbft_block1(prev_block_hash, dag_block_hash_as_pivot, kNullBlockHash, kNullBlockHash, period, beneficiary, + sk, {}); auto rlp = pbft_block1.rlp(true); PbftBlock pbft_block2(rlp); @@ -56,7 +57,8 @@ TEST_F(PbftChainTest, pbft_db_test) { PbftPeriod period = 1; addr_t beneficiary(987); - PbftBlock pbft_block(prev_block_hash, blk1.getHash(), blk_hash_t(), period, beneficiary, node->getSecretKey(), {}); + PbftBlock pbft_block(prev_block_hash, blk1.getHash(), kNullBlockHash, kNullBlockHash, period, beneficiary, + node->getSecretKey(), {}); // put into pbft chain and store into DB auto batch = db->createWriteBatch(); diff --git a/tests/pbft_manager_test.cpp b/tests/pbft_manager_test.cpp index 8fa11a5d40..45e8a3c7b8 100644 --- a/tests/pbft_manager_test.cpp +++ b/tests/pbft_manager_test.cpp @@ -276,7 +276,7 @@ TEST_F(PbftManagerTest, terminate_bogus_dag_anchor) { auto beneficiary = nodes[0]->getAddress(); auto node_sk = nodes[0]->getSecretKey(); auto propose_pbft_block = - std::make_shared(last_pbft_block_hash, dag_anchor, blk_hash_t(), propose_pbft_period, beneficiary, + std::make_shared(last_pbft_block_hash, dag_anchor, kNullBlockHash, propose_pbft_period, beneficiary, node_sk, std::move(reward_votes_hashes)); auto pbft_block_hash = propose_pbft_block->getBlockHash(); pbft_chain->pushUnverifiedPbftBlock(propose_pbft_block); @@ -641,9 +641,9 @@ TEST_F(PbftManagerTest, propose_block_and_vote_broadcast) { std::vector reward_votes_hashes; std::transform(reward_votes.begin(), reward_votes.end(), std::back_inserter(reward_votes_hashes), [](const auto &v) { return v->getHash(); }); - auto proposed_pbft_block = std::make_shared(prev_block_hash, blk_hash_t(0), blk_hash_t(0), - node1->getPbftManager()->getPbftPeriod(), node1->getAddress(), - node1->getSecretKey(), std::move(reward_votes_hashes)); + auto proposed_pbft_block = std::make_shared( + prev_block_hash, kNullBlockHash, kNullBlockHash, kNullBlockHash, node1->getPbftManager()->getPbftPeriod(), + node1->getAddress(), node1->getSecretKey(), std::move(reward_votes_hashes)); auto propose_vote = pbft_mgr1->generateVote(proposed_pbft_block->getBlockHash(), PbftVoteTypes::propose_vote, proposed_pbft_block->getPeriod(), node1->getPbftManager()->getPbftRound() + 1, value_proposal_state); @@ -825,7 +825,7 @@ TEST_F(PbftManagerWithDagCreation, limit_pbft_block) { auto max_pbft_block_capacity = node_cfgs.front().genesis.pbft.gas_limit / (trxEstimation() * 5); for (size_t i = starting_block_number; i < node->getFinalChain()->last_block_number(); ++i) { const auto &blk_hash = node->getDB()->getPeriodBlockHash(i); - ASSERT_TRUE(blk_hash != blk_hash_t()); + ASSERT_TRUE(blk_hash != kNullBlockHash); const auto &pbft_block = node->getPbftChain()->getPbftBlockInChain(blk_hash); const auto &dag_blocks_order = node->getDagManager()->getDagBlockOrder(pbft_block.getPivotDagBlockHash(), i); @@ -885,7 +885,7 @@ TEST_F(PbftManagerWithDagCreation, DISABLED_pbft_block_is_overweighted) { generateAndApplyInitialDag(); EXPECT_HAPPENS({10s, 500ms}, - [&](auto &ctx) { WAIT_EXPECT_EQ(ctx, nonce, node->getDB()->getNumTransactionExecuted()); }); + [&](auto &ctx) { WAIT_EXPECT_EQ(ctx, nonce, node->getDB()->getNumTransactionExecuted() + 1); }); node->getPbftManager()->stop(); // create pbft block @@ -913,8 +913,8 @@ TEST_F(PbftManagerWithDagCreation, DISABLED_pbft_block_is_overweighted) { std::transform(reward_votes.begin(), reward_votes.end(), std::back_inserter(reward_votes_hashes), [](const auto &v) { return v->getHash(); }); const auto pbft_block = - std::make_shared(last_hash, dag_block_hash, order_hash, propose_period, node->getAddress(), - node->getSecretKey(), std::move(reward_votes_hashes)); + std::make_shared(last_hash, dag_block_hash, order_hash, kNullBlockHash, propose_period, + node->getAddress(), node->getSecretKey(), std::move(reward_votes_hashes)); // node->getPbftChain()->pushUnverifiedPbftBlock(pbft_block); } @@ -932,7 +932,7 @@ TEST_F(PbftManagerWithDagCreation, proposed_blocks) { // Create blocks for (uint32_t i = 1; i <= block_count; i++) { std::vector reward_votes_hashes; - auto block = std::make_shared(blk_hash_t(1), blk_hash_t(0), blk_hash_t(0), 2, addr_t(), + auto block = std::make_shared(blk_hash_t(1), kNullBlockHash, kNullBlockHash, kNullBlockHash, 2, addr_t(), dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); blocks.insert({block->getBlockHash(), block}); } @@ -957,6 +957,44 @@ TEST_F(PbftManagerWithDagCreation, proposed_blocks) { EXPECT_EQ(blocks_from_db.size(), 0); } +TEST_F(PbftManagerWithDagCreation, state_root_hash) { + makeNode(); + deployContract(); + node->getDagBlockProposer()->stop(); + const auto lambda = node->getConfig().genesis.pbft.lambda_ms; + auto prev_value = node->getDagManager()->getNumVerticesInDag().first; + generateAndApplyInitialDag(); + EXPECT_HAPPENS({10s, 250ms}, [&](auto &ctx) { + WAIT_EXPECT_EQ(ctx, node->getDagManager()->getNumVerticesInDag().second, prev_value + getInitialDagSize()); + }); + // generate dag blocks with delays to distribute them between pbft blocks + for (uint8_t i = 0; i < 5; ++i) { + auto blocks = generateDagBlocks(2, 2, 2); + insertBlocks(std::move(blocks)); + std::this_thread::sleep_for(std::chrono::milliseconds(3 * lambda)); + } + + EXPECT_HAPPENS({5s, 500ms}, [&](auto &ctx) { + WAIT_EXPECT_EQ(ctx, node->getFinalChain()->get_account(node->getAddress())->nonce, nonce); + WAIT_EXPECT_EQ(ctx, node->getDB()->getNumTransactionExecuted(), nonce - 1); + }); + + const auto &state_root_delay = node_cfgs.front().genesis.pbft.state_root_recording_delay; + const auto &head_hash = node->getPbftChain()->getLastPbftBlockHash(); + auto pbft_block = node->getPbftChain()->getPbftBlockInChain(head_hash); + // Check that all produced blocks have correct state_root_hashes + while (pbft_block.getPeriod() != 1) { + auto period = pbft_block.getPeriod(); + h256 state_root; + if (period > state_root_delay) { + state_root = node->getFinalChain()->block_header(period - state_root_delay)->state_root; + } + EXPECT_EQ(pbft_block.getPrevStateRoot(), state_root); + + pbft_block = node->getPbftChain()->getPbftBlockInChain(pbft_block.getPrevBlockHash()); + } +} + } // namespace taraxa::core_tests using namespace taraxa; diff --git a/tests/sortition_test.cpp b/tests/sortition_test.cpp index 6fcb2cbb7f..e85233b4d1 100644 --- a/tests/sortition_test.cpp +++ b/tests/sortition_test.cpp @@ -25,8 +25,8 @@ PeriodData createBlock(PbftPeriod period, uint16_t efficiency, size_t dag_blocks const size_t kTrxCount = 100 * kOnePercent; PeriodData b; std::vector reward_votes_hashes; - b.pbft_blk = std::make_shared(blk_hash_t(), anchor_hash, blk_hash_t(), period, addr_t(0), - dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); + b.pbft_blk = std::make_shared(kNullBlockHash, anchor_hash, kNullBlockHash, kNullBlockHash, period, + addr_t(0), dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); size_t effective_transactions = kTrxCount * efficiency / (100 * kOnePercent); auto trx_hashes = generateTrxHashes(effective_transactions); auto trx_per_block = effective_transactions / dag_blocks_count; diff --git a/tests/test_util/include/test_util/test_util.hpp b/tests/test_util/include/test_util/test_util.hpp index 754c95c100..038a0e3cbd 100644 --- a/tests/test_util/include/test_util/test_util.hpp +++ b/tests/test_util/include/test_util/test_util.hpp @@ -161,7 +161,7 @@ state_api::BalanceMap effective_initial_balances(const state_api::Config& cfg); u256 own_effective_genesis_bal(const FullNodeConfig& cfg); std::shared_ptr make_simple_pbft_block(const h256& hash, uint64_t period, - const h256& anchor_hash = blk_hash_t(0)); + const h256& anchor_hash = kNullBlockHash); std::vector getOrderedDagBlocks(const std::shared_ptr& db); diff --git a/tests/test_util/src/test_util.cpp b/tests/test_util/src/test_util.cpp index 437b705b79..07624f7024 100644 --- a/tests/test_util/src/test_util.cpp +++ b/tests/test_util/src/test_util.cpp @@ -95,8 +95,8 @@ u256 own_effective_genesis_bal(const FullNodeConfig& cfg) { std::shared_ptr make_simple_pbft_block(const h256& hash, uint64_t period, const h256& anchor_hash) { std::vector reward_votes_hashes; - return std::make_shared(hash, anchor_hash, blk_hash_t(), period, addr_t(0), secret_t::random(), - std::move(reward_votes_hashes)); + return std::make_shared(hash, anchor_hash, kNullBlockHash, kNullBlockHash, period, addr_t(0), + secret_t::random(), std::move(reward_votes_hashes)); } std::vector getOrderedDagBlocks(const std::shared_ptr& db) { diff --git a/tests/transaction_test.cpp b/tests/transaction_test.cpp index 4517e44a21..061bde4c2a 100644 --- a/tests/transaction_test.cpp +++ b/tests/transaction_test.cpp @@ -203,8 +203,9 @@ TEST_F(TransactionTest, transaction_low_nonce) { DagBlock dag_blk({}, {}, {}, trx_hashes, secret_t::random()); db->saveDagBlock(dag_blk); std::vector reward_votes_hashes; - auto pbft_block = std::make_shared(blk_hash_t(), blk_hash_t(), blk_hash_t(), 1, addr_t::random(), - dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); + auto pbft_block = + std::make_shared(kNullBlockHash, kNullBlockHash, kNullBlockHash, kNullBlockHash, 1, addr_t::random(), + dev::KeyPair::create().secret(), std::move(reward_votes_hashes)); PeriodData period_data(pbft_block, {}); period_data.dag_blocks.push_back(dag_blk); SharedTransactions trxs{trx_1, trx_2}; diff --git a/tests/vote_test.cpp b/tests/vote_test.cpp index 1fb2b1f254..aa2b6bb4bf 100644 --- a/tests/vote_test.cpp +++ b/tests/vote_test.cpp @@ -279,7 +279,7 @@ TEST_F(VoteTest, previous_round_next_votes) { auto pbft_2t_plus_1 = pbft_mgr->getPbftTwoTPlusOne(chain_size).value(); EXPECT_EQ(pbft_2t_plus_1, 1); - // Generate a vote voted at NULL_BLOCK_HASH + // Generate a vote voted at kNullBlockHash PbftVoteTypes type = PbftVoteTypes::next_vote; PbftPeriod period = 1; PbftRound round = 1; @@ -289,7 +289,7 @@ TEST_F(VoteTest, previous_round_next_votes) { vote1->calculateWeight(1, 1, 1); std::vector> next_votes_1{vote1}; - // Enough votes for NULL_BLOCK_HASH + // Enough votes for kNullBlockHash next_votes_mgr->addNextVotes(next_votes_1, pbft_2t_plus_1); EXPECT_TRUE(next_votes_mgr->haveEnoughVotesForNullBlockHash()); EXPECT_EQ(next_votes_mgr->getNextVotes().size(), next_votes_1.size());