Skip to content

Commit

Permalink
use old state (-5 blocks) in pillar blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
JakubFornadel committed Jul 18, 2024
1 parent 599e4eb commit d9e926e
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 49 deletions.
2 changes: 1 addition & 1 deletion for_devs/local-net
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python3.11
#!/usr/bin/env python3

import click
import subprocess
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
Expand Down
4 changes: 2 additions & 2 deletions libraries/config/include/config/hardfork.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions libraries/config/src/hardfork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
7 changes: 7 additions & 0 deletions libraries/core_libs/consensus/include/pbft/pbft_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool> stopped_ = true;

// Multiple proposed pbft blocks could have same dag block anchor at same period so this cache improves retrieval of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<PillarBlock> createPillarBlock(const std::shared_ptr<const final_chain::BlockHeader>& block_header);
std::shared_ptr<PillarBlock> createPillarBlock(PbftPeriod period,
const std::shared_ptr<const final_chain::BlockHeader>& 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,18 @@ bool FinalChainImpl::isNeedToFinalize(EthBlockNumber blk_num) const {

std::vector<SharedTransaction> FinalChainImpl::makeSystemTransactions(PbftPeriod blk_num) {
std::vector<SharedTransaction> system_transactions;
if (kHardforksConfig.ficus_hf.isPillarBlockPeriod(blk_num)) {
// Make system transactions <delegation_delay()> 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();
system_transactions.push_back(finalize_trx);
}
}
}

return system_transactions;
}

Expand Down
71 changes: 42 additions & 29 deletions libraries/core_libs/consensus/src/pbft/pbft_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1682,39 +1682,11 @@ void PbftManager::finalize_(PeriodData &&period_data, std::vector<h256> &&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 <period> is
// finalized Note: period is used instead of period -1 because at this moment, block with period <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";
}
}
}
}

Expand Down Expand Up @@ -1812,9 +1784,50 @@ bool PbftManager::pushPbftBlock_(PeriodData &&period_data, std::vector<std::shar
// Advance pbft consensus period
advancePeriod();

// Create new pillar block
// !!! Important: processPillarBlock must be called only after advancePeriod()
if (kGenesisConfig.state.hardforks.ficus_hf.isPillarBlockPeriod(pbft_period)) {
assert(pbft_period == pbft_chain_->getPbftChainSize());
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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@ PillarChainManager::PillarChainManager(const FicusHardforkConfig& ficus_hf_confi
}

std::shared_ptr<PillarBlock> PillarChainManager::createPillarBlock(
const std::shared_ptr<const final_chain::BlockHeader>& block_header) {
const auto block_num = block_header->number;

PbftPeriod period, const std::shared_ptr<const final_chain::BlockHeader>& 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<PillarBlock::ValidatorVoteCountChange> 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),
Expand All @@ -64,7 +63,7 @@ std::shared_ptr<PillarBlock> 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;
}
Expand All @@ -73,7 +72,7 @@ std::shared_ptr<PillarBlock> 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;
}
Expand All @@ -84,11 +83,8 @@ std::shared_ptr<PillarBlock> 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<PillarBlock>(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<PillarBlock>(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)) {
Expand Down
1 change: 0 additions & 1 deletion tests/test_util/src/test_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d9e926e

Please sign in to comment.