diff --git a/CMakeLists.txt b/CMakeLists.txt index f55ee375e7..9cda425b08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,7 +202,7 @@ include(CMakeModules/clang_format.cmake) # cppcheck include(CMakeModules/cppcheck.cmake) -add_custom_target(check-static DEPENDS cpp-check clang-format clang-format-check) +add_custom_target(check-static DEPENDS cpp-check) # execute command to get git info include(CMakeModules/git_info.cmake) diff --git a/libraries/common/include/common/encoding_solidity.hpp b/libraries/common/include/common/encoding_solidity.hpp index 7102521152..15b7728f97 100644 --- a/libraries/common/include/common/encoding_solidity.hpp +++ b/libraries/common/include/common/encoding_solidity.hpp @@ -10,6 +10,8 @@ namespace taraxa::util { class EncodingSolidity { public: + static constexpr uint8_t kStartPrefix = 32; + static constexpr uint8_t kStartPrefixSize = 1; /// PACKING /// template static bytes packFunctionCall(const std::string& function, const Params&... args) { diff --git a/libraries/core_libs/consensus/include/final_chain/final_chain.hpp b/libraries/core_libs/consensus/include/final_chain/final_chain.hpp index 749115ca50..037dd32377 100644 --- a/libraries/core_libs/consensus/include/final_chain/final_chain.hpp +++ b/libraries/core_libs/consensus/include/final_chain/final_chain.hpp @@ -255,6 +255,11 @@ class FinalChain { */ virtual h256 get_bridge_root(EthBlockNumber blk_num) const = 0; + /** + * @param blk_num + * @return bridge epoch + */ + virtual h256 get_bridge_epoch(EthBlockNumber blk_num) const = 0; // TODO move out of here: std::pair getBalance(addr_t const& addr) const { diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp index f629311513..ed08a3c53b 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -43,9 +43,8 @@ class PillarBlock { public: PillarBlock() = default; PillarBlock(const dev::RLP& rlp); - PillarBlock(PbftPeriod period, h256 state_root, h256 bridge_root, - std::vector&& validator_votes_count_changes, - blk_hash_t previous_pillar_block_hash); + PillarBlock(PbftPeriod period, h256 state_root, blk_hash_t previous_pillar_block_hash, h256 bridge_root, u256 epoch, + std::vector&& validator_votes_count_changes); PillarBlock(const PillarBlock& pillar_block); @@ -79,6 +78,11 @@ class PillarBlock { */ const h256& getBridgeRoot() const; + /** + * @return epoch + */ + const u256& getEpoch() const; + /** * @return pillar block rlp */ @@ -89,6 +93,10 @@ class PillarBlock { */ Json::Value getJson() const; + // this is needed for solidity encoding. So should be changed if fields are changed + static constexpr uint8_t kFieldsSize = 5; + static constexpr uint8_t kArrayPosAndSize = 2; + static constexpr uint8_t kFieldsInVoteCount = 2; /** * @note Solidity encoding is used for data that are sent to smart contracts * @@ -113,14 +121,18 @@ class PillarBlock { // Pbft block(for period_) state root h256 state_root_{}; + // Hash of the previous pillar block as pillar blocks forms a chain + blk_hash_t previous_pillar_block_hash_{0}; + // Bridge root h256 bridge_root_{}; + // Bridge epoch + u256 epoch_{}; + // Delta change of validators votes count between current and latest pillar block std::vector validators_votes_count_changes_{}; - blk_hash_t previous_pillar_block_hash_{0}; - mutable std::optional hash_; mutable std::shared_mutex hash_mutex_; }; 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 cca20f2ed6..9dcd0f6345 100644 --- a/libraries/core_libs/consensus/src/final_chain/final_chain.cpp +++ b/libraries/core_libs/consensus/src/final_chain/final_chain.cpp @@ -531,6 +531,14 @@ class FinalChainImpl final : public FinalChain { .code_retval); } + h256 get_bridge_epoch(EthBlockNumber blk_num) const override { + const static auto get_bridge_epoch_method = util::EncodingSolidity::packFunctionCall("finalizedEpoch()"); + return h256(call(state_api::EVMTransaction{dev::ZeroAddress, 1, kHardforksConfig.ficus_hf.bridge_contract_address, + state_api::ZeroAccount.nonce, 0, 10000000, get_bridge_epoch_method}, + blk_num) + .code_retval); + } + private: std::shared_ptr get_transaction_hashes(std::optional n = {}) const { const auto& trxs = db_->getPeriodTransactions(last_if_absent(n)); diff --git a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp index d99d3b1deb..cdaa3f01a6 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -20,21 +20,22 @@ PillarBlock::ValidatorVoteCountChange::ValidatorVoteCountChange(const dev::RLP& PillarBlock::PillarBlock(const dev::RLP& rlp) : PillarBlock(util::rlp_dec(rlp)) {} -PillarBlock::PillarBlock(PbftPeriod period, h256 state_root, h256 bridge_root, - std::vector&& validator_votes_count_changes, - blk_hash_t previous_pillar_block_hash) +PillarBlock::PillarBlock(PbftPeriod period, h256 state_root, blk_hash_t previous_pillar_block_hash, h256 bridge_root, + u256 epoch, std::vector&& validator_votes_count_changes) : pbft_period_(period), state_root_(state_root), + previous_pillar_block_hash_(previous_pillar_block_hash), bridge_root_(bridge_root), - validators_votes_count_changes_(std::move(validator_votes_count_changes)), - previous_pillar_block_hash_(previous_pillar_block_hash) {} + epoch_(epoch), + validators_votes_count_changes_(std::move(validator_votes_count_changes)) {} PillarBlock::PillarBlock(const PillarBlock& pillar_block) : pbft_period_(pillar_block.pbft_period_), state_root_(pillar_block.state_root_), + previous_pillar_block_hash_(pillar_block.previous_pillar_block_hash_), bridge_root_(pillar_block.bridge_root_), - validators_votes_count_changes_(pillar_block.validators_votes_count_changes_), - previous_pillar_block_hash_(pillar_block.previous_pillar_block_hash_) {} + epoch_(pillar_block.epoch_), + validators_votes_count_changes_(pillar_block.validators_votes_count_changes_) {} dev::bytes PillarBlock::getRlp() const { return util::rlp_enc(*this); } @@ -50,6 +51,8 @@ const h256& PillarBlock::getStateRoot() const { return state_root_; } const h256& PillarBlock::getBridgeRoot() const { return bridge_root_; } +const u256& PillarBlock::getEpoch() const { return epoch_; } + blk_hash_t PillarBlock::getHash() const { { std::shared_lock lock(hash_mutex_); @@ -67,8 +70,9 @@ Json::Value PillarBlock::getJson() const { Json::Value res; res["pbft_period"] = static_cast(pbft_period_); res["state_root"] = dev::toJS(state_root_); - res["bridge_root"] = dev::toJS(bridge_root_); res["previous_pillar_block_hash"] = dev::toJS(previous_pillar_block_hash_); + res["bridge_root"] = dev::toJS(bridge_root_); + res["epoch"] = dev::toJS(epoch_); res["validators_vote_counts_changes"] = Json::Value(Json::arrayValue); for (auto const& vote_count_change : validators_votes_count_changes_) { Json::Value vote_count_change_json; @@ -84,25 +88,21 @@ Json::Value PillarBlock::getJson() const { dev::bytes PillarBlock::encodeSolidity() const { dev::bytes result; - const uint8_t start_prefix = 32; - const uint8_t start_prefix_size = 1; - const uint8_t fields_size = 4; - const uint8_t array_pos_and_size = 2; - const uint8_t fields_in_vote_count_struct = 2; - result.reserve((start_prefix_size + fields_size + array_pos_and_size + - (fields_in_vote_count_struct * validators_votes_count_changes_.size())) * + result.reserve((util::EncodingSolidity::kStartPrefixSize + kFieldsSize + kArrayPosAndSize + + (kFieldsInVoteCount * validators_votes_count_changes_.size())) * util::EncodingSolidity::kWordSize); - auto start = util::EncodingSolidity::pack(start_prefix); + auto start = util::EncodingSolidity::pack(util::EncodingSolidity::kStartPrefix); result.insert(result.end(), start.begin(), start.end()); - auto body = util::EncodingSolidity::pack(pbft_period_, state_root_, bridge_root_, previous_pillar_block_hash_); + auto body = + util::EncodingSolidity::pack(pbft_period_, state_root_, previous_pillar_block_hash_, bridge_root_, epoch_); result.insert(result.end(), body.begin(), body.end()); - const uint8_t array_position = (start_prefix_size + fields_size) * util::EncodingSolidity::kWordSize; + const uint8_t array_position = + (util::EncodingSolidity::kStartPrefixSize + kFieldsSize) * util::EncodingSolidity::kWordSize; auto array_data = util::EncodingSolidity::pack(array_position, validators_votes_count_changes_.size()); result.insert(result.end(), array_data.begin(), array_data.end()); - for (auto& vote_count_change : validators_votes_count_changes_) { auto vote_count_change_encoded = util::EncodingSolidity::pack(vote_count_change.addr_, vote_count_change.vote_count_change_); @@ -116,14 +116,14 @@ PillarBlock PillarBlock::decodeSolidity(const bytes& enc) { PillarBlock b; uint64_t start_prefix = 0; - util::EncodingSolidity::staticUnpack(enc, start_prefix, b.pbft_period_, b.state_root_, b.bridge_root_, - b.previous_pillar_block_hash_); + util::EncodingSolidity::staticUnpack(enc, start_prefix, b.pbft_period_, b.state_root_, b.previous_pillar_block_hash_, + b.bridge_root_, b.epoch_); - uint64_t array_pos = (1 + 4) * util::EncodingSolidity::kWordSize; + uint64_t array_pos = (util::EncodingSolidity::kStartPrefixSize + kFieldsSize) * util::EncodingSolidity::kWordSize; uint64_t array_size = 0; bytes array_data(enc.begin() + array_pos, enc.end()); util::EncodingSolidity::staticUnpack(array_data, array_pos, array_size); - array_data = bytes(array_data.begin() + 2 * util::EncodingSolidity::kWordSize, array_data.end()); + array_data = bytes(array_data.begin() + kFieldsInVoteCount * util::EncodingSolidity::kWordSize, array_data.end()); for (size_t i = 0; i < array_size; i++) { addr_t addr; @@ -137,7 +137,7 @@ PillarBlock PillarBlock::decodeSolidity(const bytes& enc) { return b; } -RLP_FIELDS_DEFINE(PillarBlock, pbft_period_, state_root_, bridge_root_, previous_pillar_block_hash_, +RLP_FIELDS_DEFINE(PillarBlock, pbft_period_, state_root_, previous_pillar_block_hash_, bridge_root_, epoch_, validators_votes_count_changes_) PillarBlockData::PillarBlockData(std::shared_ptr block, 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 7166241589..50fdc2ae36 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 @@ -53,7 +53,6 @@ std::shared_ptr PillarChainManager::createPillarBlock( blk_hash_t previous_pillar_block_hash{}; // null block hash auto new_vote_counts = final_chain_->dpos_validators_vote_counts(block_num); std::vector votes_count_changes; - h256 bridge_root = final_chain_->get_bridge_root(block_num); // First ever pillar block if (block_num == kFicusHfConfig.firstPillarBlockPeriod()) { @@ -94,9 +93,11 @@ 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_data->final_chain_blk->state_root, bridge_root, - std::move(votes_count_changes), previous_pillar_block_hash); + std::make_shared(block_num, block_data->final_chain_blk->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/pillar_chain_test.cpp b/tests/pillar_chain_test.cpp index a855e9d530..5f7feae5a2 100644 --- a/tests/pillar_chain_test.cpp +++ b/tests/pillar_chain_test.cpp @@ -26,7 +26,7 @@ TEST_F(PillarChainTest, pillar_chain_db) { const auto vote_count_change2 = votes_count_changes.emplace_back(addr_t(2), 2); const auto pillar_block = std::make_shared( - pillar_block_period, state_root, h256{}, std::move(votes_count_changes), previous_pillar_block_hash); + pillar_block_period, state_root, previous_pillar_block_hash, h256{}, 0, std::move(votes_count_changes)); // Pillar block vote counts std::vector vote_counts; @@ -53,9 +53,9 @@ TEST_F(PillarChainTest, pillar_chain_db) { const auto vote2 = pillar_votes.emplace_back( std::make_shared(secret_t::random(), pillar_block->getPeriod(), pillar_block->getHash())); - const auto previous_pillar_block = std::make_shared( - pillar_block_period - 1, h256{}, h256{}, std::vector{}, - blk_hash_t{}); + const auto previous_pillar_block = + std::make_shared(pillar_block_period - 1, h256{}, blk_hash_t{}, h256{}, 0, + std::vector{}); db.savePillarBlockData( pillar_chain::PillarBlockData{pillar_block, std::vector>{pillar_votes}}); db.savePillarBlockData( @@ -270,20 +270,21 @@ TEST_F(PillarChainTest, block_serialization) { validator_votes_count_changes.emplace_back(pillar_chain::PillarBlock::ValidatorVoteCountChange(addr_t(4), 4)); validator_votes_count_changes.emplace_back(pillar_chain::PillarBlock::ValidatorVoteCountChange(addr_t(5), -5)); auto pb = - pillar_chain::PillarBlock(11, h256(22), h256(33), std::move(validator_votes_count_changes), blk_hash_t(44)); + pillar_chain::PillarBlock(11, h256(22), h256(33), blk_hash_t(44), 55, std::move(validator_votes_count_changes)); const auto bt = pb.encodeSolidity(); // This hardcoded hex string is from bridge solidity test(TaraClient.t.sol/test_blockEncodeDecode) const auto expected = dev::jsToBytes( "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000" "00000000000000000b00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000" "000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002c0000000000" - "0000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000" - "000000050000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000200000000000000000000" - "000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003ff" - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd000000000000000000000000000000000000000000000000" - "00000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000" - "0000000000000000000000000000000005fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb"); + "00000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000" + "000000c0000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000" + "00000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000" + "00000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200" + "00000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffd0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000" + "00000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005ffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffb"); ASSERT_EQ(bt, expected); } { @@ -300,26 +301,27 @@ TEST_F(PillarChainTest, block_serialization) { validator_votes_count_changes.emplace_back(addr_t("0x8a35AcfbC15Ff81A39Ae7d344fD709f28e8600B4"), 465876798); auto pb = - pillar_chain::PillarBlock(11, h256(22), h256(33), std::move(validator_votes_count_changes), blk_hash_t(44)); + pillar_chain::PillarBlock(11, h256(22), h256(33), blk_hash_t(44), 55, std::move(validator_votes_count_changes)); const auto bt = pb.encodeSolidity(); // This hardcoded hex string is from bridge solidity test(TaraClient.t.sol/test_blockEncodeDecode) const auto expected = dev::jsToBytes( - "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000" - "0000000000000000000b000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000" - "00000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002c00000000" - "000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000" - "000000000a0000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000002000000000000000000" - "00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0000000000000000000000000000000000000000000000" - "00000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000" - "000000000000000000000000000000000005fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0000000000" - "00000000000000290decd9548b62a8d60345a988386fc84ba6bc9500000000000000000000000000000000000000000000000000000000" - "486d7a74000000000000000000000000b10e2d527612073b26eecdfd717e6a320cf44b4affffffffffffffffffffffffffffffffffffff" - "fffffffffffffffffffffe493f000000000000000000000000405787fa12a823e0f2b7631cc41b3ba8828b3321ffffffffffffffffffff" - "ffffffffffffffffffffffffffffffffffffaf53b57e000000000000000000000000c2575a0e9e593c00f959f8c92f12db2869c3395a00" - "0000000000000000000000000000000000000000000000000000003b77acd10000000000000000000000008a35acfbc15ff81a39ae7d34" - "4fd709f28e8600b4000000000000000000000000000000000000000000000000000000001bc4b73e"); + "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000" + "00000000000000000b00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000" + "000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000000000002c0000000000" + "00000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000" + "000000c0000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000" + "00000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000" + "00000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200" + "00000000000000000000000000000000000000000000000000000000000003ffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffd0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000" + "00000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005ffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffb000000000000000000000000290decd9548b62a8d60345a988386fc84b" + "a6bc9500000000000000000000000000000000000000000000000000000000486d7a74000000000000000000000000b10e2d527612073b" + "26eecdfd717e6a320cf44b4afffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe493f0000000000000000000000" + "00405787fa12a823e0f2b7631cc41b3ba8828b3321ffffffffffffffffffffffffffffffffffffffffffffffffffffffffaf53b57e0000" + "00000000000000000000c2575a0e9e593c00f959f8c92f12db2869c3395a00000000000000000000000000000000000000000000000000" + "0000003b77acd10000000000000000000000008a35acfbc15ff81a39ae7d344fd709f28e8600b400000000000000000000000000000000" + "0000000000000000000000001bc4b73e"); ASSERT_EQ(bt, expected); } } @@ -372,6 +374,7 @@ TEST_F(PillarChainTest, pillar_block_solidity_rlp_encoding) { EthBlockNumber pillar_block_period(123); h256 state_root(456); h256 bridge_root(789); + u256 epoch = 0; blk_hash_t previous_pillar_block_hash(789); std::vector votes_count_changes; @@ -379,8 +382,8 @@ TEST_F(PillarChainTest, pillar_block_solidity_rlp_encoding) { const auto vote_count_change2 = votes_count_changes.emplace_back(addr_t(2), 2); auto vcc = votes_count_changes; - const auto pillar_block = pillar_chain::PillarBlock(pillar_block_period, state_root, bridge_root, std::move(vcc), - previous_pillar_block_hash); + const auto pillar_block = pillar_chain::PillarBlock(pillar_block_period, state_root, previous_pillar_block_hash, + bridge_root, epoch, std::move(vcc)); auto validateDecodedPillarBlock = [&](const pillar_chain::PillarBlock& pillar_block) { ASSERT_EQ(pillar_block.getPeriod(), pillar_block_period);