diff --git a/libs/ledger/include/ledger/chain/block.hpp b/libs/ledger/include/ledger/chain/block.hpp index dbd46b35f0..6acd9b79a6 100644 --- a/libs/ledger/include/ledger/chain/block.hpp +++ b/libs/ledger/include/ledger/chain/block.hpp @@ -68,9 +68,11 @@ class Block Proof proof; ///< The consensus proof /// @} + // TODO(HUT): This should be part of body since it's no longer going to be metadata + uint64_t weight = 1; + /// @name Metadata for block management /// @{ - uint64_t weight = 1; uint64_t total_weight = 1; bool is_loose = false; /// @} diff --git a/libs/ledger/include/ledger/consensus/stake_manager.hpp b/libs/ledger/include/ledger/consensus/stake_manager.hpp index 54ff20f731..e4eda228df 100644 --- a/libs/ledger/include/ledger/consensus/stake_manager.hpp +++ b/libs/ledger/include/ledger/consensus/stake_manager.hpp @@ -29,7 +29,7 @@ namespace ledger { class StakeSnapshot; class EntropyGeneratorInterface; -class StakeManager : public StakeManagerInterface +class StakeManager final : public StakeManagerInterface { public: using Committee = std::vector
; @@ -46,6 +46,7 @@ class StakeManager : public StakeManagerInterface void UpdateCurrentBlock(Block const ¤t) override; std::size_t GetBlockGenerationWeight(Block const &previous, Address const &address) override; bool ShouldGenerateBlock(Block const &previous, Address const &address) override; + bool ValidMinerForBlock(Block const &previous, Address const &address) override; /// @} // Accessors diff --git a/libs/ledger/include/ledger/consensus/stake_manager_interface.hpp b/libs/ledger/include/ledger/consensus/stake_manager_interface.hpp index a59438e457..9291893c61 100644 --- a/libs/ledger/include/ledger/consensus/stake_manager_interface.hpp +++ b/libs/ledger/include/ledger/consensus/stake_manager_interface.hpp @@ -39,6 +39,7 @@ class StakeManagerInterface virtual void UpdateCurrentBlock(Block const ¤t) = 0; virtual std::size_t GetBlockGenerationWeight(Block const &previous, Address const &address) = 0; virtual bool ShouldGenerateBlock(Block const &previous, Address const &address) = 0; + virtual bool ValidMinerForBlock(Block const &previous, Address const &address) = 0; /// @} private: diff --git a/libs/ledger/src/chain/block_coordinator.cpp b/libs/ledger/src/chain/block_coordinator.cpp index a62941f4a3..b0adb2b23f 100644 --- a/libs/ledger/src/chain/block_coordinator.cpp +++ b/libs/ledger/src/chain/block_coordinator.cpp @@ -417,6 +417,11 @@ BlockCoordinator::State BlockCoordinator::OnSynchronised(State current, State pr next_block_->body.block_number = current_block_->body.block_number + 1; next_block_->body.miner = mining_address_; + if (stake_) + { + next_block_->weight = stake_->GetBlockGenerationWeight(*current_block_, mining_address_); + } + // Attach current DAG state if (dag_) { @@ -469,6 +474,21 @@ BlockCoordinator::State BlockCoordinator::OnPreExecBlockValidation() return fail("No previous block in chain"); } + // Check that the weight as given by the proof is correct + if (stake_) + { + if (!stake_->ValidMinerForBlock(*previous, current_block_->body.miner)) + { + return fail("Block signed by miner deemed invalid by the staking mechanism"); + } + + if (current_block_->weight != + stake_->GetBlockGenerationWeight(*previous, current_block_->body.miner)) + { + return fail("Incorrect stake weight found for block"); + } + } + // Check: Ensure the block number is continuous uint64_t const expected_block_number = previous->body.block_number + 1u; if (expected_block_number != current_block_->body.block_number) diff --git a/libs/ledger/src/chain/main_chain.cpp b/libs/ledger/src/chain/main_chain.cpp index bbfb4b8af8..5b367220d3 100644 --- a/libs/ledger/src/chain/main_chain.cpp +++ b/libs/ledger/src/chain/main_chain.cpp @@ -106,13 +106,8 @@ BlockStatus MainChain::AddBlock(Block const &blk) // create a copy of the block auto block = std::make_shared(blk); - // update the weight based on the proof and the number of transactions - block->weight = 1; + // At this point we assume that the weight has been correctly set by the miner block->total_weight = 1; - for (auto const &slice : block->body.slices) - { - block->weight += slice.size(); - } // pass the block to the auto const status = InsertBlock(block); diff --git a/libs/ledger/src/consensus/stake_manager.cpp b/libs/ledger/src/consensus/stake_manager.cpp index 79a093de35..f5cb376ea7 100644 --- a/libs/ledger/src/consensus/stake_manager.cpp +++ b/libs/ledger/src/consensus/stake_manager.cpp @@ -176,5 +176,18 @@ void StakeManager::ResetInternal(StakeSnapshotPtr &&snapshot, std::size_t commit current_block_index_ = 0; } +bool StakeManager::ValidMinerForBlock(Block const &previous, Address const &address) +{ + auto const committee = GetCommittee(previous); + + if (!committee || committee->empty()) + { + FETCH_LOG_WARN(LOGGING_NAME, "Unable to determine committee for block validation"); + return false; + } + + return std::find((*committee).begin(), (*committee).end(), address) != (*committee).end(); +} + } // namespace ledger } // namespace fetch