From 9be9fa5a84234a2e9f237fd1f9027dfe397449c3 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 6 Sep 2023 16:24:41 -0700 Subject: [PATCH 01/20] add libBLS as submodule + create custom cmake for bls --- .gitmodules | 3 +++ CMakeLists.txt | 5 ++++- libraries/aleth/CMakeLists.txt | 1 - submodules/libBLS | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) create mode 160000 submodules/libBLS diff --git a/.gitmodules b/.gitmodules index 4db3a3c38c..3f72a38648 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ path = submodules/taraxa-vrf url = ../taraxa-vrf.git ignore = dirty +[submodule "submodules/libBLS"] + path = submodules/libBLS + url = git@github.com:skalenetwork/libBLS.git diff --git a/CMakeLists.txt b/CMakeLists.txt index bfcd09a7aa..e85930e31b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,11 +207,14 @@ add_custom_target(check-static DEPENDS cpp-check clang-format clang-format-check # execute command to get git info include(CMakeModules/git_info.cmake) +include(ExternalProject) + # find and include system libraries used in submodues and libraries find_package(GMP) find_package(MPFR) +# used in libraries/aleth & submodules/libBLS +include(ProjectLibFF) -include(ExternalProject) # use JSONCPP library from conan for JSONRPCCPP build set(JSONCPP_INCLUDE_DIR ${CONAN_INCLUDE_DIRS_JSONCPP}) include(ProjectJSONRPCCPP) diff --git a/libraries/aleth/CMakeLists.txt b/libraries/aleth/CMakeLists.txt index 729924d415..5b01b3ea2b 100644 --- a/libraries/aleth/CMakeLists.txt +++ b/libraries/aleth/CMakeLists.txt @@ -1,6 +1,5 @@ ### Aleth part include(ProjectSecp256k1) -include(ProjectLibFF) add_subdirectory(libdevcore) add_subdirectory(libdevcrypto) diff --git a/submodules/libBLS b/submodules/libBLS new file mode 160000 index 0000000000..6fb4d5c5a1 --- /dev/null +++ b/submodules/libBLS @@ -0,0 +1 @@ +Subproject commit 6fb4d5c5a1af80bcca82b95fc30e01b65c7cf235 From e7a719d2cf9613d1c7460d9d24ef9bc1094c6ac8 Mon Sep 17 00:00:00 2001 From: Dmytro Kostenko Date: Thu, 7 Sep 2023 12:07:17 +0200 Subject: [PATCH 02/20] fix: add openssl lib to bls build --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 3f72a38648..a02ed948f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,4 +16,4 @@ ignore = dirty [submodule "submodules/libBLS"] path = submodules/libBLS - url = git@github.com:skalenetwork/libBLS.git + url = https://github.com/skalenetwork/libBLS.git From 653a269d06ff1d35b822416586b8bc59fa346a7a Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Thu, 7 Sep 2023 11:02:49 -0700 Subject: [PATCH 03/20] create separate custom cmake for libBLS --- submodules/CMakeLists.txt | 3 ++ submodules/CMakeLists_bls.cmake | 70 +++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 - 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 submodules/CMakeLists_bls.cmake diff --git a/submodules/CMakeLists.txt b/submodules/CMakeLists.txt index 117cbcd879..02184be434 100644 --- a/submodules/CMakeLists.txt +++ b/submodules/CMakeLists.txt @@ -149,3 +149,6 @@ add_custom_command( WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND cd ./taraxa-evm && ${EVM_BUILD_ENV} go test ./... COMMENT "Running Go EVM tests") + +# Alternative libBLS cmake +include(CMakeLists_bls.cmake) diff --git a/submodules/CMakeLists_bls.cmake b/submodules/CMakeLists_bls.cmake new file mode 100644 index 0000000000..099070abe7 --- /dev/null +++ b/submodules/CMakeLists_bls.cmake @@ -0,0 +1,70 @@ +# Alternative cmake for libBLS +project(libBLS) + +set(prefix_libBLS libBLS) + +set(sourses_bls + ${prefix_libBLS}/bls/bls.cpp + ${prefix_libBLS}/bls/BLSPrivateKeyShare.cpp + ${prefix_libBLS}/bls/BLSPrivateKey.cpp + ${prefix_libBLS}/bls/BLSPublicKeyShare.cpp + ${prefix_libBLS}/bls/BLSPublicKey.cpp + ${prefix_libBLS}/bls/BLSSignature.cpp + ${prefix_libBLS}/bls/BLSSigShare.cpp + ${prefix_libBLS}/bls/BLSSigShareSet.cpp + ${prefix_libBLS}/dkg/dkg.cpp + ${prefix_libBLS}/dkg/DKGBLSWrapper.cpp + ${prefix_libBLS}/dkg/DKGBLSSecret.cpp + ${prefix_libBLS}/third_party/cryptlite/base64.cpp + ${prefix_libBLS}/tools/utils.cpp + ) + +set(headers_bls + ${prefix_libBLS}/libBLS.h + ${prefix_libBLS}/bls/bls.h + ${prefix_libBLS}/bls/BLSPrivateKeyShare.h + ${prefix_libBLS}/bls/BLSPrivateKey.h + ${prefix_libBLS}/bls/BLSPublicKeyShare.h + ${prefix_libBLS}/bls/BLSPublicKey.h + ${prefix_libBLS}/bls/BLSSignature.h + ${prefix_libBLS}/bls/BLSSigShare.h + ${prefix_libBLS}/bls/BLSSigShareSet.h + ${prefix_libBLS}/dkg/dkg.h + ${prefix_libBLS}/dkg/DKGBLSWrapper.h + ${prefix_libBLS}/dkg/DKGBLSSecret.h + ${prefix_libBLS}/third_party/json.hpp + ${prefix_libBLS}/third_party/cryptlite/sha256.h + ${prefix_libBLS}/third_party/cryptlite/sha1.h + ${prefix_libBLS}/third_party/cryptlite/hmac.h + ${prefix_libBLS}/third_party/cryptlite/base64.h + ${prefix_libBLS}/tools/utils.h + ) + +## add new target, because libBLS at submodule have too many properties +## and we can do it here more simpler +add_library(bls STATIC ${sourses_bls} ${headers_bls}) +target_link_libraries(bls PUBLIC libff::ff CONAN_PKG::cryptopp ${GMP_LIBRARIES} CONAN_PKG::openssl) +target_include_directories(bls PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${prefix_libBLS} ${CONAN_INCLUDE_DIRS_BOOST} ${GMP_INCLUDES} ${libff_inlcude_dir}/..) +target_compile_options(bls PUBLIC -Wall -Wparentheses -Wunused -Wno-error=unused-private-field -Wno-error=vla-extension -Wno-error=extra-semi -Wno-error=sign-compare -Wno-error=sign-compare -Wno-error=bitwise-op-parentheses -Wno-error=deprecated-copy -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=uninitialized -Wunreachable-code -Wextra -fPIC) + +# bls tests +add_executable(bls_unit_test ${prefix_libBLS}/test/unit_tests_bls.cpp) +target_link_libraries(bls_unit_test PRIVATE bls) + +add_executable(dkg_unit_test ${prefix_libBLS}/test/unit_tests_dkg.cpp) +target_link_libraries(dkg_unit_test PRIVATE bls) + +add_executable(bls_test ${prefix_libBLS}/test/test_bls.cpp) +target_link_libraries(bls_test PRIVATE bls) + +add_executable(utils_unit_test ${prefix_libBLS}/test/unit_tests_utils.cpp) +target_link_libraries(utils_unit_test PRIVATE bls) + +add_custom_target(all_bls_tests + COMMAND ./bls_unit_test + COMMAND ./dkg_unit_test + COMMAND ./bls_test + COMMAND ./utils_unit_test + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin + COMMENT "Run all BLS and DKG tests" + ) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d120dea503..106fd10942 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,7 +3,6 @@ add_subdirectory(test_util) # Enable testing for current directory and below. enable_testing(true) - add_executable(abi_test abi_test.cpp) target_link_libraries(abi_test test_util) add_test(abi_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/abi_test) From 56c62db2d713fed36ab2d8c8e02bda36ec3ea4a5 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Fri, 15 Sep 2023 16:42:27 -0700 Subject: [PATCH 04/20] bbasic architecture & initial code for pillar blocks & bls signature --- libraries/core_libs/CMakeLists.txt | 3 +- .../include/pillar_chain/bls_signature.hpp | 59 ++++++++++ .../include/pillar_chain/pillar_block.hpp | 46 ++++++++ .../pillar_chain/pillar_chain_manager.hpp | 101 ++++++++++++++++++ .../include/vote_manager/vote_manager.hpp | 2 +- .../src/pillar_chain/bls_signature.cpp | 43 ++++++++ .../src/pillar_chain/pillar_block.cpp | 24 +++++ .../src/pillar_chain/pillar_chain_manager.cpp | 79 ++++++++++++++ .../network/include/network/network.hpp | 2 + .../include/network/tarcap/packet_types.hpp | 1 + .../latest/bls_sig_packet_handler.hpp | 31 ++++++ .../v1/init_packets_handlers.hpp | 6 +- .../network/tarcap/taraxa_capability.hpp | 3 +- .../include/network/tarcap/taraxa_peer.hpp | 14 ++- libraries/core_libs/network/src/network.cpp | 8 ++ .../latest/bls_sig_packet_handler.cpp | 67 ++++++++++++ .../network/src/tarcap/taraxa_capability.cpp | 5 +- .../network/src/tarcap/taraxa_peer.cpp | 12 ++- .../core_libs/node/include/node/node.hpp | 2 + libraries/core_libs/node/src/node.cpp | 19 +++- 20 files changed, 515 insertions(+), 12 deletions(-) create mode 100644 libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp create mode 100644 libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp create mode 100644 libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp create mode 100644 libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp create mode 100644 libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp create mode 100644 libraries/core_libs/consensus/src/pillar_chain/pillar_chain_manager.cpp create mode 100644 libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp create mode 100644 libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp diff --git a/libraries/core_libs/CMakeLists.txt b/libraries/core_libs/CMakeLists.txt index 925fc5b572..f20053b811 100644 --- a/libraries/core_libs/CMakeLists.txt +++ b/libraries/core_libs/CMakeLists.txt @@ -57,6 +57,7 @@ target_link_libraries(core_libs PUBLIC metrics Jsonrpccpp rocksdb + bls # GraphQL cppgraphqlgen::graphqlservice @@ -66,4 +67,4 @@ target_link_libraries(core_libs PUBLIC install(TARGETS core_libs ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) \ No newline at end of file +) diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp new file mode 100644 index 0000000000..fbe83613b4 --- /dev/null +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include "common/types.hpp" +#include +#include +#include +#include "pillar_chain/pillar_block.hpp" + +namespace taraxa { + + +/** @addtogroup PILLAR_CHAIN + * @{ + */ + +/** + * @brief BlsSignature + */ +class BlsSignature { + public: + using Signature = libff::alt_bn128_G1; + using Hash = uint256_hash_t; + + public: + BlsSignature(const dev::RLP& rlp); + BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, const libff::alt_bn128_Fr& secret); + + /** + * @brief Validates BLS signature + * + * @return true if valid, otherwise false + */ + bool isValid() const; + + /** + * @return bls signature rlp + */ + dev::bytes getRlp() const; + + /** + * @return bls signature hash + */ + Hash getHash() const; + + PillarBlock::Hash getPillarBlockHash() const; + + private: + PillarBlock::Hash pillar_block_hash_{0}; + + Signature signature_; + // TODO: seems like pub key is needed for verification of sig ??? + libff::alt_bn128_G2 public_key_; + + mutable std::optional cached_hash_; +}; + +/** @}*/ + +} // namespace taraxa diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp new file mode 100644 index 0000000000..c28fb15231 --- /dev/null +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "common/types.hpp" + +namespace taraxa { + +class DbStorage; + +/** @addtogroup PILLAR_CHAIN + * @{ + */ + +/** + * @brief PillarBlock contains merkle root of all finalized blocks created in the last epoch + */ +class PillarBlock { + public: + using Hash = uint256_hash_t; + + public: + // TODO: use real merkle root + PillarBlock(blk_hash_t epoch_blocks_merkle_root, blk_hash_t previous_pillar_block_hash); + + /** + * @return pillar block hash + */ + Hash getHash() const; + + private: + /** + * @return pillar block rlp + */ + dev::bytes getRlp() const; + + private: + // TODO: replace with actual merkle root + blk_hash_t epoch_blocks_merkle_root_{0}; + + Hash previous_pillar_block_hash_{0}; + + const Hash kCachedHash; +}; + +/** @}*/ + +} // namespace taraxa diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp new file mode 100644 index 0000000000..e01fdf14d5 --- /dev/null +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include + +#include "final_chain/data.hpp" +#include "logger/logger.hpp" +#include "pillar_chain/bls_signature.hpp" +#include "pillar_chain/pillar_block.hpp" + +namespace taraxa { + +class DbStorage; +class Network; +class BlsSignature; + +/** @addtogroup PILLAR_CHAIN + * @{ + */ + +/** + * @brief PillarChainMgr class contains functionality related to pillar chain + */ +class PillarChainManager { + public: + PillarChainManager(std::shared_ptr db, addr_t node_addr); + + /** + * @Process new final block + * + * @param block_data + */ + void newFinalBlock(const final_chain::FinalizationResult& block_data); + + /** + * @brief Set network as a weak pointer + * @param network a weak pointer + */ + void setNetwork(std::weak_ptr network); + + /** + * @brief Checks if signature is related to saved last_pillar_block_ and it is not already saved + * + * @param signature + * @return true if relevant, otherwise false + */ + bool isRelevantBlsSig(const std::shared_ptr signature) const; + + /** + * @brief Add a signature to the bls signatures map + * @param signature signature + * + * @return true if signature was successfully added, otherwise false + */ + bool addVerifiedBlsSig(const std::shared_ptr& signature); + + /** + * @brief Get all bls signatures + * @return all bls signatures + */ + // std::vector> getVerifiedBlsSigs() const; + + private: + std::shared_ptr db_; + std::weak_ptr network_; + + // TODO: from wallet-config file + std::pair bls_keys_; + + // Last processed pillar block + // TODO: might be just atomic hash + std::shared_ptr last_pillar_block_; + + // Last processed pillar block signatures + std::unordered_map> last_pillar_block_signatures_; + + // Last processed pillar block signatures weight + uint64_t last_pillar_block_signatures_weight_; + + // Protects last_pillar_block_ & last_pillar_block_signatures_ & last_pillar_block_signatures_weight_ + mutable std::shared_mutex mutex_; + + // How often is pillar block created + // TODO: put in config + static constexpr uint16_t kEpochBlocksNum = 100; + + // Nodes start to broadcast BLS signatures for pillar blocks with small delay to make sure that + // all up-to-date nodes already processed the pillar block + // TODO: validation: kBlsSigBroadcastDelayBlocks should be way smaller than kEpochBlocksNum + static constexpr uint16_t kBlsSigBroadcastDelayBlocks = 5; + + // How often to check if node has 2t+1 bls signature for the latest pillar block & potentially trigger syncing + // TODO: validation: kCheckLatestBlockBlsSigs should be way smaller than kEpochBlocksNum and bigger than + // kBlsSigBroadcastDelayBlocks + static constexpr uint16_t kCheckLatestBlockBlsSigs = 5; + + LOG_OBJECTS_DEFINE +}; + +/** @}*/ + +} // namespace taraxa 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 de8d6391b7..0ece7f76e8 100644 --- a/libraries/core_libs/consensus/include/vote_manager/vote_manager.hpp +++ b/libraries/core_libs/consensus/include/vote_manager/vote_manager.hpp @@ -38,7 +38,7 @@ class VoteManager { /** * @brief Set network as a weak pointer - * @param network a weak pinter + * @param network a weak pointer */ void setNetwork(std::weak_ptr network); diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp new file mode 100644 index 0000000000..c7ae525fee --- /dev/null +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -0,0 +1,43 @@ +#include "pillar_chain/bls_signature.hpp" +#include "common/encoding_rlp.hpp" +#include + +namespace taraxa { + +BlsSignature::BlsSignature(const dev::RLP& rlp) { + // TODO: parse rlp +} + +BlsSignature::BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, const libff::alt_bn128_Fr& secret) { + pillar_block_hash_ = pillar_block_hash; + public_key_ = public_key; + signature_ = libBLS::Bls::CoreSignAggregated( pillar_block_hash_.toString(), secret ); +} + +bool BlsSignature::isValid() const { + return libBLS::Bls::CoreVerify( public_key_, pillar_block_hash_.toString(), signature_); +} + +blk_hash_t BlsSignature::getPillarBlockHash() const { + return pillar_block_hash_; +} + +dev::bytes BlsSignature::getRlp() const { + dev::RLPStream s(1); + s << pillar_block_hash_; + // TODO: add signature into rlp + //s << signature_; + //s << public_key_; + + return s.invalidate(); +} + +BlsSignature::Hash BlsSignature::getHash() const { + if (!cached_hash_.has_value()) { + cached_hash_ = dev::sha3(getRlp()); + } + + return *cached_hash_; +} + +} // namespace taraxa diff --git a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp new file mode 100644 index 0000000000..8b90267580 --- /dev/null +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -0,0 +1,24 @@ +#include "pillar_chain/pillar_block.hpp" + +#include + +#include "common/encoding_rlp.hpp" + +namespace taraxa { + +PillarBlock::PillarBlock(blk_hash_t epoch_blocks_merkle_root, PillarBlock::Hash previous_pillar_block_hash) + : epoch_blocks_merkle_root_(epoch_blocks_merkle_root), + previous_pillar_block_hash_(previous_pillar_block_hash), + kCachedHash(dev::sha3(getRlp())) {} + +dev::bytes PillarBlock::getRlp() const { + dev::RLPStream s(2); + s << epoch_blocks_merkle_root_; + s << previous_pillar_block_hash_; + + return s.invalidate(); +} + +PillarBlock::Hash PillarBlock::getHash() const { return kCachedHash; } + +} // namespace taraxa 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 new file mode 100644 index 0000000000..2c3325f304 --- /dev/null +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_chain_manager.cpp @@ -0,0 +1,79 @@ +#include "pillar_chain/pillar_chain_manager.hpp" + +#include "network/network.hpp" + +// TODO: should ne #include +#include + +namespace taraxa { + +PillarChainManager::PillarChainManager(std::shared_ptr db, addr_t node_addr) + : db_(std::move(db)), + network_{}, + // TODO: from wallet-config + bls_keys_(libBLS::Bls::KeyGeneration()), + // TODO: last_pillar_block_ might be optional ??? + last_pillar_block_{std::make_shared(blk_hash_t{0}, blk_hash_t{0})}, + last_pillar_block_signatures_{}, + mutex_{} { + libBLS::ThresholdUtils::initCurve(); + + LOG_OBJECTS_CREATE("PILLAR_CHAIN"); +} + +void PillarChainManager::newFinalBlock(const final_chain::FinalizationResult& block_data) { + // TODO: add each final block to final blocks merkle tree + const auto epoch_blocks_merkle_root = block_data.final_chain_blk->hash; + + // Create pillar block and broadcast BLS signature + if (block_data.final_chain_blk->number % kEpochBlocksNum == 0) { + const auto pillar_block = std::make_shared(epoch_blocks_merkle_root, last_pillar_block_->getHash()); + + // TODO: should we save it into db ??? Theoretically pillar blocks can be made from saved final blocks ... + std::scoped_lock lock(mutex_); + last_pillar_block_ = pillar_block; + } else if (block_data.final_chain_blk->number % (kEpochBlocksNum + kBlsSigBroadcastDelayBlocks) == 0) { + // Create and broadcast bls signature with kBlsSigBroadcastDelayBlocks delay to make sure other up-to-date nodes + // already processed the latest pillar block + std::shared_ptr signature; + { + std::shared_lock lock(mutex_); + signature = std::make_shared(last_pillar_block_->getHash(), bls_keys_.second, bls_keys_.first); + } + + if (auto net = network_.lock()) { + net->gossipBlsSignature(signature); + } + + } else if (block_data.final_chain_blk->number % kCheckLatestBlockBlsSigs == 0) { + // Check if the node has 2t+1 bls signatures. If not, request it + std::shared_lock lock(mutex_); + + // TODO: request bls signatures + } +} + +bool PillarChainManager::isRelevantBlsSig(const std::shared_ptr signature) const { + std::shared_lock lock(mutex_); + + if (last_pillar_block_->getHash() != signature->getPillarBlockHash()) { + return false; + } + + if (last_pillar_block_signatures_.contains(signature->getHash())) { + return false; + } + + return true; +} + +bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& signature) { + std::scoped_lock lock(mutex_); + + // TODO: adjust also last_pillar_block_signatures_weight_ + return last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second; +} + +void PillarChainManager::setNetwork(std::weak_ptr network) { network_ = std::move(network); } + +} // namespace taraxa diff --git a/libraries/core_libs/network/include/network/network.hpp b/libraries/core_libs/network/include/network/network.hpp index ae12b3b69b..43a32a8373 100644 --- a/libraries/core_libs/network/include/network/network.hpp +++ b/libraries/core_libs/network/include/network/network.hpp @@ -28,6 +28,7 @@ class TimePeriodPacketsStats; class NodeStats; } // namespace network::tarcap +class BlsSignature; class PacketHandler; class Network { @@ -63,6 +64,7 @@ class Network { void gossipDagBlock(const DagBlock &block, bool proposed, const SharedTransactions &trxs); void gossipVote(const std::shared_ptr &vote, const std::shared_ptr &block, bool rebroadcast = false); void gossipVotesBundle(const std::vector> &votes, bool rebroadcast = false); + void gossipBlsSignature(const std::shared_ptr &signature); void handleMaliciousSyncPeer(const dev::p2p::NodeID &id); std::shared_ptr getMaxChainPeer() const; diff --git a/libraries/core_libs/network/include/network/tarcap/packet_types.hpp b/libraries/core_libs/network/include/network/tarcap/packet_types.hpp index 25ab9ed77d..7defb0338c 100644 --- a/libraries/core_libs/network/include/network/tarcap/packet_types.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packet_types.hpp @@ -29,6 +29,7 @@ enum SubprotocolPacketType : uint32_t { GetPbftSyncPacket, PbftSyncPacket, GetDagSyncPacket, + BlsSigPacket, PacketCount }; diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp new file mode 100644 index 0000000000..1e45ea653a --- /dev/null +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "common/packet_handler.hpp" +#include "pillar_chain/pillar_chain_manager.hpp" + +namespace taraxa::network::tarcap { + +class BlsSigPacketHandler : public PacketHandler { + public: + BlsSigPacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, const addr_t& node_addr, + const std::string& logs_prefix); + + void onNewBlsSig(const std::shared_ptr& signature, bool rebroadcast = false); + void sendBlsSig(const std::shared_ptr& peer, const std::shared_ptr& signature); + + // Packet type that is processed by this handler + static constexpr SubprotocolPacketType kPacketType_ = SubprotocolPacketType::BlsSigPacket; + + private: + virtual void validatePacketRlpFormat(const threadpool::PacketData& packet_data) const override; + virtual void process(const threadpool::PacketData& packet_data, const std::shared_ptr& peer) override; + + protected: + constexpr static size_t kBlsSigPacketSize{1}; + + std::shared_ptr pillar_chain_manager_; +}; + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp index 802277bf89..5f5020ebdf 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp @@ -25,7 +25,7 @@ static const TaraxaCapability::InitPacketsHandlers kInitV1Handlers = const std::shared_ptr &pbft_mgr, const std::shared_ptr &pbft_chain, const std::shared_ptr &vote_mgr, const std::shared_ptr &dag_mgr, const std::shared_ptr &trx_mgr, const std::shared_ptr &slashing_manager, - const addr_t &node_addr) { + const std::shared_ptr &pillar_chain_mgr, const addr_t &node_addr) { auto packets_handlers = std::make_shared(); // Consensus packets with high processing priority @@ -62,6 +62,10 @@ static const TaraxaCapability::InitPacketsHandlers kInitV1Handlers = config, peers_state, packets_stats, pbft_syncing_state, pbft_chain, pbft_mgr, dag_mgr, vote_mgr, db, node_addr, logs_prefix); + // TODO: should ut be registered also for V1 ? + packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, + node_addr, logs_prefix); + return packets_handlers; }; diff --git a/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp b/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp index 0e09c62ed4..3f3a2761cf 100644 --- a/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp +++ b/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp @@ -24,6 +24,7 @@ class VoteManager; class DagManager; class TransactionManager; class SlashingManager; +class PillarChainManager; enum class TransactionStatus; } // namespace taraxa @@ -46,7 +47,7 @@ class TaraxaCapability final : public dev::p2p::CapabilityFace { const std::shared_ptr &pbft_mgr, const std::shared_ptr &pbft_chain, const std::shared_ptr &vote_mgr, const std::shared_ptr &dag_mgr, const std::shared_ptr &trx_mgr, const std::shared_ptr &slashing_manager, - const addr_t &node_addr)>; + const std::shared_ptr &pillar_chain_mgr, const addr_t &node_addr)>; /** * @brief Default InitPacketsHandlers function definition with the latest version of packets handlers diff --git a/libraries/core_libs/network/include/network/tarcap/taraxa_peer.hpp b/libraries/core_libs/network/include/network/tarcap/taraxa_peer.hpp index ca8983973a..844ccd8995 100644 --- a/libraries/core_libs/network/include/network/tarcap/taraxa_peer.hpp +++ b/libraries/core_libs/network/include/network/tarcap/taraxa_peer.hpp @@ -7,6 +7,7 @@ #include "common/util.hpp" #include "network/tarcap/stats/packets_stats.hpp" +#include "pillar_chain/bls_signature.hpp" namespace taraxa::network::tarcap { @@ -54,6 +55,16 @@ class TaraxaPeer : public boost::noncopyable { bool markPbftBlockAsKnown(const blk_hash_t& hash); bool isPbftBlockKnown(const blk_hash_t& hash) const; + /** + * @brief Mark bls signature as known + * + * @param _hash + * @return true in case bls signature was actually marked as known(was not known before), otherwise false (was already + * known) + */ + bool markBlsSigAsKnown(const BlsSignature::Hash& hash); + bool isBlsSigKnown(const BlsSignature::Hash& hash) const; + const dev::p2p::NodeID& getId() const; /** @@ -121,7 +132,8 @@ class TaraxaPeer : public boost::noncopyable { ExpirationBlockNumberCache known_transactions_; // PBFT ExpirationBlockNumberCache known_pbft_blocks_; - ExpirationBlockNumberCache known_votes_; // for peers + ExpirationBlockNumberCache known_votes_; + ExpirationBlockNumberCache known_bls_signature_; std::atomic timestamp_suspicious_packet_ = 0; std::atomic suspicious_packet_count_ = 0; diff --git a/libraries/core_libs/network/src/network.cpp b/libraries/core_libs/network/src/network.cpp index a12cede4d6..cfbd341c14 100644 --- a/libraries/core_libs/network/src/network.cpp +++ b/libraries/core_libs/network/src/network.cpp @@ -8,6 +8,7 @@ #include #include "config/version.hpp" +#include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/pbft_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/votes_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/v1/init_packets_handlers.hpp" @@ -16,6 +17,7 @@ #include "network/tarcap/stats/time_period_packets_stats.hpp" #include "network/tarcap/taraxa_capability.hpp" #include "pbft/pbft_manager.hpp" +#include "pillar_chain/bls_signature.hpp" namespace taraxa { @@ -298,6 +300,12 @@ void Network::gossipVotesBundle(const std::vector> &votes, } } +void Network::gossipBlsSignature(const std::shared_ptr &signature) { + for (const auto &tarcap : tarcaps_) { + tarcap.second->getSpecificHandler()->onNewBlsSig(signature); + } +} + void Network::handleMaliciousSyncPeer(const dev::p2p::NodeID &node_id) { for (const auto &tarcap : tarcaps_) { // Peer is present only in one taraxa capability depending on his network version diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp new file mode 100644 index 0000000000..2431ae3fa9 --- /dev/null +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp @@ -0,0 +1,67 @@ +#include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" + +#include "pillar_chain/pillar_chain_manager.hpp" + +namespace taraxa::network::tarcap { + +BlsSigPacketHandler::BlsSigPacketHandler(const FullNodeConfig &conf, std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, + const addr_t &node_addr, const std::string &logs_prefix) + : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "BLS_SIG_PH"), + pillar_chain_manager_{std::move(pillar_chain_manager)} {} + +void BlsSigPacketHandler::validatePacketRlpFormat([[maybe_unused]] const threadpool::PacketData &packet_data) const { + auto items = packet_data.rlp_.itemCount(); + if (items != kBlsSigPacketSize) { + throw InvalidRlpItemsCountException(packet_data.type_str_, items, kBlsSigPacketSize); + } +} + +void BlsSigPacketHandler::process(const threadpool::PacketData &packet_data, const std::shared_ptr &peer) { + const auto bls_signature = std::make_shared(packet_data.rlp_[0]); + + if (!pillar_chain_manager_->isRelevantBlsSig(bls_signature)) { + LOG(log_dg_) << "Drop irrelevant signature " << bls_signature->getHash() << " from peer " << peer->getId(); + } + + if (!bls_signature->isValid()) { + std::ostringstream err_msg; + err_msg << "Invalid signature " << bls_signature->getHash() << " from peer " << peer->getId(); + throw MaliciousPeerException(err_msg.str()); + } + + pillar_chain_manager_->addVerifiedBlsSig(bls_signature); + + // Mark bls signature as known for peer + peer->markBlsSigAsKnown(bls_signature->getHash()); + onNewBlsSig(bls_signature); +} + +void BlsSigPacketHandler::onNewBlsSig(const std::shared_ptr &signature, bool rebroadcast) { + for (const auto &peer : peers_state_->getAllPeers()) { + if (peer.second->syncing_) { + LOG(log_dg_) << " PBFT vote " << signature << " not sent to " << peer.first << " peer syncing"; + continue; + } + + if (peer.second->isBlsSigKnown(signature->getHash()) && !rebroadcast) { + continue; + } + + sendBlsSig(peer.second, signature); + } +} + +void BlsSigPacketHandler::sendBlsSig(const std::shared_ptr &peer, + const std::shared_ptr &signature) { + dev::RLPStream s(1); + s.appendRaw(signature->getRlp()); + + if (sealAndSend(peer->getId(), SubprotocolPacketType::BlsSigPacket, std::move(s))) { + peer->markBlsSigAsKnown(signature->getHash()); + LOG(log_dg_) << "BLS signature " << signature->getHash() << " sent to " << peer->getId(); + } +} + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp b/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp index 301678d7d2..c4e67a5d09 100644 --- a/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp +++ b/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp @@ -3,6 +3,7 @@ #include #include "network/tarcap/packets_handler.hpp" +#include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_block_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_dag_sync_packet_handler.hpp" @@ -213,7 +214,7 @@ const TaraxaCapability::InitPacketsHandlers TaraxaCapability::kInitLatestVersion const std::shared_ptr &pbft_mgr, const std::shared_ptr &pbft_chain, const std::shared_ptr &vote_mgr, const std::shared_ptr &dag_mgr, const std::shared_ptr &trx_mgr, const std::shared_ptr &slashing_manager, - const addr_t &node_addr) { + const std::shared_ptr &pillar_chain_mgr, const addr_t &node_addr) { auto packets_handlers = std::make_shared(); // Consensus packets with high processing priority packets_handlers->registerHandler(config, peers_state, packets_stats, pbft_mgr, pbft_chain, @@ -248,6 +249,8 @@ const TaraxaCapability::InitPacketsHandlers TaraxaCapability::kInitLatestVersion packets_handlers->registerHandler(config, peers_state, packets_stats, pbft_syncing_state, pbft_chain, pbft_mgr, dag_mgr, vote_mgr, db, node_addr, logs_prefix); + packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, + node_addr, logs_prefix); return packets_handlers; }; diff --git a/libraries/core_libs/network/src/tarcap/taraxa_peer.cpp b/libraries/core_libs/network/src/tarcap/taraxa_peer.cpp index 1bf9a8b9a3..6849a0559a 100644 --- a/libraries/core_libs/network/src/tarcap/taraxa_peer.cpp +++ b/libraries/core_libs/network/src/tarcap/taraxa_peer.cpp @@ -6,7 +6,8 @@ TaraxaPeer::TaraxaPeer() : known_dag_blocks_(10000, 1000, 10), known_transactions_(100000, 10000, 10), known_pbft_blocks_(10000, 1000, 10), - known_votes_(10000, 1000, 10) {} + known_votes_(10000, 1000, 10), + known_bls_signature_(10000, 1000, 10) {} TaraxaPeer::TaraxaPeer(const dev::p2p::NodeID& id, size_t transaction_pool_size, std::string address) : address_(address), @@ -14,7 +15,8 @@ TaraxaPeer::TaraxaPeer(const dev::p2p::NodeID& id, size_t transaction_pool_size, known_dag_blocks_(10000, 1000, 10), known_transactions_(transaction_pool_size * 1.2, transaction_pool_size / 10, 10), known_pbft_blocks_(10000, 1000, 10), - known_votes_(100000, 1000, 10) {} + known_votes_(100000, 1000, 10), + known_bls_signature_(10000, 1000, 10) {} bool TaraxaPeer::markDagBlockAsKnown(const blk_hash_t& hash) { return known_dag_blocks_.insert(hash, pbft_chain_size_); @@ -38,6 +40,12 @@ bool TaraxaPeer::markPbftBlockAsKnown(const blk_hash_t& hash) { bool TaraxaPeer::isPbftBlockKnown(const blk_hash_t& hash) const { return known_pbft_blocks_.contains(hash); } +bool TaraxaPeer::markBlsSigAsKnown(const BlsSignature::Hash& hash) { + return known_bls_signature_.insert(hash, pbft_chain_size_); +} + +bool TaraxaPeer::isBlsSigKnown(const BlsSignature::Hash& hash) const { return known_bls_signature_.contains(hash); } + const dev::p2p::NodeID& TaraxaPeer::getId() const { return id_; } bool TaraxaPeer::reportSuspiciousPacket() { diff --git a/libraries/core_libs/node/include/node/node.hpp b/libraries/core_libs/node/include/node/node.hpp index d90b52f9fe..26cb8b963c 100644 --- a/libraries/core_libs/node/include/node/node.hpp +++ b/libraries/core_libs/node/include/node/node.hpp @@ -42,6 +42,7 @@ struct Transaction; class TransactionManager; class GasPricer; class PbftManager; +class PillarChainManager; struct NetworkConfig; class KeyManager; @@ -106,6 +107,7 @@ class FullNode : public std::enable_shared_from_this { std::shared_ptr vote_mgr_; std::shared_ptr pbft_mgr_; std::shared_ptr pbft_chain_; + std::shared_ptr pillar_chain_; std::shared_ptr key_manager_; std::shared_ptr final_chain_; std::shared_ptr jsonrpc_http_; diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index a95d68b421..9977395041 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -26,6 +26,7 @@ #include "network/rpc/jsonrpc_http_processor.hpp" #include "network/rpc/jsonrpc_ws_server.hpp" #include "pbft/pbft_manager.hpp" +#include "pillar_chain/pillar_chain_manager.hpp" #include "slashing_manager/slashing_manager.hpp" #include "storage/migration/migration_manager.hpp" #include "transaction/gas_pricer.hpp" @@ -123,10 +124,11 @@ void FullNode::init() { } pbft_chain_ = std::make_shared(node_addr, db_); - dag_mgr_ = std::make_shared( - conf_.genesis.dag_genesis_block, node_addr, conf_.genesis.sortition, conf_.genesis.dag, trx_mgr_, pbft_chain_, - final_chain_, db_, key_manager_, conf_.genesis.pbft.gas_limit, conf_.genesis.state, conf_.is_light_node, - conf_.light_node_history, conf_.max_levels_per_period, conf_.dag_expiry_limit); + pillar_chain_ = std::make_shared(db_, node_addr); + dag_mgr_ = std::make_shared(conf_.genesis.dag_genesis_block, node_addr, conf_.genesis.sortition, + conf_.genesis.dag, trx_mgr_, pbft_chain_, final_chain_, db_, key_manager_, + conf_.genesis.pbft.gas_limit, conf_.genesis.state, conf_.light_node_history, + conf_.max_levels_per_period, conf_.dag_expiry_limit); auto slashing_manager = std::make_shared(final_chain_, trx_mgr_, gas_pricer_, conf_, kp_.secret()); vote_mgr_ = std::make_shared(node_addr, conf_.genesis.pbft, kp_.secret(), conf_.vrf_secret, db_, pbft_chain_, final_chain_, key_manager_, slashing_manager); @@ -317,6 +319,15 @@ void FullNode::start() { } }, subscription_pool_); + + // TODO: send new block to pillar chain for processing + final_chain_->block_finalized_.subscribe( + [pillar_chain_weak = as_weak(pillar_chain_)](const auto &res) { + if (auto pillar_chain = pillar_chain_weak.lock()) { + pillar_chain->newFinalBlock(res); + } + }, + subscription_pool_); } vote_mgr_->setNetwork(network_); From 081df7b8eb9ed38fec9e3d21c6b72380a467c57b Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Mon, 18 Sep 2023 17:50:25 -0700 Subject: [PATCH 05/20] added bls siagntures syncing --- .../include/pillar_chain/bls_signature.hpp | 8 +-- .../pillar_chain/pillar_chain_manager.hpp | 4 +- .../src/pillar_chain/bls_signature.cpp | 41 ++++++++------- .../src/pillar_chain/pillar_chain_manager.cpp | 24 ++++++++- .../include/network/tarcap/packet_types.hpp | 8 +++ .../latest/bls_sig_packet_handler.hpp | 7 +-- .../latest/bls_sigs_bundle_packet_handler.hpp | 25 ++++++++++ .../common/ext_bls_sig_packet_handler.hpp | 22 ++++++++ .../get_bls_sigs_bundle_packet_handler.hpp | 31 ++++++++++++ .../latest/bls_sig_packet_handler.cpp | 26 ++-------- .../latest/bls_sigs_bundle_packet_handler.cpp | 29 +++++++++++ .../common/ext_bls_sig_packet_handler.cpp | 32 ++++++++++++ .../get_bls_sigs_bundle_packet_handler.cpp | 50 +++++++++++++++++++ .../network/src/threadpool/priority_queue.cpp | 3 ++ 14 files changed, 260 insertions(+), 50 deletions(-) create mode 100644 libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp create mode 100644 libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp create mode 100644 libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp create mode 100644 libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp create mode 100644 libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp create mode 100644 libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp index fbe83613b4..68909fc191 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -1,14 +1,15 @@ #pragma once -#include "common/types.hpp" #include #include + #include + +#include "common/types.hpp" #include "pillar_chain/pillar_block.hpp" namespace taraxa { - /** @addtogroup PILLAR_CHAIN * @{ */ @@ -23,7 +24,8 @@ class BlsSignature { public: BlsSignature(const dev::RLP& rlp); - BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, const libff::alt_bn128_Fr& secret); + BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, + const libff::alt_bn128_Fr& secret); /** * @brief Validates BLS signature diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index e01fdf14d5..fd03ebf42a 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -54,10 +54,10 @@ class PillarChainManager { bool addVerifiedBlsSig(const std::shared_ptr& signature); /** - * @brief Get all bls signatures + * @brief Get all bls signatures for specified pillar block * @return all bls signatures */ - // std::vector> getVerifiedBlsSigs() const; + std::vector> getVerifiedBlsSigs(const PillarBlock::Hash pillar_block_hash) const; private: std::shared_ptr db_; diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp index c7ae525fee..d1064cbfb7 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -1,33 +1,40 @@ #include "pillar_chain/bls_signature.hpp" -#include "common/encoding_rlp.hpp" + #include +#include "common/encoding_rlp.hpp" + namespace taraxa { BlsSignature::BlsSignature(const dev::RLP& rlp) { - // TODO: parse rlp -} + std::string sig_str, pk_str; + util::rlp_tuple(util::RLPDecoderRef(rlp, true), pillar_block_hash_, sig_str, pk_str); -BlsSignature::BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, const libff::alt_bn128_Fr& secret) { - pillar_block_hash_ = pillar_block_hash; - public_key_ = public_key; - signature_ = libBLS::Bls::CoreSignAggregated( pillar_block_hash_.toString(), secret ); + std::stringstream(sig_str) >> signature_; + std::stringstream(pk_str) >> public_key_; } -bool BlsSignature::isValid() const { - return libBLS::Bls::CoreVerify( public_key_, pillar_block_hash_.toString(), signature_); -} +BlsSignature::BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, + const libff::alt_bn128_Fr& secret) + : pillar_block_hash_(pillar_block_hash), + signature_(libBLS::Bls::CoreSignAggregated(getHash().toString(), secret)), + public_key_(public_key) {} -blk_hash_t BlsSignature::getPillarBlockHash() const { - return pillar_block_hash_; -} +bool BlsSignature::isValid() const { return libBLS::Bls::CoreVerify(public_key_, getHash().toString(), signature_); } + +blk_hash_t BlsSignature::getPillarBlockHash() const { return pillar_block_hash_; } dev::bytes BlsSignature::getRlp() const { - dev::RLPStream s(1); + dev::RLPStream s(3); s << pillar_block_hash_; - // TODO: add signature into rlp - //s << signature_; - //s << public_key_; + + std::stringstream sig_ss; + sig_ss << signature_; + s << sig_ss.str(); + + std::stringstream pk_ss; + pk_ss << public_key_; + s << pk_ss.str(); return s.invalidate(); } 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 2c3325f304..748d06b026 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 @@ -70,8 +70,28 @@ bool PillarChainManager::isRelevantBlsSig(const std::shared_ptr si bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& signature) { std::scoped_lock lock(mutex_); - // TODO: adjust also last_pillar_block_signatures_weight_ - return last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second; + if (last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second) { + // TODO: adjust also last_pillar_block_signatures_weight_ + + return true; + } + + return false; +} + +std::vector> PillarChainManager::getVerifiedBlsSigs(const PillarBlock::Hash pillar_block_hash) const { + std::shared_lock lock(mutex_); + if (pillar_block_hash != last_pillar_block_->getHash()) { + return {}; + } + + std::vector> signatures; + signatures.reserve(last_pillar_block_signatures_.size()); + for (const auto& sig: last_pillar_block_signatures_) { + signatures.push_back(sig.second); + } + + return signatures; } void PillarChainManager::setNetwork(std::weak_ptr network) { network_ = std::move(network); } diff --git a/libraries/core_libs/network/include/network/tarcap/packet_types.hpp b/libraries/core_libs/network/include/network/tarcap/packet_types.hpp index 7defb0338c..a2bc3694bb 100644 --- a/libraries/core_libs/network/include/network/tarcap/packet_types.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packet_types.hpp @@ -30,6 +30,8 @@ enum SubprotocolPacketType : uint32_t { PbftSyncPacket, GetDagSyncPacket, BlsSigPacket, + GetBlsSigsBundlePacket, + BlsSigsBundlePacket, PacketCount }; @@ -60,6 +62,12 @@ inline std::string convertPacketTypeToString(SubprotocolPacketType packet_type) return "GetPbftSyncPacket"; case PbftSyncPacket: return "PbftSyncPacket"; + case BlsSigPacket: + return "BlsSigPacket"; + case GetBlsSigsBundlePacket: + return "GetBlsSigsBundlePacket"; + case BlsSigsBundlePacket: + return "BlsSigsBundlePacket"; default: break; } diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp index 1e45ea653a..9f891221c1 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp @@ -1,11 +1,10 @@ #pragma once -#include "common/packet_handler.hpp" -#include "pillar_chain/pillar_chain_manager.hpp" +#include "common/ext_bls_sig_packet_handler.hpp" namespace taraxa::network::tarcap { -class BlsSigPacketHandler : public PacketHandler { +class BlsSigPacketHandler : public ExtBlsSigPacketHandler { public: BlsSigPacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, @@ -24,8 +23,6 @@ class BlsSigPacketHandler : public PacketHandler { protected: constexpr static size_t kBlsSigPacketSize{1}; - - std::shared_ptr pillar_chain_manager_; }; } // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp new file mode 100644 index 0000000000..16748dcca4 --- /dev/null +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "common/ext_bls_sig_packet_handler.hpp" + +namespace taraxa::network::tarcap { + +class BlsSigsBundlePacketHandler : public ExtBlsSigPacketHandler { + public: + BlsSigsBundlePacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, const addr_t& node_addr, + const std::string& logs_prefix); + + // Packet type that is processed by this handler + static constexpr SubprotocolPacketType kPacketType_ = SubprotocolPacketType::BlsSigsBundlePacket; + + private: + virtual void validatePacketRlpFormat(const threadpool::PacketData& packet_data) const override; + virtual void process(const threadpool::PacketData& packet_data, const std::shared_ptr& peer) override; + + protected: + constexpr static size_t kMaxSignaturesInBundleRlp{250}; +}; + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp new file mode 100644 index 0000000000..0e7fe1c10e --- /dev/null +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "packet_handler.hpp" +#include "pillar_chain/pillar_chain_manager.hpp" + +namespace taraxa::network::tarcap { + +class ExtBlsSigPacketHandler : public PacketHandler { + public: + ExtBlsSigPacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, const addr_t& node_addr, + const std::string& logs_prefix); + + protected: + void processBlsSignature(const std::shared_ptr& signature, const std::shared_ptr& peer); + + protected: + std::shared_ptr pillar_chain_manager_; +}; + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp new file mode 100644 index 0000000000..93deb71589 --- /dev/null +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "common/packet_handler.hpp" +#include "pillar_chain/pillar_block.hpp" +#include "pillar_chain/pillar_chain_manager.hpp" + +namespace taraxa::network::tarcap { + +class GetBlsSigsBundlePacketHandler : public PacketHandler { + public: + GetBlsSigsBundlePacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, const addr_t& node_addr, + const std::string& logs_prefix); + + void requestBlsSigsBundle(PillarBlock::Hash pillar_block_hash, const std::shared_ptr& peer); + + // Packet type that is processed by this handler + static constexpr SubprotocolPacketType kPacketType_ = SubprotocolPacketType::GetBlsSigsBundlePacket; + + private: + virtual void validatePacketRlpFormat(const threadpool::PacketData& packet_data) const override; + virtual void process(const threadpool::PacketData& packet_data, const std::shared_ptr& peer) override; + + protected: + constexpr static size_t kGetBlsSigsPacketSize{1}; + + std::shared_ptr pillar_chain_manager_; +}; + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp index 2431ae3fa9..6c382e3eac 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp @@ -1,15 +1,13 @@ #include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" -#include "pillar_chain/pillar_chain_manager.hpp" - namespace taraxa::network::tarcap { BlsSigPacketHandler::BlsSigPacketHandler(const FullNodeConfig &conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, std::shared_ptr pillar_chain_manager, const addr_t &node_addr, const std::string &logs_prefix) - : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "BLS_SIG_PH"), - pillar_chain_manager_{std::move(pillar_chain_manager)} {} + : ExtBlsSigPacketHandler(conf, std::move(peers_state), std::move(packets_stats), std::move(pillar_chain_manager), + node_addr, logs_prefix + "BLS_SIG_PH") {} void BlsSigPacketHandler::validatePacketRlpFormat([[maybe_unused]] const threadpool::PacketData &packet_data) const { auto items = packet_data.rlp_.itemCount(); @@ -19,29 +17,15 @@ void BlsSigPacketHandler::validatePacketRlpFormat([[maybe_unused]] const threadp } void BlsSigPacketHandler::process(const threadpool::PacketData &packet_data, const std::shared_ptr &peer) { - const auto bls_signature = std::make_shared(packet_data.rlp_[0]); - - if (!pillar_chain_manager_->isRelevantBlsSig(bls_signature)) { - LOG(log_dg_) << "Drop irrelevant signature " << bls_signature->getHash() << " from peer " << peer->getId(); - } - - if (!bls_signature->isValid()) { - std::ostringstream err_msg; - err_msg << "Invalid signature " << bls_signature->getHash() << " from peer " << peer->getId(); - throw MaliciousPeerException(err_msg.str()); - } - - pillar_chain_manager_->addVerifiedBlsSig(bls_signature); - - // Mark bls signature as known for peer - peer->markBlsSigAsKnown(bls_signature->getHash()); + const auto bls_signature = std::make_shared(packet_data.rlp_); + processBlsSignature(bls_signature, peer); onNewBlsSig(bls_signature); } void BlsSigPacketHandler::onNewBlsSig(const std::shared_ptr &signature, bool rebroadcast) { for (const auto &peer : peers_state_->getAllPeers()) { if (peer.second->syncing_) { - LOG(log_dg_) << " PBFT vote " << signature << " not sent to " << peer.first << " peer syncing"; + LOG(log_dg_) << "BLS signature " << signature->getHash() << " not sent to " << peer.first << " peer syncing"; continue; } diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp new file mode 100644 index 0000000000..9e33c53bb4 --- /dev/null +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp @@ -0,0 +1,29 @@ +#include "network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp" + +namespace taraxa::network::tarcap { + +BlsSigsBundlePacketHandler::BlsSigsBundlePacketHandler(const FullNodeConfig &conf, + std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, + const addr_t &node_addr, const std::string &logs_prefix) + : ExtBlsSigPacketHandler(conf, std::move(peers_state), std::move(packets_stats), std::move(pillar_chain_manager), + node_addr, logs_prefix + "BLS_SIGS_BUNDLE_PH") {} + +void BlsSigsBundlePacketHandler::validatePacketRlpFormat( + [[maybe_unused]] const threadpool::PacketData &packet_data) const { + auto items = packet_data.rlp_.itemCount(); + if (items == 0 || items > kMaxSignaturesInBundleRlp) { + throw InvalidRlpItemsCountException(packet_data.type_str_, items, kMaxSignaturesInBundleRlp); + } +} + +void BlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet_data, + const std::shared_ptr &peer) { + for (const auto signature_rlp : packet_data.rlp_) { + const auto bls_signature = std::make_shared(signature_rlp); + processBlsSignature(bls_signature, peer); + } +} + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp new file mode 100644 index 0000000000..4433395ca3 --- /dev/null +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp @@ -0,0 +1,32 @@ +#include "network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp" + +#include "pillar_chain/pillar_chain_manager.hpp" + +namespace taraxa::network::tarcap { + +ExtBlsSigPacketHandler::ExtBlsSigPacketHandler(const FullNodeConfig &conf, std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, + const addr_t &node_addr, const std::string &logs_prefix) + : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "BLS_SIG_PH"), + pillar_chain_manager_{std::move(pillar_chain_manager)} {} + +void ExtBlsSigPacketHandler::processBlsSignature(const std::shared_ptr &signature, + const std::shared_ptr &peer) { + if (!pillar_chain_manager_->isRelevantBlsSig(signature)) { + LOG(log_dg_) << "Drop irrelevant signature " << signature->getHash() << " from peer " << peer->getId(); + } + + if (!signature->isValid()) { + std::ostringstream err_msg; + err_msg << "Invalid signature " << signature->getHash() << " from peer " << peer->getId(); + throw MaliciousPeerException(err_msg.str()); + } + + pillar_chain_manager_->addVerifiedBlsSig(signature); + + // Mark bls signature as known for peer + peer->markBlsSigAsKnown(signature->getHash()); +} + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp new file mode 100644 index 0000000000..5f3f43ea5a --- /dev/null +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp @@ -0,0 +1,50 @@ +#include "network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp" + +namespace taraxa::network::tarcap { + +GetBlsSigsBundlePacketHandler::GetBlsSigsBundlePacketHandler(const FullNodeConfig &conf, + std::shared_ptr peers_state, + std::shared_ptr packets_stats, + std::shared_ptr pillar_chain_manager, + const addr_t &node_addr, const std::string &logs_prefix) + : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "GET_BLS_SIGS_BUNDLE_PH"), + pillar_chain_manager_(std::move(std::move(pillar_chain_manager))) {} + +void GetBlsSigsBundlePacketHandler::validatePacketRlpFormat( + [[maybe_unused]] const threadpool::PacketData &packet_data) const { + auto items = packet_data.rlp_.itemCount(); + if (items != kGetBlsSigsPacketSize) { + throw InvalidRlpItemsCountException(packet_data.type_str_, items, kGetBlsSigsPacketSize); + } +} + +void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet_data, + const std::shared_ptr &peer) { + const PillarBlock::Hash pillar_block_hash = packet_data.rlp_.toHash(); + + const auto signatures = pillar_chain_manager_->getVerifiedBlsSigs(pillar_block_hash); + + // TODO: split packet to multiple with kGetBlsSigsPacketSize sigs containing each + dev::RLPStream s(signatures.size()); + for (const auto& sig : signatures) { + s.appendRaw(sig->getRlp()); + } + + if (sealAndSend(peer->getId(), SubprotocolPacketType::BlsSigsBundlePacket, std::move(s))) {\ + for (const auto& sig : signatures) { + peer->markBlsSigAsKnown(sig->getHash()); + } + + LOG(log_dg_) << "BLS signatures bundle sent to " << peer->getId(); + } +} + +void GetBlsSigsBundlePacketHandler::requestBlsSigsBundle(PillarBlock::Hash pillar_block_hash, const std::shared_ptr& peer) { + dev::RLPStream s(1); + s << pillar_block_hash; + + sealAndSend(peer->getId(), SubprotocolPacketType::GetBlsSigsBundlePacket, std::move(s)); + LOG(log_dg_) << "Requested BLS signatures bundle for pillar block " << pillar_block_hash << " from peer " << peer->getId(); +} + +} // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/threadpool/priority_queue.cpp b/libraries/core_libs/network/src/threadpool/priority_queue.cpp index 35a16922b5..3514fbf840 100644 --- a/libraries/core_libs/network/src/threadpool/priority_queue.cpp +++ b/libraries/core_libs/network/src/threadpool/priority_queue.cpp @@ -134,9 +134,12 @@ void PriorityQueue::updateDependenciesStart(const PacketData& packet) { // Packets that can be processed only 1 at the time // GetDagSyncPacket -> serve dag syncing data to only 1 node at the time // GetPbftSyncPacket -> serve pbft syncing data to only 1 node at the time + // GetBlsSigsBundlePacket -> serve bls signatures syncing data to only 1 node at the time // PbftSyncPacket -> process sync pbft blocks synchronously case SubprotocolPacketType::GetDagSyncPacket: case SubprotocolPacketType::GetPbftSyncPacket: + case SubprotocolPacketType::GetBlsSigsBundlePacket: + case SubprotocolPacketType::BlsSigsBundlePacket: case SubprotocolPacketType::PbftSyncPacket: blocked_packets_mask_.markPacketAsHardBlocked(packet, packet.type_); break; From d06c32c831c9db9195465811d4d9010b504e8cfd Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 20 Sep 2023 11:08:02 -0700 Subject: [PATCH 06/20] create bls signature syncing mechanism --- .../pillar_chain/pillar_chain_manager.hpp | 2 +- .../src/pillar_chain/pillar_chain_manager.cpp | 17 ++++++++++++----- .../network/include/network/network.hpp | 7 +++++++ .../get_bls_sigs_bundle_packet_handler.hpp | 2 +- libraries/core_libs/network/src/network.cpp | 17 +++++++++++++++++ .../latest/bls_sigs_bundle_packet_handler.cpp | 2 ++ .../get_bls_sigs_bundle_packet_handler.cpp | 15 +++++++++------ 7 files changed, 49 insertions(+), 13 deletions(-) diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index fd03ebf42a..c2cf9b5ead 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -91,7 +91,7 @@ class PillarChainManager { // How often to check if node has 2t+1 bls signature for the latest pillar block & potentially trigger syncing // TODO: validation: kCheckLatestBlockBlsSigs should be way smaller than kEpochBlocksNum and bigger than // kBlsSigBroadcastDelayBlocks - static constexpr uint16_t kCheckLatestBlockBlsSigs = 5; + static constexpr uint16_t kCheckLatestBlockBlsSigs = 10; LOG_OBJECTS_DEFINE }; 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 748d06b026..1ae72c7ec7 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 @@ -46,10 +46,16 @@ void PillarChainManager::newFinalBlock(const final_chain::FinalizationResult& bl } } else if (block_data.final_chain_blk->number % kCheckLatestBlockBlsSigs == 0) { - // Check if the node has 2t+1 bls signatures. If not, request it - std::shared_lock lock(mutex_); + PillarBlock::Hash last_pillar_block_hash; + { + std::shared_lock lock(mutex_); + last_pillar_block_hash = last_pillar_block_->getHash(); + } - // TODO: request bls signatures + // TODO: Request signature only if node does not have 2t+1 bls signatures + if (auto net = network_.lock()) { + net->requestBlsSigBundle(last_pillar_block_hash); + } } } @@ -79,7 +85,8 @@ bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& return false; } -std::vector> PillarChainManager::getVerifiedBlsSigs(const PillarBlock::Hash pillar_block_hash) const { +std::vector> PillarChainManager::getVerifiedBlsSigs( + const PillarBlock::Hash pillar_block_hash) const { std::shared_lock lock(mutex_); if (pillar_block_hash != last_pillar_block_->getHash()) { return {}; @@ -87,7 +94,7 @@ std::vector> PillarChainManager::getVerifiedBlsSig std::vector> signatures; signatures.reserve(last_pillar_block_signatures_.size()); - for (const auto& sig: last_pillar_block_signatures_) { + for (const auto& sig : last_pillar_block_signatures_) { signatures.push_back(sig.second); } diff --git a/libraries/core_libs/network/include/network/network.hpp b/libraries/core_libs/network/include/network/network.hpp index 43a32a8373..f36b877165 100644 --- a/libraries/core_libs/network/include/network/network.hpp +++ b/libraries/core_libs/network/include/network/network.hpp @@ -68,6 +68,13 @@ class Network { void handleMaliciousSyncPeer(const dev::p2p::NodeID &id); std::shared_ptr getMaxChainPeer() const; + /** + * @brief Request bls signatures bundle packet from random peer + * + * @param pillar_block_hash + */ + void requestBlsSigBundle(const PillarBlock::Hash &pillar_block_hash); + // METHODS USED IN TESTS ONLY template std::shared_ptr getSpecificHandler() const; diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp index 93deb71589..71df6ddac8 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp @@ -13,7 +13,7 @@ class GetBlsSigsBundlePacketHandler : public PacketHandler { std::shared_ptr pillar_chain_manager, const addr_t& node_addr, const std::string& logs_prefix); - void requestBlsSigsBundle(PillarBlock::Hash pillar_block_hash, const std::shared_ptr& peer); + void requestBlsSigsBundle(const PillarBlock::Hash& pillar_block_hash, const std::shared_ptr& peer); // Packet type that is processed by this handler static constexpr SubprotocolPacketType kPacketType_ = SubprotocolPacketType::GetBlsSigsBundlePacket; diff --git a/libraries/core_libs/network/src/network.cpp b/libraries/core_libs/network/src/network.cpp index cfbd341c14..59ca1ce481 100644 --- a/libraries/core_libs/network/src/network.cpp +++ b/libraries/core_libs/network/src/network.cpp @@ -9,6 +9,7 @@ #include "config/version.hpp" #include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" +#include "network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/pbft_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/votes_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/v1/init_packets_handlers.hpp" @@ -337,6 +338,22 @@ std::shared_ptr Network::getMaxChainPeer() const { return max_chain_peer; } +void Network::requestBlsSigBundle(const PillarBlock::Hash &pillar_block_hash) { + for (const auto &tarcap : tarcaps_) { + // Try to get most up-to-date peer + const auto peer = + tarcap.second->getSpecificHandler<::taraxa::network::tarcap::PbftSyncPacketHandler>()->getMaxChainPeer(); + + if (!peer) { + continue; + } + + // TODO: is it good enough to request it just from 1 peer without knowing if he has all of the signatures ? + tarcap.second->getSpecificHandler()->requestBlsSigsBundle( + pillar_block_hash, peer); + } +} + // METHODS USED IN TESTS ONLY // Note: for functions use in tests all data are fetched only from the tarcap with the highest version, // other functions must use all tarcaps diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp index 9e33c53bb4..f6558ca2d8 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.cpp @@ -20,6 +20,8 @@ void BlsSigsBundlePacketHandler::validatePacketRlpFormat( void BlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet_data, const std::shared_ptr &peer) { + // TODO: there could be the same protection as in pbft syncing that only requested bundle packet is accepted + for (const auto signature_rlp : packet_data.rlp_) { const auto bls_signature = std::make_shared(signature_rlp); processBlsSignature(bls_signature, peer); diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp index 5f3f43ea5a..4ad817f68b 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp @@ -7,7 +7,8 @@ GetBlsSigsBundlePacketHandler::GetBlsSigsBundlePacketHandler(const FullNodeConfi std::shared_ptr packets_stats, std::shared_ptr pillar_chain_manager, const addr_t &node_addr, const std::string &logs_prefix) - : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "GET_BLS_SIGS_BUNDLE_PH"), + : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, + logs_prefix + "GET_BLS_SIGS_BUNDLE_PH"), pillar_chain_manager_(std::move(std::move(pillar_chain_manager))) {} void GetBlsSigsBundlePacketHandler::validatePacketRlpFormat( @@ -26,12 +27,12 @@ void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet // TODO: split packet to multiple with kGetBlsSigsPacketSize sigs containing each dev::RLPStream s(signatures.size()); - for (const auto& sig : signatures) { + for (const auto &sig : signatures) { s.appendRaw(sig->getRlp()); } - if (sealAndSend(peer->getId(), SubprotocolPacketType::BlsSigsBundlePacket, std::move(s))) {\ - for (const auto& sig : signatures) { + if (sealAndSend(peer->getId(), SubprotocolPacketType::BlsSigsBundlePacket, std::move(s))) { + for (const auto &sig : signatures) { peer->markBlsSigAsKnown(sig->getHash()); } @@ -39,12 +40,14 @@ void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet } } -void GetBlsSigsBundlePacketHandler::requestBlsSigsBundle(PillarBlock::Hash pillar_block_hash, const std::shared_ptr& peer) { +void GetBlsSigsBundlePacketHandler::requestBlsSigsBundle(const PillarBlock::Hash &pillar_block_hash, + const std::shared_ptr &peer) { dev::RLPStream s(1); s << pillar_block_hash; sealAndSend(peer->getId(), SubprotocolPacketType::GetBlsSigsBundlePacket, std::move(s)); - LOG(log_dg_) << "Requested BLS signatures bundle for pillar block " << pillar_block_hash << " from peer " << peer->getId(); + LOG(log_dg_) << "Requested BLS signatures bundle for pillar block " << pillar_block_hash << " from peer " + << peer->getId(); } } // namespace taraxa::network::tarcap From 093286336f51fccc658cbb708735e6178cd1a42d Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Thu, 28 Sep 2023 15:34:09 -0700 Subject: [PATCH 07/20] implement address -> bls public key mapping --- .../include/final_chain/final_chain.hpp | 9 ++++ .../include/final_chain/state_api.hpp | 2 + .../include/key_manager/key_manager.hpp | 13 +++-- .../include/pillar_chain/bls_signature.hpp | 30 +++++++---- .../include/pillar_chain/pillar_block.hpp | 10 +++- .../pillar_chain/pillar_chain_manager.hpp | 12 ++++- .../consensus/src/dag/dag_block_proposer.cpp | 2 +- .../consensus/src/dag/dag_manager.cpp | 4 +- .../consensus/src/final_chain/final_chain.cpp | 4 ++ .../consensus/src/final_chain/state_api.cpp | 16 ++++++ .../consensus/src/key_manager/key_manager.cpp | 33 ++++++++++-- .../src/pillar_chain/bls_signature.cpp | 30 ++++++----- .../src/pillar_chain/pillar_block.cpp | 12 +++-- .../src/pillar_chain/pillar_chain_manager.cpp | 52 ++++++++++++++++--- .../src/vote_manager/vote_manager.cpp | 2 +- .../common/ext_bls_sig_packet_handler.hpp | 18 ++++++- .../common/ext_bls_sig_packet_handler.cpp | 33 ++++++++++-- submodules/taraxa-evm | 2 +- 18 files changed, 232 insertions(+), 52 deletions(-) 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 70e95043cd..34c7e354dd 100644 --- a/libraries/core_libs/consensus/include/final_chain/final_chain.hpp +++ b/libraries/core_libs/consensus/include/final_chain/final_chain.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "common/event.hpp" #include "common/range_view.hpp" @@ -217,6 +218,14 @@ class FinalChain { */ virtual vrf_wrapper::vrf_pk_t dpos_get_vrf_key(EthBlockNumber blk_n, const addr_t& addr) const = 0; + /** + * @brief Get the bls key object from DPOS state + * @param addr account address + * @param blk_n number of block we are getting state from + * @return libff::alt_bn128_G2 + */ + virtual libff::alt_bn128_G2 dpos_get_bls_key(EthBlockNumber blk_n, const addr_t& addr) const = 0; + /** * @brief Prune state db for all blocks older than blk_n * @param blk_n number of block we are getting state from diff --git a/libraries/core_libs/consensus/include/final_chain/state_api.hpp b/libraries/core_libs/consensus/include/final_chain/state_api.hpp index 17a4d148cb..55df0511ed 100644 --- a/libraries/core_libs/consensus/include/final_chain/state_api.hpp +++ b/libraries/core_libs/consensus/include/final_chain/state_api.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "common/range_view.hpp" #include "final_chain/state_api_data.hpp" @@ -59,6 +60,7 @@ class StateAPI { u256 get_staking_balance(EthBlockNumber blk_num, const addr_t& addr) const; vrf_wrapper::vrf_pk_t dpos_get_vrf_key(EthBlockNumber blk_num, const addr_t& addr) const; std::vector dpos_validators_total_stakes(EthBlockNumber blk_num) const; + libff::alt_bn128_G2 dpos_get_bls_key(EthBlockNumber blk_num, const addr_t& addr) const; }; /** @} */ diff --git a/libraries/core_libs/consensus/include/key_manager/key_manager.hpp b/libraries/core_libs/consensus/include/key_manager/key_manager.hpp index ea70c529fc..1e093b70f9 100644 --- a/libraries/core_libs/consensus/include/key_manager/key_manager.hpp +++ b/libraries/core_libs/consensus/include/key_manager/key_manager.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -7,6 +8,7 @@ #include "final_chain/final_chain.hpp" namespace taraxa { + class KeyManager { public: KeyManager(std::shared_ptr final_chain); @@ -15,12 +17,17 @@ class KeyManager { KeyManager &operator=(const KeyManager &) = delete; KeyManager &operator=(KeyManager &&) = delete; - std::shared_ptr get(EthBlockNumber blk_n, const addr_t &addr); + std::shared_ptr getVrfKey(EthBlockNumber blk_n, const addr_t &addr); + std::shared_ptr getBlsKey(EthBlockNumber blk_n, const addr_t &addr); private: - std::shared_mutex mutex_; - std::unordered_map> key_map_; + std::shared_mutex vrf_keys_mutex_; + std::unordered_map> vrf_keys_; + + std::shared_mutex bls_keys_mutex_; + std::unordered_map> bls_keys_; std::shared_ptr final_chain_; }; + } // namespace taraxa \ No newline at end of file diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp index 68909fc191..879c58343e 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -19,20 +19,19 @@ namespace taraxa { */ class BlsSignature { public: - using Signature = libff::alt_bn128_G1; using Hash = uint256_hash_t; public: BlsSignature(const dev::RLP& rlp); - BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, - const libff::alt_bn128_Fr& secret); + BlsSignature(PillarBlock::Hash pillar_block_hash, PbftPeriod period, const addr_t& validator, const libff::alt_bn128_Fr& secret); /** * @brief Validates BLS signature * - * @return true if valid, otherwise false + * @param bls_puk_key + * @return */ - bool isValid() const; + bool isValid(const std::shared_ptr& bls_pub_key) const; /** * @return bls signature rlp @@ -44,14 +43,27 @@ class BlsSignature { */ Hash getHash() const; + /** + * @return pillar block hash + */ PillarBlock::Hash getPillarBlockHash() const; + /** + * @return signature pbft period + */ + PbftPeriod getPeriod() const; + + /** + * @return bls signature author address + */ + addr_t getSignerAddr() const; + private: PillarBlock::Hash pillar_block_hash_{0}; - - Signature signature_; - // TODO: seems like pub key is needed for verification of sig ??? - libff::alt_bn128_G2 public_key_; + // Pbft period of pillar block & period during which ws=as the signature created + PbftPeriod period_; + addr_t signer_addr_; + libff::alt_bn128_G1 signature_; mutable std::optional cached_hash_; }; 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 c28fb15231..32c3b3b73f 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -19,13 +19,18 @@ class PillarBlock { public: // TODO: use real merkle root - PillarBlock(blk_hash_t epoch_blocks_merkle_root, blk_hash_t previous_pillar_block_hash); + PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, blk_hash_t previous_pillar_block_hash); /** * @return pillar block hash */ Hash getHash() const; + /** + * @return pillar block pbft period + */ + PbftPeriod getPeriod() const; + private: /** * @return pillar block rlp @@ -33,6 +38,9 @@ class PillarBlock { dev::bytes getRlp() const; private: + // Pillar block pbft period + PbftPeriod period_; + // TODO: replace with actual merkle root blk_hash_t epoch_blocks_merkle_root_{0}; diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index c2cf9b5ead..9b687b9583 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -12,6 +12,11 @@ namespace taraxa { class DbStorage; class Network; class BlsSignature; +class KeyManager; + +namespace final_chain { +class FinalChain; +} /** @addtogroup PILLAR_CHAIN * @{ @@ -22,7 +27,8 @@ class BlsSignature; */ class PillarChainManager { public: - PillarChainManager(std::shared_ptr db, addr_t node_addr); + PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, + std::shared_ptr key_manager, addr_t node_addr); /** * @Process new final block @@ -62,6 +68,10 @@ class PillarChainManager { private: std::shared_ptr db_; std::weak_ptr network_; + std::shared_ptr final_chain_; + std::shared_ptr key_manager_; + + const addr_t node_addr_; // TODO: from wallet-config file std::pair bls_keys_; diff --git a/libraries/core_libs/consensus/src/dag/dag_block_proposer.cpp b/libraries/core_libs/consensus/src/dag/dag_block_proposer.cpp index 44d6d4f0a1..cad7733b8c 100644 --- a/libraries/core_libs/consensus/src/dag/dag_block_proposer.cpp +++ b/libraries/core_libs/consensus/src/dag/dag_block_proposer.cpp @@ -66,7 +66,7 @@ bool DagBlockProposer::proposeDagBlock() { return false; } - auto pk = key_manager_->get(*proposal_period, node_addr_); + auto pk = key_manager_->getVrfKey(*proposal_period, node_addr_); if (pk && *pk != vrf_pk_) { LOG(log_er_) << "VRF public key mismatch " << *pk << " - " << vrf_pk_; return false; diff --git a/libraries/core_libs/consensus/src/dag/dag_manager.cpp b/libraries/core_libs/consensus/src/dag/dag_manager.cpp index d9e4229ff1..f46e3de989 100644 --- a/libraries/core_libs/consensus/src/dag/dag_manager.cpp +++ b/libraries/core_libs/consensus/src/dag/dag_manager.cpp @@ -496,7 +496,7 @@ void DagManager::recoverDag() { break; } - const auto pk = key_manager_->get(*propose_period, blk.getSender()); + const auto pk = key_manager_->getVrfKey(*propose_period, blk.getSender()); if (!pk) { LOG(log_er_) << "DAG block " << blk.getHash() << " with " << blk.getLevel() << " level is missing VRF key for sender " << blk.getSender(); @@ -628,7 +628,7 @@ DagManager::VerifyBlockReturnType DagManager::verifyBlock(const DagBlock &blk) { } // Verify VDF solution - const auto pk = key_manager_->get(*propose_period, blk.getSender()); + const auto pk = key_manager_->getVrfKey(*propose_period, blk.getSender()); if (!pk) { LOG(log_er_) << "DAG block " << blk.getHash() << " with " << blk.getLevel() << " level is missing VRF key for sender " << blk.getSender(); 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 c39ef5a6fb..0f0e6757b3 100644 --- a/libraries/core_libs/consensus/src/final_chain/final_chain.cpp +++ b/libraries/core_libs/consensus/src/final_chain/final_chain.cpp @@ -453,6 +453,10 @@ class FinalChainImpl final : public FinalChain { finalized_cv_.wait_for(lck, std::chrono::milliseconds(10)); } + libff::alt_bn128_G2 dpos_get_bls_key(EthBlockNumber blk_n, const addr_t& addr) const override { + return state_api_.dpos_get_bls_key(blk_n, addr); + } + 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/final_chain/state_api.cpp b/libraries/core_libs/consensus/src/final_chain/state_api.cpp index d9d68d2048..0f93f62afa 100644 --- a/libraries/core_libs/consensus/src/final_chain/state_api.cpp +++ b/libraries/core_libs/consensus/src/final_chain/state_api.cpp @@ -258,4 +258,20 @@ std::vector StateAPI::dpos_validators_total_stakes(EthBlockNumbe return ret; } +libff::alt_bn128_G2 StateAPI::dpos_get_bls_key(EthBlockNumber blk_num, const addr_t& addr) const { + + dev::bytes sig_bytes = c_method_args_rlp(this_c_, blk_num, addr); + + // TODO: will this work ??? + std::stringstream sig_ss; + for (auto it = sig_bytes.begin(); it != sig_bytes.end(); it++) { + sig_ss << *it; + } + + libff::alt_bn128_G2 signature; + sig_ss >> signature; + + return signature; +} + } // namespace taraxa::state_api diff --git a/libraries/core_libs/consensus/src/key_manager/key_manager.cpp b/libraries/core_libs/consensus/src/key_manager/key_manager.cpp index 220707fc2f..c240fbd492 100644 --- a/libraries/core_libs/consensus/src/key_manager/key_manager.cpp +++ b/libraries/core_libs/consensus/src/key_manager/key_manager.cpp @@ -3,21 +3,22 @@ namespace taraxa { static const vrf_wrapper::vrf_pk_t kEmptyVrfKey; +static const libff::alt_bn128_G2 kEmptyBlsKey; KeyManager::KeyManager(std::shared_ptr final_chain) : final_chain_(std::move(final_chain)) {} -std::shared_ptr KeyManager::get(EthBlockNumber blk_n, const addr_t& addr) { +std::shared_ptr KeyManager::getVrfKey(EthBlockNumber blk_n, const addr_t& addr) { { - std::shared_lock lock(mutex_); - if (const auto it = key_map_.find(addr); it != key_map_.end()) { + std::shared_lock lock(vrf_keys_mutex_); + if (const auto it = vrf_keys_.find(addr); it != vrf_keys_.end()) { return it->second; } } try { if (auto key = final_chain_->dpos_get_vrf_key(blk_n, addr); key != kEmptyVrfKey) { - std::unique_lock lock(mutex_); - return key_map_.insert_or_assign(addr, std::make_shared(std::move(key))).first->second; + std::unique_lock lock(vrf_keys_mutex_); + return vrf_keys_.insert_or_assign(addr, std::make_shared(std::move(key))).first->second; } } catch (state_api::ErrFutureBlock&) { return nullptr; @@ -25,4 +26,26 @@ std::shared_ptr KeyManager::get(EthBlockNumber blk_n, con return nullptr; } + +std::shared_ptr KeyManager::getBlsKey(EthBlockNumber blk_n, const addr_t& addr) { + { + std::shared_lock lock(bls_keys_mutex_); + if (const auto it = bls_keys_.find(addr); it != bls_keys_.end()) { + return it->second; + } + } + + try { + // TODO: does kEmptyBlsKey comparison work ??? + if (auto key = final_chain_->dpos_get_bls_key(blk_n, addr); key != kEmptyBlsKey) { + std::unique_lock lock(bls_keys_mutex_); + return bls_keys_.insert_or_assign(addr, std::make_shared(std::move(key))).first->second; + } + } catch (state_api::ErrFutureBlock&) { + return nullptr; + } + + return nullptr; +} + } // namespace taraxa \ No newline at end of file diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp index d1064cbfb7..c280ad6812 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -7,35 +7,41 @@ namespace taraxa { BlsSignature::BlsSignature(const dev::RLP& rlp) { - std::string sig_str, pk_str; - util::rlp_tuple(util::RLPDecoderRef(rlp, true), pillar_block_hash_, sig_str, pk_str); + std::string sig_str; + util::rlp_tuple(util::RLPDecoderRef(rlp, true), pillar_block_hash_, period_,signer_addr_, sig_str); std::stringstream(sig_str) >> signature_; - std::stringstream(pk_str) >> public_key_; } -BlsSignature::BlsSignature(PillarBlock::Hash pillar_block_hash, const libff::alt_bn128_G2& public_key, +BlsSignature::BlsSignature(PillarBlock::Hash pillar_block_hash, PbftPeriod period, const addr_t& validator, const libff::alt_bn128_Fr& secret) : pillar_block_hash_(pillar_block_hash), - signature_(libBLS::Bls::CoreSignAggregated(getHash().toString(), secret)), - public_key_(public_key) {} + period_(period), + signer_addr_(validator), + signature_(libBLS::Bls::CoreSignAggregated(getHash().toString(), secret)) {} -bool BlsSignature::isValid() const { return libBLS::Bls::CoreVerify(public_key_, getHash().toString(), signature_); } +bool BlsSignature::isValid(const std::shared_ptr& bls_pub_key) const { + return libBLS::Bls::CoreVerify(*bls_pub_key, getHash().toString(), signature_); +} blk_hash_t BlsSignature::getPillarBlockHash() const { return pillar_block_hash_; } +PbftPeriod BlsSignature::getPeriod() const { + return period_; +} + +addr_t BlsSignature::getSignerAddr() const { return signer_addr_; } + dev::bytes BlsSignature::getRlp() const { - dev::RLPStream s(3); + dev::RLPStream s(4); s << pillar_block_hash_; + s << period_; + s << signer_addr_; std::stringstream sig_ss; sig_ss << signature_; s << sig_ss.str(); - std::stringstream pk_ss; - pk_ss << public_key_; - s << pk_ss.str(); - return s.invalidate(); } 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 8b90267580..8d391057a3 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -6,19 +6,25 @@ namespace taraxa { -PillarBlock::PillarBlock(blk_hash_t epoch_blocks_merkle_root, PillarBlock::Hash previous_pillar_block_hash) - : epoch_blocks_merkle_root_(epoch_blocks_merkle_root), +PillarBlock::PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, PillarBlock::Hash previous_pillar_block_hash) + : period_(period), + epoch_blocks_merkle_root_(epoch_blocks_merkle_root), previous_pillar_block_hash_(previous_pillar_block_hash), kCachedHash(dev::sha3(getRlp())) {} dev::bytes PillarBlock::getRlp() const { - dev::RLPStream s(2); + dev::RLPStream s(3); + s << period_; s << epoch_blocks_merkle_root_; s << previous_pillar_block_hash_; return s.invalidate(); } +PbftPeriod PillarBlock::getPeriod() const { + return period_; +} + PillarBlock::Hash PillarBlock::getHash() const { return kCachedHash; } } // namespace taraxa 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 1ae72c7ec7..e95cea1f1f 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 @@ -1,5 +1,6 @@ #include "pillar_chain/pillar_chain_manager.hpp" - +#include "final_chain/final_chain.hpp" +#include "key_manager/key_manager.hpp" #include "network/network.hpp" // TODO: should ne #include @@ -7,9 +8,13 @@ namespace taraxa { -PillarChainManager::PillarChainManager(std::shared_ptr db, addr_t node_addr) +PillarChainManager::PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, + std::shared_ptr key_manager, addr_t node_addr) : db_(std::move(db)), network_{}, + final_chain_{std::move(final_chain)}, + key_manager_(std::move(key_manager)), + node_addr_(node_addr), // TODO: from wallet-config bls_keys_(libBLS::Bls::KeyGeneration()), // TODO: last_pillar_block_ might be optional ??? @@ -27,24 +32,43 @@ void PillarChainManager::newFinalBlock(const final_chain::FinalizationResult& bl // Create pillar block and broadcast BLS signature if (block_data.final_chain_blk->number % kEpochBlocksNum == 0) { - const auto pillar_block = std::make_shared(epoch_blocks_merkle_root, last_pillar_block_->getHash()); + const auto pillar_block = std::make_shared(block_data.final_chain_blk->number, epoch_blocks_merkle_root, last_pillar_block_->getHash()); // TODO: should we save it into db ??? Theoretically pillar blocks can be made from saved final blocks ... std::scoped_lock lock(mutex_); last_pillar_block_ = pillar_block; } else if (block_data.final_chain_blk->number % (kEpochBlocksNum + kBlsSigBroadcastDelayBlocks) == 0) { + // Check if node is eligible validator + try { + if (!final_chain_->dpos_is_eligible(block_data.final_chain_blk->number, node_addr_)) { + return; + } + } catch (state_api::ErrFutureBlock& e) { + assert(false); // This should never happen as newFinalBlock is triggered after the new block is finalized + return; + } + + if (!key_manager_->getBlsKey(block_data.final_chain_blk->number, node_addr_)) { + LOG(log_er_) << "No bls public key registered in dpos contract !"; + return; + } + // Create and broadcast bls signature with kBlsSigBroadcastDelayBlocks delay to make sure other up-to-date nodes // already processed the latest pillar block + // TODO: maybe dont use the delay and accept signatures with right period ??? std::shared_ptr signature; { std::shared_lock lock(mutex_); - signature = std::make_shared(last_pillar_block_->getHash(), bls_keys_.second, bls_keys_.first); + signature = std::make_shared(last_pillar_block_->getHash(), block_data.final_chain_blk->number, node_addr_, bls_keys_.first); } + addVerifiedBlsSig(signature); + if (auto net = network_.lock()) { net->gossipBlsSignature(signature); } + // TODO: fix bls sigs requesting - do it every N blocks after pillar block was created } else if (block_data.final_chain_blk->number % kCheckLatestBlockBlsSigs == 0) { PillarBlock::Hash last_pillar_block_hash; { @@ -74,15 +98,27 @@ bool PillarChainManager::isRelevantBlsSig(const std::shared_ptr si } bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& signature) { + uint64_t signer_vote_count = 0; + try { + signer_vote_count = final_chain_->dpos_eligible_vote_count(signature->getPeriod(), signature->getSignerAddr()); + } catch (state_api::ErrFutureBlock& e) { + LOG(log_er_) << "Signature " << signature->getHash() << " period " << signature->getPeriod() << " is too far ahead of DPOS. " << e.what(); + return false; + } + + if (!signer_vote_count) { + LOG(log_er_) << "Signature " << signature->getHash() << " author " << signature->getSignerAddr() << " stake is zero"; + return false; + } + std::scoped_lock lock(mutex_); if (last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second) { - // TODO: adjust also last_pillar_block_signatures_weight_ - - return true; + last_pillar_block_signatures_weight_ += signer_vote_count; + // TODO: check if we have 2t+1 signatures ??? } - return false; + return true; } std::vector> PillarChainManager::getVerifiedBlsSigs( 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 c3c991c625..1c2694abc5 100644 --- a/libraries/core_libs/consensus/src/vote_manager/vote_manager.cpp +++ b/libraries/core_libs/consensus/src/vote_manager/vote_manager.cpp @@ -890,7 +890,7 @@ std::pair VoteManager::validateVote(const std::shared_ptrget(vote_period - 1, vote->getVoterAddr()); + const auto pk = key_manager_->getVrfKey(vote_period - 1, vote->getVoterAddr()); if (!pk) { err_msg << "No vrf key mapped for vote author " << vote->getVoterAddr(); return {false, err_msg.str()}; diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp index 0e7fe1c10e..e3c7074e48 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp @@ -1,7 +1,17 @@ #pragma once #include "packet_handler.hpp" -#include "pillar_chain/pillar_chain_manager.hpp" + +namespace taraxa { +class KeyManager; +class BlsSignature; +class PillarChainManager; + +namespace final_chain { +class FinalChain; +} + +} namespace taraxa::network::tarcap { @@ -9,7 +19,9 @@ class ExtBlsSigPacketHandler : public PacketHandler { public: ExtBlsSigPacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, - std::shared_ptr pillar_chain_manager, const addr_t& node_addr, + std::shared_ptr pillar_chain_manager, + std::shared_ptr key_manager, + std::shared_ptr final_chain, const addr_t& node_addr, const std::string& logs_prefix); protected: @@ -17,6 +29,8 @@ class ExtBlsSigPacketHandler : public PacketHandler { protected: std::shared_ptr pillar_chain_manager_; + std::shared_ptr key_manager_; + std::shared_ptr final_chain_; }; } // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp index 4433395ca3..51a1afcc31 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp @@ -1,23 +1,50 @@ #include "network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp" - +#include "key_manager/key_manager.hpp" #include "pillar_chain/pillar_chain_manager.hpp" +#include "final_chain/final_chain.hpp" namespace taraxa::network::tarcap { ExtBlsSigPacketHandler::ExtBlsSigPacketHandler(const FullNodeConfig &conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, std::shared_ptr pillar_chain_manager, + std::shared_ptr key_manager, std::shared_ptr final_chain, const addr_t &node_addr, const std::string &logs_prefix) : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "BLS_SIG_PH"), - pillar_chain_manager_{std::move(pillar_chain_manager)} {} + pillar_chain_manager_{std::move(pillar_chain_manager)}, + key_manager_(std::move(key_manager)), + final_chain_(std::move(final_chain)){} void ExtBlsSigPacketHandler::processBlsSignature(const std::shared_ptr &signature, const std::shared_ptr &peer) { if (!pillar_chain_manager_->isRelevantBlsSig(signature)) { LOG(log_dg_) << "Drop irrelevant signature " << signature->getHash() << " from peer " << peer->getId(); + return; + } + + const auto sig_period = signature->getPeriod(); + const auto sig_author = signature->getSignerAddr(); + + // Check if signer registered his bls key + const auto bls_pub_key = key_manager_->getBlsKey(sig_period, sig_author); + if (!bls_pub_key) { + LOG(log_er_) << "No bls public key mapped for node " << sig_author << ". Signature " << signature->getHash(); + return; + } + + // Check if signer is eligible validator + try { + if (!final_chain_->dpos_is_eligible(sig_period, sig_author)) { + std::ostringstream err_msg; + err_msg << "Invalid signature " << signature->getHash() << " from peer " << peer->getId() << ". Signer is not eligible validator"; + throw MaliciousPeerException(err_msg.str()); + } + } catch (state_api::ErrFutureBlock& e) { + LOG(log_wr_) << "Signature " << signature->getHash() << " period " << sig_period << " is too far ahead of DPOS. " << e.what(); + return; } - if (!signature->isValid()) { + if (!signature->isValid(bls_pub_key)) { std::ostringstream err_msg; err_msg << "Invalid signature " << signature->getHash() << " from peer " << peer->getId(); throw MaliciousPeerException(err_msg.str()); diff --git a/submodules/taraxa-evm b/submodules/taraxa-evm index c067e03759..9015933370 160000 --- a/submodules/taraxa-evm +++ b/submodules/taraxa-evm @@ -1 +1 @@ -Subproject commit c067e03759ca18fbe98c75d5857cfcd840d46e6a +Subproject commit 901593337053f820cef8d1c747adbeae64536fef From a1a7c19357110cc4830494ab82af2dfbac60363d Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Fri, 29 Sep 2023 15:18:01 -0700 Subject: [PATCH 08/20] integrate dpos validator -> bls pub key mapping into C++ part --- .../include/pillar_chain/bls_signature.hpp | 10 +- .../pillar_chain/pillar_chain_manager.hpp | 19 ++- .../consensus/src/final_chain/state_api.cpp | 4 +- .../src/pillar_chain/bls_signature.cpp | 8 +- .../src/pillar_chain/pillar_block.cpp | 7 +- .../src/pillar_chain/pillar_chain_manager.cpp | 138 +++++++++++++++--- .../network/include/network/network.hpp | 2 +- .../common/ext_bls_sig_packet_handler.hpp | 8 +- .../v1/init_packets_handlers.hpp | 13 +- .../network/tarcap/taraxa_capability.hpp | 1 + libraries/core_libs/network/src/network.cpp | 8 +- .../common/ext_bls_sig_packet_handler.cpp | 32 +--- .../get_bls_sigs_bundle_packet_handler.cpp | 2 +- .../network/src/tarcap/taraxa_capability.cpp | 28 ++-- libraries/core_libs/node/src/node.cpp | 8 +- 15 files changed, 192 insertions(+), 96 deletions(-) diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp index 879c58343e..d66ea6ee62 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -23,7 +23,8 @@ class BlsSignature { public: BlsSignature(const dev::RLP& rlp); - BlsSignature(PillarBlock::Hash pillar_block_hash, PbftPeriod period, const addr_t& validator, const libff::alt_bn128_Fr& secret); + BlsSignature(PillarBlock::Hash pillar_block_hash, PbftPeriod period, const addr_t& validator, + const libff::alt_bn128_Fr& secret); /** * @brief Validates BLS signature @@ -58,9 +59,14 @@ class BlsSignature { */ addr_t getSignerAddr() const; + /** + * @return actual bls signature + */ + libff::alt_bn128_G1 getSignature() const; + private: PillarBlock::Hash pillar_block_hash_{0}; - // Pbft period of pillar block & period during which ws=as the signature created + // Pbft period of pillar block & period during which was the signature created PbftPeriod period_; addr_t signer_addr_; libff::alt_bn128_G1 signature_; diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index 9b687b9583..6ea8a09702 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -13,6 +13,7 @@ class DbStorage; class Network; class BlsSignature; class KeyManager; +class VoteManager; namespace final_chain { class FinalChain; @@ -28,14 +29,14 @@ class FinalChain; class PillarChainManager { public: PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, - std::shared_ptr key_manager, addr_t node_addr); + std::shared_ptr vote_mgr, std::shared_ptr key_manager, addr_t node_addr); /** * @Process new final block * * @param block_data */ - void newFinalBlock(const final_chain::FinalizationResult& block_data); + void newFinalBlock(const std::shared_ptr& block_data); /** * @brief Set network as a weak pointer @@ -51,6 +52,14 @@ class PillarChainManager { */ bool isRelevantBlsSig(const std::shared_ptr signature) const; + /** + * @brief Validates bls signature + * + * @param signature + * @return true if valid, otherwise false + */ + bool validateBlsSignature(const std::shared_ptr signature) const; + /** * @brief Add a signature to the bls signatures map * @param signature signature @@ -63,12 +72,13 @@ class PillarChainManager { * @brief Get all bls signatures for specified pillar block * @return all bls signatures */ - std::vector> getVerifiedBlsSigs(const PillarBlock::Hash pillar_block_hash) const; + std::vector> getVerifiedBlsSignatures(const PillarBlock::Hash pillar_block_hash) const; private: std::shared_ptr db_; std::weak_ptr network_; std::shared_ptr final_chain_; + std::shared_ptr vote_mgr_; std::shared_ptr key_manager_; const addr_t node_addr_; @@ -80,6 +90,9 @@ class PillarChainManager { // TODO: might be just atomic hash std::shared_ptr last_pillar_block_; + // 2t+1 threshold for last pillar block period + uint64_t last_pillar_block_two_t_plus_one_; + // Last processed pillar block signatures std::unordered_map> last_pillar_block_signatures_; diff --git a/libraries/core_libs/consensus/src/final_chain/state_api.cpp b/libraries/core_libs/consensus/src/final_chain/state_api.cpp index 0f93f62afa..cd829d66c6 100644 --- a/libraries/core_libs/consensus/src/final_chain/state_api.cpp +++ b/libraries/core_libs/consensus/src/final_chain/state_api.cpp @@ -259,8 +259,8 @@ std::vector StateAPI::dpos_validators_total_stakes(EthBlockNumbe } libff::alt_bn128_G2 StateAPI::dpos_get_bls_key(EthBlockNumber blk_num, const addr_t& addr) const { - - dev::bytes sig_bytes = c_method_args_rlp(this_c_, blk_num, addr); + dev::bytes sig_bytes = + c_method_args_rlp(this_c_, blk_num, addr); // TODO: will this work ??? std::stringstream sig_ss; diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp index c280ad6812..4402ebbd8f 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -8,7 +8,7 @@ namespace taraxa { BlsSignature::BlsSignature(const dev::RLP& rlp) { std::string sig_str; - util::rlp_tuple(util::RLPDecoderRef(rlp, true), pillar_block_hash_, period_,signer_addr_, sig_str); + util::rlp_tuple(util::RLPDecoderRef(rlp, true), pillar_block_hash_, period_, signer_addr_, sig_str); std::stringstream(sig_str) >> signature_; } @@ -26,12 +26,12 @@ bool BlsSignature::isValid(const std::shared_ptr& bls_pub_k blk_hash_t BlsSignature::getPillarBlockHash() const { return pillar_block_hash_; } -PbftPeriod BlsSignature::getPeriod() const { - return period_; -} +PbftPeriod BlsSignature::getPeriod() const { return period_; } addr_t BlsSignature::getSignerAddr() const { return signer_addr_; } +libff::alt_bn128_G1 BlsSignature::getSignature() const { return signature_; } + dev::bytes BlsSignature::getRlp() const { dev::RLPStream s(4); s << pillar_block_hash_; 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 8d391057a3..0a9cb5de84 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -6,7 +6,8 @@ namespace taraxa { -PillarBlock::PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, PillarBlock::Hash previous_pillar_block_hash) +PillarBlock::PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, + PillarBlock::Hash previous_pillar_block_hash) : period_(period), epoch_blocks_merkle_root_(epoch_blocks_merkle_root), previous_pillar_block_hash_(previous_pillar_block_hash), @@ -21,9 +22,7 @@ dev::bytes PillarBlock::getRlp() const { return s.invalidate(); } -PbftPeriod PillarBlock::getPeriod() const { - return period_; -} +PbftPeriod PillarBlock::getPeriod() const { return period_; } PillarBlock::Hash PillarBlock::getHash() const { return kCachedHash; } 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 e95cea1f1f..fb230f2654 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 @@ -1,24 +1,29 @@ #include "pillar_chain/pillar_chain_manager.hpp" + #include "final_chain/final_chain.hpp" #include "key_manager/key_manager.hpp" #include "network/network.hpp" +#include "vote_manager/vote_manager.hpp" // TODO: should ne #include #include namespace taraxa { -PillarChainManager::PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, - std::shared_ptr key_manager, addr_t node_addr) +PillarChainManager::PillarChainManager(std::shared_ptr db, + std::shared_ptr final_chain, + std::shared_ptr vote_mgr, std::shared_ptr key_manager, + addr_t node_addr) : db_(std::move(db)), network_{}, final_chain_{std::move(final_chain)}, + vote_mgr_(std::move(vote_mgr)), key_manager_(std::move(key_manager)), node_addr_(node_addr), // TODO: from wallet-config bls_keys_(libBLS::Bls::KeyGeneration()), // TODO: last_pillar_block_ might be optional ??? - last_pillar_block_{std::make_shared(blk_hash_t{0}, blk_hash_t{0})}, + last_pillar_block_{std::make_shared(0, blk_hash_t{0}, blk_hash_t{0})}, last_pillar_block_signatures_{}, mutex_{} { libBLS::ThresholdUtils::initCurve(); @@ -26,29 +31,48 @@ PillarChainManager::PillarChainManager(std::shared_ptr db, std::share LOG_OBJECTS_CREATE("PILLAR_CHAIN"); } -void PillarChainManager::newFinalBlock(const final_chain::FinalizationResult& block_data) { +void PillarChainManager::newFinalBlock(const std::shared_ptr& block_data) { // TODO: add each final block to final blocks merkle tree - const auto epoch_blocks_merkle_root = block_data.final_chain_blk->hash; + const auto epoch_blocks_merkle_root = block_data->final_chain_blk->hash; // Create pillar block and broadcast BLS signature - if (block_data.final_chain_blk->number % kEpochBlocksNum == 0) { - const auto pillar_block = std::make_shared(block_data.final_chain_blk->number, epoch_blocks_merkle_root, last_pillar_block_->getHash()); + if (block_data->final_chain_blk->number % kEpochBlocksNum == 0) { + const auto pillar_block = std::make_shared(block_data->final_chain_blk->number, + epoch_blocks_merkle_root, last_pillar_block_->getHash()); + + // Get 2t+1 threshold + // Note: do not use signature->getPeriod() - 1 as in votes processing - signature are made after the block is + // finalized, not before as votes + const auto two_t_plus_one = vote_mgr_->getPbftTwoTPlusOne(pillar_block->getPeriod(), PbftVoteTypes::cert_vote); + // getPbftTwoTPlusOne returns empty optional only when requested period is too far ahead and that should never + // happen as newFinalBlock is triggered only after the block is finalized + assert(two_t_plus_one.has_value()); - // TODO: should we save it into db ??? Theoretically pillar blocks can be made from saved final blocks ... std::scoped_lock lock(mutex_); last_pillar_block_ = pillar_block; - } else if (block_data.final_chain_blk->number % (kEpochBlocksNum + kBlsSigBroadcastDelayBlocks) == 0) { + last_pillar_block_signatures_.clear(); + last_pillar_block_signatures_weight_ = 0; + if (two_t_plus_one.has_value()) [[likely]] { + last_pillar_block_two_t_plus_one_ = *two_t_plus_one; + } + + return; + } + + // TODO: do not create & gossip own sig or request other signatures if the node is in syncing state + // Create and broadcast own bls signature + if (block_data->final_chain_blk->number % (kEpochBlocksNum + kBlsSigBroadcastDelayBlocks) == 0) { // Check if node is eligible validator try { - if (!final_chain_->dpos_is_eligible(block_data.final_chain_blk->number, node_addr_)) { + if (!final_chain_->dpos_is_eligible(block_data->final_chain_blk->number, node_addr_)) { return; } } catch (state_api::ErrFutureBlock& e) { - assert(false); // This should never happen as newFinalBlock is triggered after the new block is finalized + assert(false); // This should never happen as newFinalBlock is triggered after the new block is finalized return; } - if (!key_manager_->getBlsKey(block_data.final_chain_blk->number, node_addr_)) { + if (!key_manager_->getBlsKey(block_data->final_chain_blk->number, node_addr_)) { LOG(log_er_) << "No bls public key registered in dpos contract !"; return; } @@ -59,7 +83,8 @@ void PillarChainManager::newFinalBlock(const final_chain::FinalizationResult& bl std::shared_ptr signature; { std::shared_lock lock(mutex_); - signature = std::make_shared(last_pillar_block_->getHash(), block_data.final_chain_blk->number, node_addr_, bls_keys_.first); + signature = std::make_shared(last_pillar_block_->getHash(), block_data->final_chain_blk->number, + node_addr_, bls_keys_.first); } addVerifiedBlsSig(signature); @@ -68,8 +93,12 @@ void PillarChainManager::newFinalBlock(const final_chain::FinalizationResult& bl net->gossipBlsSignature(signature); } - // TODO: fix bls sigs requesting - do it every N blocks after pillar block was created - } else if (block_data.final_chain_blk->number % kCheckLatestBlockBlsSigs == 0) { + return; + } + + // Check (& request) 2t+1 signatures + // TODO: fix bls sigs requesting - do it every N blocks after pillar block was created + if (block_data->final_chain_blk->number % kCheckLatestBlockBlsSigs == 0) { PillarBlock::Hash last_pillar_block_hash; { std::shared_lock lock(mutex_); @@ -97,31 +126,96 @@ bool PillarChainManager::isRelevantBlsSig(const std::shared_ptr si return true; } +bool PillarChainManager::validateBlsSignature(const std::shared_ptr signature) const { + const auto sig_period = signature->getPeriod(); + const auto sig_author = signature->getSignerAddr(); + + // Check if signer registered his bls key + const auto bls_pub_key = key_manager_->getBlsKey(sig_period, sig_author); + if (!bls_pub_key) { + LOG(log_er_) << "No bls public key mapped for node " << sig_author << ". Signature " << signature->getHash(); + return false; + } + + // Check if signer is eligible validator + try { + if (!final_chain_->dpos_is_eligible(sig_period, sig_author)) { + LOG(log_er_) << "Signer is not eligible validator. Signature " << signature->getHash(); + return false; + } + } catch (state_api::ErrFutureBlock& e) { + LOG(log_wr_) << "Period " << sig_period << " is too far ahead of DPOS. Signature " << signature->getHash() + << ". Err: " << e.what(); + return false; + } + + if (!signature->isValid(bls_pub_key)) { + LOG(log_er_) << "Invalid signature " << signature->getHash(); + return false; + } + + return true; +} + bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& signature) { uint64_t signer_vote_count = 0; try { signer_vote_count = final_chain_->dpos_eligible_vote_count(signature->getPeriod(), signature->getSignerAddr()); } catch (state_api::ErrFutureBlock& e) { - LOG(log_er_) << "Signature " << signature->getHash() << " period " << signature->getPeriod() << " is too far ahead of DPOS. " << e.what(); + LOG(log_er_) << "Signature " << signature->getHash() << " period " << signature->getPeriod() + << " is too far ahead of DPOS. " << e.what(); return false; } if (!signer_vote_count) { - LOG(log_er_) << "Signature " << signature->getHash() << " author " << signature->getSignerAddr() << " stake is zero"; + // Signer is not a valid validator + LOG(log_er_) << "Signature " << signature->getHash() << " author's " << signature->getSignerAddr() + << " stake is zero"; return false; } - std::scoped_lock lock(mutex_); + std::vector bls_signatures; + dev::RLPStream signers_addresses_rlp; + PillarBlock::Hash pillar_block_hash; + + { + std::scoped_lock lock(mutex_); + if (!last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second) { + // Signature is already saved + return true; + } - if (last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second) { - last_pillar_block_signatures_weight_ += signer_vote_count; - // TODO: check if we have 2t+1 signatures ??? + if ((last_pillar_block_signatures_weight_ += signer_vote_count) < last_pillar_block_two_t_plus_one_) { + // Signatures weight < 2t+1 + return true; + } + + pillar_block_hash = last_pillar_block_signatures_.begin()->second->getPillarBlockHash(); + + signers_addresses_rlp.appendList(last_pillar_block_signatures_.size()); + for (const auto& bls_sig : last_pillar_block_signatures_) { + signers_addresses_rlp << bls_sig.second->getSignerAddr(); + bls_signatures.push_back(bls_sig.second->getSignature()); + } } + // Create aggregated bls signature and save it to db + libff::alt_bn128_G1 aggregated_signature = libBLS::Bls::Aggregate(bls_signatures); + + std::stringstream aggregated_signature_ss; + aggregated_signature_ss << aggregated_signature; + + dev::RLPStream bls_aggregated_sig_rlp(3); + bls_aggregated_sig_rlp << pillar_block_hash; + bls_aggregated_sig_rlp << aggregated_signature_ss.str(); + bls_aggregated_sig_rlp.appendRaw(signers_addresses_rlp.invalidate()); + + // TODO: save bls_aggregated_sig_rlp to db + return true; } -std::vector> PillarChainManager::getVerifiedBlsSigs( +std::vector> PillarChainManager::getVerifiedBlsSignatures( const PillarBlock::Hash pillar_block_hash) const { std::shared_lock lock(mutex_); if (pillar_block_hash != last_pillar_block_->getHash()) { diff --git a/libraries/core_libs/network/include/network/network.hpp b/libraries/core_libs/network/include/network/network.hpp index f36b877165..a75f57baac 100644 --- a/libraries/core_libs/network/include/network/network.hpp +++ b/libraries/core_libs/network/include/network/network.hpp @@ -37,7 +37,7 @@ class Network { const dev::KeyPair &key, std::shared_ptr db, std::shared_ptr pbft_mgr, std::shared_ptr pbft_chain, std::shared_ptr vote_mgr, std::shared_ptr dag_mgr, std::shared_ptr trx_mgr, - std::shared_ptr slashing_manager); + std::shared_ptr slashing_manager, std::shared_ptr pillar_chain_mgr); ~Network(); Network(const Network &) = delete; diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp index e3c7074e48..97a3d3f3c4 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp @@ -11,7 +11,7 @@ namespace final_chain { class FinalChain; } -} +} // namespace taraxa namespace taraxa::network::tarcap { @@ -19,9 +19,7 @@ class ExtBlsSigPacketHandler : public PacketHandler { public: ExtBlsSigPacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, - std::shared_ptr pillar_chain_manager, - std::shared_ptr key_manager, - std::shared_ptr final_chain, const addr_t& node_addr, + std::shared_ptr pillar_chain_manager, const addr_t& node_addr, const std::string& logs_prefix); protected: @@ -29,8 +27,6 @@ class ExtBlsSigPacketHandler : public PacketHandler { protected: std::shared_ptr pillar_chain_manager_; - std::shared_ptr key_manager_; - std::shared_ptr final_chain_; }; } // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp index 5f5020ebdf..28b7c9e11d 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp @@ -1,17 +1,19 @@ #pragma once -#include "get_next_votes_bundle_packet_handler.hpp" -#include "get_pbft_sync_packet_handler.hpp" +#include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" +#include "network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_block_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_dag_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/status_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/transaction_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/vote_packet_handler.hpp" +#include "network/tarcap/packets_handlers/v1/get_next_votes_bundle_packet_handler.hpp" +#include "network/tarcap/packets_handlers/v1/get_pbft_sync_packet_handler.hpp" +#include "network/tarcap/packets_handlers/v1/pbft_sync_packet_handler.hpp" +#include "network/tarcap/packets_handlers/v1/votes_bundle_packet_handler.hpp" #include "network/tarcap/taraxa_capability.hpp" -#include "pbft_sync_packet_handler.hpp" #include "slashing_manager/slashing_manager.hpp" -#include "votes_bundle_packet_handler.hpp" namespace taraxa::network::tarcap::v1 { @@ -66,6 +68,9 @@ static const TaraxaCapability::InitPacketsHandlers kInitV1Handlers = packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, node_addr, logs_prefix); + packets_handlers->registerHandler(config, peers_state, packets_stats, + pillar_chain_mgr, node_addr, logs_prefix); + return packets_handlers; }; diff --git a/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp b/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp index 3f3a2761cf..0ea6bcf3f7 100644 --- a/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp +++ b/libraries/core_libs/network/include/network/tarcap/taraxa_capability.hpp @@ -63,6 +63,7 @@ class TaraxaCapability final : public dev::p2p::CapabilityFace { std::shared_ptr pbft_mgr, std::shared_ptr pbft_chain, std::shared_ptr vote_mgr, std::shared_ptr dag_mgr, std::shared_ptr trx_mgr, std::shared_ptr slashing_manager, + std::shared_ptr pillar_chain_mgr, InitPacketsHandlers init_packets_handlers = kInitLatestVersionHandlers); virtual ~TaraxaCapability() = default; diff --git a/libraries/core_libs/network/src/network.cpp b/libraries/core_libs/network/src/network.cpp index 59ca1ce481..afb5cd8f51 100644 --- a/libraries/core_libs/network/src/network.cpp +++ b/libraries/core_libs/network/src/network.cpp @@ -26,7 +26,8 @@ Network::Network(const FullNodeConfig &config, const h256 &genesis_hash, std::fi dev::KeyPair const &key, std::shared_ptr db, std::shared_ptr pbft_mgr, std::shared_ptr pbft_chain, std::shared_ptr vote_mgr, std::shared_ptr dag_mgr, std::shared_ptr trx_mgr, - std::shared_ptr slashing_manager) + std::shared_ptr slashing_manager, + std::shared_ptr pillar_chain_mgr) : kConf(config), pub_key_(key.pub()), all_packets_stats_(nullptr), @@ -79,13 +80,14 @@ Network::Network(const FullNodeConfig &config, const h256 &genesis_hash, std::fi // Register old version (V1) of taraxa capability auto v1_tarcap = std::make_shared( kV1NetworkVersion, config, genesis_hash, host, key, packets_tp_, all_packets_stats_, pbft_syncing_state_, db, - pbft_mgr, pbft_chain, vote_mgr, dag_mgr, trx_mgr, slashing_manager, network::tarcap::v1::kInitV1Handlers); + pbft_mgr, pbft_chain, vote_mgr, dag_mgr, trx_mgr, slashing_manager, pillar_chain_mgr, + network::tarcap::v1::kInitV1Handlers); capabilities.emplace_back(v1_tarcap); // Register latest version of taraxa capability auto latest_tarcap = std::make_shared( TARAXA_NET_VERSION, config, genesis_hash, host, key, packets_tp_, all_packets_stats_, pbft_syncing_state_, db, - pbft_mgr, pbft_chain, vote_mgr, dag_mgr, trx_mgr, slashing_manager); + pbft_mgr, pbft_chain, vote_mgr, dag_mgr, trx_mgr, slashing_manager, pillar_chain_mgr); capabilities.emplace_back(latest_tarcap); return capabilities; diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp index 51a1afcc31..dc683c7496 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp @@ -1,19 +1,17 @@ #include "network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp" + +#include "final_chain/final_chain.hpp" #include "key_manager/key_manager.hpp" #include "pillar_chain/pillar_chain_manager.hpp" -#include "final_chain/final_chain.hpp" namespace taraxa::network::tarcap { ExtBlsSigPacketHandler::ExtBlsSigPacketHandler(const FullNodeConfig &conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, std::shared_ptr pillar_chain_manager, - std::shared_ptr key_manager, std::shared_ptr final_chain, const addr_t &node_addr, const std::string &logs_prefix) : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "BLS_SIG_PH"), - pillar_chain_manager_{std::move(pillar_chain_manager)}, - key_manager_(std::move(key_manager)), - final_chain_(std::move(final_chain)){} + pillar_chain_manager_{std::move(pillar_chain_manager)} {} void ExtBlsSigPacketHandler::processBlsSignature(const std::shared_ptr &signature, const std::shared_ptr &peer) { @@ -22,29 +20,7 @@ void ExtBlsSigPacketHandler::processBlsSignature(const std::shared_ptrgetPeriod(); - const auto sig_author = signature->getSignerAddr(); - - // Check if signer registered his bls key - const auto bls_pub_key = key_manager_->getBlsKey(sig_period, sig_author); - if (!bls_pub_key) { - LOG(log_er_) << "No bls public key mapped for node " << sig_author << ". Signature " << signature->getHash(); - return; - } - - // Check if signer is eligible validator - try { - if (!final_chain_->dpos_is_eligible(sig_period, sig_author)) { - std::ostringstream err_msg; - err_msg << "Invalid signature " << signature->getHash() << " from peer " << peer->getId() << ". Signer is not eligible validator"; - throw MaliciousPeerException(err_msg.str()); - } - } catch (state_api::ErrFutureBlock& e) { - LOG(log_wr_) << "Signature " << signature->getHash() << " period " << sig_period << " is too far ahead of DPOS. " << e.what(); - return; - } - - if (!signature->isValid(bls_pub_key)) { + if (!pillar_chain_manager_->validateBlsSignature(signature)) { std::ostringstream err_msg; err_msg << "Invalid signature " << signature->getHash() << " from peer " << peer->getId(); throw MaliciousPeerException(err_msg.str()); diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp index 4ad817f68b..9f46c5f73e 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp @@ -23,7 +23,7 @@ void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet const std::shared_ptr &peer) { const PillarBlock::Hash pillar_block_hash = packet_data.rlp_.toHash(); - const auto signatures = pillar_chain_manager_->getVerifiedBlsSigs(pillar_block_hash); + const auto signatures = pillar_chain_manager_->getVerifiedBlsSignatures(pillar_block_hash); // TODO: split packet to multiple with kGetBlsSigsPacketSize sigs containing each dev::RLPStream s(signatures.size()); diff --git a/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp b/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp index c4e67a5d09..cbe423483c 100644 --- a/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp +++ b/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp @@ -4,6 +4,7 @@ #include "network/tarcap/packets_handler.hpp" #include "network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp" +#include "network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_block_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_dag_sync_packet_handler.hpp" @@ -18,22 +19,21 @@ #include "node/node.hpp" #include "pbft/pbft_chain.hpp" #include "pbft/pbft_manager.hpp" +#include "pillar_chain/pillar_chain_manager.hpp" #include "slashing_manager/slashing_manager.hpp" #include "transaction/transaction_manager.hpp" #include "vote/vote.hpp" namespace taraxa::network::tarcap { -TaraxaCapability::TaraxaCapability(TarcapVersion version, const FullNodeConfig &conf, const h256 &genesis_hash, - std::weak_ptr host, const dev::KeyPair &key, - std::shared_ptr threadpool, - std::shared_ptr packets_stats, - std::shared_ptr syncing_state, std::shared_ptr db, - std::shared_ptr pbft_mgr, std::shared_ptr pbft_chain, - std::shared_ptr vote_mgr, std::shared_ptr dag_mgr, - std::shared_ptr trx_mgr, - std::shared_ptr slashing_manager, - InitPacketsHandlers init_packets_handlers) +TaraxaCapability::TaraxaCapability( + TarcapVersion version, const FullNodeConfig &conf, const h256 &genesis_hash, std::weak_ptr host, + const dev::KeyPair &key, std::shared_ptr threadpool, + std::shared_ptr packets_stats, std::shared_ptr syncing_state, + std::shared_ptr db, std::shared_ptr pbft_mgr, std::shared_ptr pbft_chain, + std::shared_ptr vote_mgr, std::shared_ptr dag_mgr, + std::shared_ptr trx_mgr, std::shared_ptr slashing_manager, + std::shared_ptr pillar_chain_mgr, InitPacketsHandlers init_packets_handlers) : version_(version), all_packets_stats_(std::move(packets_stats)), kConf(conf), @@ -47,9 +47,9 @@ TaraxaCapability::TaraxaCapability(TarcapVersion version, const FullNodeConfig & LOG_OBJECTS_CREATE(logs_prefix + "TARCAP"); peers_state_ = std::make_shared(host, kConf); - packets_handlers_ = - init_packets_handlers(logs_prefix, conf, genesis_hash, peers_state_, pbft_syncing_state_, all_packets_stats_, db, - pbft_mgr, pbft_chain, vote_mgr, dag_mgr, trx_mgr, slashing_manager, node_addr); + packets_handlers_ = init_packets_handlers(logs_prefix, conf, genesis_hash, peers_state_, pbft_syncing_state_, + all_packets_stats_, db, pbft_mgr, pbft_chain, vote_mgr, dag_mgr, trx_mgr, + slashing_manager, pillar_chain_mgr, node_addr); // Must be called after init_packets_handlers thread_pool_->setPacketsHandlers(version, packets_handlers_); @@ -251,6 +251,8 @@ const TaraxaCapability::InitPacketsHandlers TaraxaCapability::kInitLatestVersion logs_prefix); packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, node_addr, logs_prefix); + packets_handlers->registerHandler(config, peers_state, packets_stats, + pillar_chain_mgr, node_addr, logs_prefix); return packets_handlers; }; diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index 9977395041..9d788194c7 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -124,7 +124,6 @@ void FullNode::init() { } pbft_chain_ = std::make_shared(node_addr, db_); - pillar_chain_ = std::make_shared(db_, node_addr); dag_mgr_ = std::make_shared(conf_.genesis.dag_genesis_block, node_addr, conf_.genesis.sortition, conf_.genesis.dag, trx_mgr_, pbft_chain_, final_chain_, db_, key_manager_, conf_.genesis.pbft.gas_limit, conf_.genesis.state, conf_.light_node_history, @@ -139,8 +138,10 @@ void FullNode::init() { conf_.genesis.dag.block_proposer, dag_mgr_, trx_mgr_, final_chain_, db_, key_manager_, node_addr, getSecretKey(), getVrfSecretKey(), conf_.genesis.pbft.gas_limit, conf_.genesis.dag.gas_limit, conf_.genesis.state); - network_ = std::make_shared(conf_, genesis_hash, conf_.net_file_path().string(), kp_, db_, pbft_mgr_, - pbft_chain_, vote_mgr_, dag_mgr_, trx_mgr_, std::move(slashing_manager)); + pillar_chain_ = std::make_shared(db_, final_chain_, vote_mgr_, key_manager_, node_addr); + network_ = + std::make_shared(conf_, genesis_hash, conf_.net_file_path().string(), kp_, db_, pbft_mgr_, pbft_chain_, + vote_mgr_, dag_mgr_, trx_mgr_, std::move(slashing_manager), pillar_chain_); } void FullNode::setupMetricsUpdaters() { @@ -333,6 +334,7 @@ void FullNode::start() { vote_mgr_->setNetwork(network_); pbft_mgr_->setNetwork(network_); dag_mgr_->setNetwork(network_); + pillar_chain_->setNetwork(network_); if (conf_.db_config.rebuild_db) { rebuildDb(); From 8252056f57e4f9618f5cad3e29cfbb5952e528b9 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Mon, 9 Oct 2023 12:55:35 -0700 Subject: [PATCH 09/20] rebase me... --- .../config_jsons/default/default_genesis.json | 12 ++-- .../config_jsons/devnet/devnet_genesis.json | 56 ++++++++++++------- .../config_jsons/mainnet/mainnet_genesis.json | 3 +- .../config_jsons/testnet/testnet_genesis.json | 5 +- .../common/include/common/encoding_rlp.hpp | 12 ++++ libraries/config/include/config/hardfork.hpp | 3 + .../config/include/config/state_config.hpp | 2 + libraries/config/src/hardfork.cpp | 6 +- libraries/config/src/state_config.cpp | 4 +- 9 files changed, 75 insertions(+), 28 deletions(-) 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 cad60f15cc..72e35a3256 100644 --- a/libraries/cli/include/cli/config_jsons/default/default_genesis.json +++ b/libraries/cli/include/cli/config_jsons/default/default_genesis.json @@ -30,7 +30,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0x84595161401484a000000" }, - "vrf_key": "05fe580fd2d461ee5f762a33bbe669403bb04a851f2e9ed8d2579a9c9b77c3ec" + "vrf_key": "05fe580fd2d461ee5f762a33bbe669403bb04a851f2e9ed8d2579a9c9b77c3ec", + "bls_key": "" }, { "address": "0x56e0de6933d9d0453d0363caf42b136eb5854e4e", @@ -41,7 +42,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0x84595161401484a000000" }, - "vrf_key": "70d34c86787e5f7bd0f266cad291cb521e23176fa37c6efc034858a1620ac69e" + "vrf_key": "70d34c86787e5f7bd0f266cad291cb521e23176fa37c6efc034858a1620ac69e", + "bls_key": "" }, { "address": "0x71bdcbec7e3642782447b0fbf31eed068dfbdbb1", @@ -52,7 +54,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0x84595161401484a000000" }, - "vrf_key": "f8d5c00ce9fa3058341e051b36a1e6ccf69df81fb865568b2bf1507d085691e2" + "vrf_key": "f8d5c00ce9fa3058341e051b36a1e6ccf69df81fb865568b2bf1507d085691e2", + "bls_key": "" } ] }, @@ -105,6 +108,7 @@ "magnolia_hf" : { "block_num" : 0, "jail_time": 163459 - } + }, + "ficus_hf_block_num": 0 } } \ No newline at end of file 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 5a0d4441ae..775d3bf7e3 100644 --- a/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json @@ -30,7 +30,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "05fe580fd2d461ee5f762a33bbe669403bb04a851f2e9ed8d2579a9c9b77c3ec" + "vrf_key": "05fe580fd2d461ee5f762a33bbe669403bb04a851f2e9ed8d2579a9c9b77c3ec", + "bls_key": "" }, { "address": "0x56e0de6933d9d0453d0363caf42b136eb5854e4e", @@ -41,7 +42,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "70d34c86787e5f7bd0f266cad291cb521e23176fa37c6efc034858a1620ac69e" + "vrf_key": "70d34c86787e5f7bd0f266cad291cb521e23176fa37c6efc034858a1620ac69e", + "bls_key": "" }, { "address": "0x71bdcbec7e3642782447b0fbf31eed068dfbdbb1", @@ -52,7 +54,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "f8d5c00ce9fa3058341e051b36a1e6ccf69df81fb865568b2bf1507d085691e2" + "vrf_key": "f8d5c00ce9fa3058341e051b36a1e6ccf69df81fb865568b2bf1507d085691e2", + "bls_key": "" }, { "address": "0xac24bc60a491bd0c29414e5f34aa6bbd8d4aa499", @@ -63,7 +66,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "aa12507d00c992b95e65d80b21fd2db5b48c4f7ff4393064828d1adc930710b4" + "vrf_key": "aa12507d00c992b95e65d80b21fd2db5b48c4f7ff4393064828d1adc930710b4", + "bls_key": "" }, { "address": "0x635d3831ad5d1252a2a07f09b8d3539b3af34df8", @@ -74,7 +78,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "bd34898ae0080187c408b5724f05682855c4425fda61d332f5f9d746d4eb753a" + "vrf_key": "bd34898ae0080187c408b5724f05682855c4425fda61d332f5f9d746d4eb753a", + "bls_key": "" }, { "address": "0x43af71034ed7fd0b54496a30ba4a5889a94e7088", @@ -85,7 +90,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "25d35fed93989c40b4e8685d9d7ee02213230221ea9efcbe8cfccfc788670dba" + "vrf_key": "25d35fed93989c40b4e8685d9d7ee02213230221ea9efcbe8cfccfc788670dba", + "bls_key": "" }, { "address": "0x4546f088bf636ed4652d1635c98ef5422805dfa3", @@ -96,7 +102,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "55c0bd1af84fb793a5dd7b960e330248d8a0acde566922b3e210f43592700dad" + "vrf_key": "55c0bd1af84fb793a5dd7b960e330248d8a0acde566922b3e210f43592700dad", + "bls_key": "" }, { "address": "0x8ca042649a263272442bee8b7209fa19426e54c4", @@ -107,7 +114,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "33131367e7279ee51c0f26c6f9b6627848f822d134abef21a88be467dfbaae7b" + "vrf_key": "33131367e7279ee51c0f26c6f9b6627848f822d134abef21a88be467dfbaae7b", + "bls_key": "" }, { "address": "0x7d7319df8950546850a01a0d793ee602f6eb390f", @@ -118,7 +126,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "da63de37c69a59cb3ebbcfb79ef8d561b18b448b544a14438c62cd56bc0a29f5" + "vrf_key": "da63de37c69a59cb3ebbcfb79ef8d561b18b448b544a14438c62cd56bc0a29f5", + "bls_key": "" }, { "address": "0x64c171b9845c15c4555f7a4489895f0e687c496c", @@ -129,7 +138,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "337178752602a5ca38928bf0d8d434ec653505c92b280b0edab6c39d5e79f4fd" + "vrf_key": "337178752602a5ca38928bf0d8d434ec653505c92b280b0edab6c39d5e79f4fd", + "bls_key": "" }, { "address": "0x614c85fad6f17f03949f735e05b1a24c5155b726", @@ -140,7 +150,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "ac08e4ca5f1bcdd61dbefa7551ab839bdd4545e59ee8a4ab5d3aabb71104ab73" + "vrf_key": "ac08e4ca5f1bcdd61dbefa7551ab839bdd4545e59ee8a4ab5d3aabb71104ab73", + "bls_key": "" }, { "address": "0xeff3dd2b0a6c29146c46ca01764aae0691ee1744", @@ -151,7 +162,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "189b05cca0a816a36f977f0541ef7585218b2087f04b23444ab58d0c755adecc" + "vrf_key": "189b05cca0a816a36f977f0541ef7585218b2087f04b23444ab58d0c755adecc", + "bls_key": "" }, { "address": "0xe543a20db4fa1820cc9f00144fc402bb1f31aa29", @@ -162,7 +174,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "8e95172f90b68ee753132bf6342ee00b398e2417312f610d58c34729ab0608ee" + "vrf_key": "8e95172f90b68ee753132bf6342ee00b398e2417312f610d58c34729ab0608ee", + "bls_key": "" }, { "address": "0x211a5ec33fec843b14319bcd62ab30c2a064745e", @@ -173,7 +186,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "959551740ff948d9714f15a2bfb2183c4ead897dd79775a0a18488aa8936e2ba" + "vrf_key": "959551740ff948d9714f15a2bfb2183c4ead897dd79775a0a18488aa8936e2ba", + "bls_key": "" }, { "address": "0x5354adf587cad5fe74e4912d4b6c1f754538891d", @@ -184,7 +198,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "56b7831cb3e35c1d6d1e3f661de2068d6feeaa54074b3e02709a87d7f0d6c72a" + "vrf_key": "56b7831cb3e35c1d6d1e3f661de2068d6feeaa54074b3e02709a87d7f0d6c72a", + "bls_key": "" }, { "address": "0x1473a6c154655fdc1f19d98e5823d3bb3f09a895", @@ -195,7 +210,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "e774c519814cbc04008aa958932e7adb82ebbbd6ca69089c0a1458ea34fb4299" + "vrf_key": "e774c519814cbc04008aa958932e7adb82ebbbd6ca69089c0a1458ea34fb4299", + "bls_key": "" }, { "address": "0x9588f6457d67792f141424983a93978f44331054", @@ -206,7 +222,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "1b15b7bef6a1dbe9aeb2792f2e38d6222d31f8c6c15cff1152f258013d70d933" + "vrf_key": "1b15b7bef6a1dbe9aeb2792f2e38d6222d31f8c6c15cff1152f258013d70d933", + "bls_key": "" }, { "address": "0xb48da366e19f141f5647dcdb0960eb88719e1c8d", @@ -217,7 +234,8 @@ "delegations": { "0x7e4aa664f71de4e9d0b4a6473d796372639bdcde": "0xd3c21bcecceda1000000" }, - "vrf_key": "37bf145ac98e7de7db6e5b933e72737fbf190fd4fb1d193b15cf8b00db30ba30" + "vrf_key": "37bf145ac98e7de7db6e5b933e72737fbf190fd4fb1d193b15cf8b00db30ba30", + "bls_key": "" } ] }, @@ -273,4 +291,4 @@ "jail_time": 1000 } } -} \ No newline at end of file +} 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 747257b6b1..b66c3d0c68 100644 --- a/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json @@ -1640,6 +1640,7 @@ "magnolia_hf" : { "block_num" : 5730000, "jail_time": 163459 - } + }, + "ficus_hf_block_num": 0 } } \ No newline at end of file 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 79c2f1911a..71cab08498 100644 --- a/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json @@ -140,6 +140,7 @@ "magnolia_hf": { "block_num": 297000, "jail_time": 163459 - } + }, + "ficus_hf_block_num": 0 } -} \ No newline at end of file +} diff --git a/libraries/common/include/common/encoding_rlp.hpp b/libraries/common/include/common/encoding_rlp.hpp index 41a4c2c917..0fdfd33335 100644 --- a/libraries/common/include/common/encoding_rlp.hpp +++ b/libraries/common/include/common/encoding_rlp.hpp @@ -2,6 +2,8 @@ #include +#include +#include #include #include #include @@ -42,6 +44,12 @@ inline auto rlp(RLPEncoderRef encoding, T const& target) -> decltype(target.rlp( inline auto rlp(RLPEncoderRef encoding, std::string const& target) { encoding.append(target); } +inline auto rlp(RLPEncoderRef encoding, const libff::alt_bn128_G2& target) { + std::stringstream sig_ss; + sig_ss << target; + encoding.append(sig_ss.str()); +} + inline auto rlp(RLPEncoderRef encoding, bytes const& target) { encoding.append(target); } template @@ -104,6 +112,10 @@ void rlp(RLPDecoderRef encoding, dev::FixedHash& target) { inline auto rlp(RLPDecoderRef encoding, std::string& target) { target = encoding.value.toString(encoding.strictness); } +inline auto rlp(RLPDecoderRef encoding, libff::alt_bn128_G2& target) { + std::stringstream(encoding.value.toString(encoding.strictness)) >> target; +} + inline auto rlp(RLPDecoderRef encoding, bytes& target) { target = encoding.value.toBytes(encoding.strictness); } template diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp index 7246e9932c..ff440d3553 100644 --- a/libraries/config/include/config/hardfork.hpp +++ b/libraries/config/include/config/hardfork.hpp @@ -50,6 +50,9 @@ struct HardforksConfig { // participate in consensus MagnoliaHardfork magnolia_hf; + // Ficus hardfork: implementation of pillar block & bls signatures required for bridge + uint64_t ficus_hf_block_num; + HAS_RLP_FIELDS }; diff --git a/libraries/config/include/config/state_config.hpp b/libraries/config/include/config/state_config.hpp index 338f28e23c..ca8593ea70 100644 --- a/libraries/config/include/config/state_config.hpp +++ b/libraries/config/include/config/state_config.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -27,6 +28,7 @@ struct ValidatorInfo { addr_t address; addr_t owner; vrf_wrapper::vrf_pk_t vrf_key; + libff::alt_bn128_G2 bls_key; uint16_t commission = 0; std::string endpoint; std::string description; diff --git a/libraries/config/src/hardfork.cpp b/libraries/config/src/hardfork.cpp index 6b4f7d5cee..c993692120 100644 --- a/libraries/config/src/hardfork.cpp +++ b/libraries/config/src/hardfork.cpp @@ -44,6 +44,7 @@ Json::Value enc_json(const HardforksConfig& obj) { } json["magnolia_hf"] = enc_json(obj.magnolia_hf); + json["ficus_hf_block_num"] = dev::toJS(obj.ficus_hf_block_num); return json; } @@ -68,6 +69,9 @@ void dec_json(const Json::Value& json, HardforksConfig& obj) { if (const auto& e = json["magnolia_hf"]) { dec_json(e, obj.magnolia_hf); } + + obj.ficus_hf_block_num = dev::getUInt(json["ficus_hf_block_num"]); } -RLP_FIELDS_DEFINE(HardforksConfig, fix_redelegate_block_num, redelegations, rewards_distribution_frequency, magnolia_hf) +RLP_FIELDS_DEFINE(HardforksConfig, fix_redelegate_block_num, redelegations, rewards_distribution_frequency, magnolia_hf, + ficus_hf_block_num) diff --git a/libraries/config/src/state_config.cpp b/libraries/config/src/state_config.cpp index e938d3d000..ff257c48ba 100644 --- a/libraries/config/src/state_config.cpp +++ b/libraries/config/src/state_config.cpp @@ -56,6 +56,7 @@ Json::Value enc_json(const ValidatorInfo& obj) { json["address"] = dev::toJS(obj.address); json["owner"] = dev::toJS(obj.owner); json["vrf_key"] = dev::toJS(obj.vrf_key); + json["bls_key"] = dev::toJS(obj.bls_key); json["commission"] = dev::toJS(obj.commission); json["endpoint"] = obj.endpoint; json["description"] = obj.description; @@ -67,6 +68,7 @@ void dec_json(const Json::Value& json, ValidatorInfo& obj) { obj.address = addr_t(json["address"].asString()); obj.owner = addr_t(json["owner"].asString()); obj.vrf_key = vrf_wrapper::vrf_pk_t(json["vrf_key"].asString()); + std::stringstream(json["bls_key"].asString()) >> obj.bls_key; obj.commission = dev::getUInt(json["commission"]); obj.endpoint = json["endpoint"].asString(); obj.description = json["description"].asString(); @@ -120,7 +122,7 @@ void dec_json(const Json::Value& json, DPOSConfig& obj) { } RLP_FIELDS_DEFINE(EVMChainConfig, chain_id) -RLP_FIELDS_DEFINE(ValidatorInfo, address, owner, vrf_key, commission, endpoint, description, delegations) +RLP_FIELDS_DEFINE(ValidatorInfo, address, owner, vrf_key, bls_key, commission, endpoint, description, delegations) RLP_FIELDS_DEFINE(DPOSConfig, eligibility_balance_threshold, vote_eligibility_balance_step, validator_maximum_stake, minimum_deposit, max_block_author_reward, dag_proposers_reward, commission_change_delta, commission_change_frequency, delegation_delay, delegation_locking_period, blocks_per_year, From f2e4bdb5713268e1898596654145ef54e068f88c Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 18 Oct 2023 17:29:17 -0700 Subject: [PATCH 10/20] implement bls key wallet generation --- CMakeLists.txt | 2 +- libraries/cli/CMakeLists.txt | 2 +- libraries/cli/include/cli/config.hpp | 1 + libraries/cli/include/cli/tools.hpp | 6 ++- libraries/cli/src/config.cpp | 5 +- libraries/cli/src/tools.cpp | 46 +++++++++++++++++-- libraries/common/CMakeLists.txt | 1 + libraries/common/include/common/util.hpp | 3 ++ libraries/common/src/util.cpp | 4 ++ libraries/config/include/config/config.hpp | 1 + libraries/config/include/config/hardfork.hpp | 2 +- .../config/include/config/state_config.hpp | 2 +- libraries/config/src/config.cpp | 20 ++++++++ libraries/config/src/state_config.cpp | 8 +++- .../pillar_chain/pillar_chain_manager.hpp | 7 +-- .../src/pillar_chain/pillar_chain_manager.cpp | 7 ++- .../common/ext_bls_sig_packet_handler.hpp | 2 +- .../v1/init_packets_handlers.hpp | 4 +- .../common/ext_bls_sig_packet_handler.cpp | 4 +- .../get_bls_sigs_bundle_packet_handler.cpp | 7 ++- .../network/src/tarcap/taraxa_capability.cpp | 3 ++ libraries/core_libs/node/src/node.cpp | 3 +- libraries/vdf/CMakeLists.txt | 1 + 23 files changed, 115 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e85930e31b..972a88ecdf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,7 +209,7 @@ include(CMakeModules/git_info.cmake) include(ExternalProject) -# find and include system libraries used in submodues and libraries +# find and include system libraries used in submodules and libraries find_package(GMP) find_package(MPFR) # used in libraries/aleth & submodules/libBLS diff --git a/libraries/cli/CMakeLists.txt b/libraries/cli/CMakeLists.txt index 1424999c9f..7568319834 100644 --- a/libraries/cli/CMakeLists.txt +++ b/libraries/cli/CMakeLists.txt @@ -12,7 +12,7 @@ set(SOURCES add_library(cli ${SOURCES} ${HEADERS}) target_include_directories(cli PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(cli PUBLIC config) +target_link_libraries(cli PUBLIC bls config) install(TARGETS cli ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/libraries/cli/include/cli/config.hpp b/libraries/cli/include/cli/config.hpp index 1d4117d1c9..a3a0a18a26 100644 --- a/libraries/cli/include/cli/config.hpp +++ b/libraries/cli/include/cli/config.hpp @@ -55,6 +55,7 @@ class Config { static constexpr const char* LOG_CHANNELS_APPEND = "log-channels-append"; static constexpr const char* NODE_SECRET = "node-secret"; static constexpr const char* VRF_SECRET = "vrf-secret"; + static constexpr const char* BLS_SECRET = "bls-secret"; static constexpr const char* OVERWRITE_CONFIG = "overwrite-config"; static constexpr const char* ENABLE_TEST_RPC = "enable-test-rpc"; static constexpr const char* ENABLE_DEBUG = "debug"; diff --git a/libraries/cli/include/cli/tools.hpp b/libraries/cli/include/cli/tools.hpp index cf33ed2928..ccc22dd0c9 100644 --- a/libraries/cli/include/cli/tools.hpp +++ b/libraries/cli/include/cli/tools.hpp @@ -40,7 +40,8 @@ Json::Value overrideConfig(Json::Value& config, std::string& data_dir, const std const std::vector& log_configurations, const std::vector& boot_nodes_append, const std::vector& log_channels_append); -Json::Value overrideWallet(Json::Value& wallet, const std::string& node_key, const std::string& vrf_key); +Json::Value overrideWallet(Json::Value& wallet, const std::string& node_key, const std::string& vrf_key, + const std::string& bls_key); std::string getHomeDir(); std::string getTaraxaDefaultDir(); @@ -49,6 +50,7 @@ std::string getTaraxaDefaultConfigFile(); std::string getTaraxaDefaultWalletFile(); std::string getTaraxaDefaultGenesisFile(); Json::Value createWalletJson(const dev::KeyPair& account, const taraxa::vrf_wrapper::vrf_sk_t& sk, - const taraxa::vrf_wrapper::vrf_pk_t& pk); + const taraxa::vrf_wrapper::vrf_pk_t& pk, const libff::alt_bn128_Fr& bls_secret, + const libff::alt_bn128_G2& bls_pub_key); } // namespace taraxa::cli::tools \ No newline at end of file diff --git a/libraries/cli/src/config.cpp b/libraries/cli/src/config.cpp index 91a62da4ef..4f33fdc111 100644 --- a/libraries/cli/src/config.cpp +++ b/libraries/cli/src/config.cpp @@ -33,6 +33,7 @@ Config::Config(int argc, const char* argv[]) { std::vector log_channels_append; std::string node_secret; std::string vrf_secret; + std::string bls_secret; bool overwrite_config; bool destroy_db = false; @@ -121,6 +122,8 @@ Config::Config(int argc, const char* argv[]) { node_command_options.add_options()(VRF_SECRET, bpo::value(&vrf_secret), "Vrf secret key to use"); + node_command_options.add_options()(BLS_SECRET, bpo::value(&bls_secret), "Bls secret key to use"); + node_command_options.add_options()( OVERWRITE_CONFIG, bpo::bool_switch(&overwrite_config), "Overwrite config - " @@ -222,7 +225,7 @@ Config::Config(int argc, const char* argv[]) { // Override config values with values from CLI config_json = tools::overrideConfig(config_json, data_dir, boot_nodes, log_channels, log_configurations, boot_nodes_append, log_channels_append); - wallet_json = tools::overrideWallet(wallet_json, node_secret, vrf_secret); + wallet_json = tools::overrideWallet(wallet_json, node_secret, vrf_secret, bls_secret); if (light_node) { config_json["is_light_node"] = true; diff --git a/libraries/cli/src/tools.cpp b/libraries/cli/src/tools.cpp index cdfea7be4f..3001ebc9e8 100644 --- a/libraries/cli/src/tools.cpp +++ b/libraries/cli/src/tools.cpp @@ -1,6 +1,7 @@ #include "cli/tools.hpp" +#include #include #include @@ -9,6 +10,9 @@ #include "cli/config.hpp" #include "common/jsoncpp.hpp" +// TODO: should ne #include +#include + using namespace std; using namespace dev; namespace fs = std::filesystem; @@ -153,16 +157,31 @@ Json::Value overrideConfig(Json::Value& conf, std::string& data_dir, const vecto void generateWallet(const string& wallet) { // Wallet dev::KeyPair account = dev::KeyPair::create(); - auto [pk, sk] = taraxa::vrf_wrapper::getVrfKeyPair(); - auto account_json = createWalletJson(account, sk, pk); + // Required for libBLS::Bls::KeyGeneration() + libBLS::ThresholdUtils::initCurve(); + const auto [bls_secret, bls_puk_key] = libBLS::Bls::KeyGeneration(); + + auto account_json = createWalletJson(account, sk, pk, bls_secret, bls_puk_key); // Create account file util::writeJsonToFile(wallet, account_json); } -Json::Value overrideWallet(Json::Value& wallet, const string& node_key, const string& vrf_key) { +std::string blsSecretToStr(const libff::alt_bn128_Fr& el, size_t base = 10) { + mpz_t t; + mpz_init(t); + el.as_bigint().to_mpz(t); + char arr[mpz_sizeinbase(t, 10) + 2]; + mpz_get_str(arr, base, t); + mpz_clear(t); + + return std::string(arr); +} + +Json::Value overrideWallet(Json::Value& wallet, const std::string& node_key, const std::string& vrf_key, + const std::string& bls_key) { if (!node_key.empty()) { auto sk = dev::Secret(node_key, dev::Secret::ConstructFromStringType::FromHex); dev::KeyPair account = dev::KeyPair(sk); @@ -178,6 +197,17 @@ Json::Value overrideWallet(Json::Value& wallet, const string& node_key, const st wallet["vrf_public"] = pk.toString(); } + if (!bls_key.empty()) { + auto bls_secret = libff::alt_bn128_Fr(bls_key.c_str()); + auto bls_public = getBlsPublicKey(bls_secret); + + wallet["bls_secret"] = blsSecretToStr(bls_secret); + + std::stringstream bls_public_ss; + bls_public_ss << bls_public; + wallet["bls_public"] = bls_public_ss.str(); + } + return wallet; } @@ -212,13 +242,21 @@ void generateVrfFromKey(const string& key) { } Json::Value createWalletJson(const dev::KeyPair& account, const taraxa::vrf_wrapper::vrf_sk_t& sk, - const taraxa::vrf_wrapper::vrf_pk_t& pk) { + const taraxa::vrf_wrapper::vrf_pk_t& pk, const libff::alt_bn128_Fr& bls_secret, + const libff::alt_bn128_G2& bls_pub_key) { Json::Value json(Json::objectValue); json["node_secret"] = toHex(account.secret().ref()); json["node_public"] = account.pub().toString(); json["node_address"] = account.address().toString(); json["vrf_secret"] = sk.toString(); json["vrf_public"] = pk.toString(); + + json["bls_secret"] = blsSecretToStr(bls_secret); + + std::stringstream bls_pub_key_ss; + bls_pub_key_ss << bls_pub_key; + json["bls_public"] = bls_pub_key_ss.str(); + return json; } diff --git a/libraries/common/CMakeLists.txt b/libraries/common/CMakeLists.txt index 584c16883e..8684dbfee0 100644 --- a/libraries/common/CMakeLists.txt +++ b/libraries/common/CMakeLists.txt @@ -30,6 +30,7 @@ target_link_libraries(common PUBLIC taraxa-vrf CONAN_PKG::openssl CONAN_PKG::jsoncpp + bls ) install(TARGETS common diff --git a/libraries/common/include/common/util.hpp b/libraries/common/include/common/util.hpp index 737d84d317..fccdf07734 100644 --- a/libraries/common/include/common/util.hpp +++ b/libraries/common/include/common/util.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,8 @@ namespace taraxa { */ std::string jsonToUnstyledString(const Json::Value &value); +libff::alt_bn128_G2 getBlsPublicKey(const libff::alt_bn128_Fr &bls_secret); + template std::weak_ptr as_weak(std::shared_ptr sp) { return std::weak_ptr(sp); diff --git a/libraries/common/src/util.cpp b/libraries/common/src/util.cpp index a8c8190aa6..5beafcfc1c 100644 --- a/libraries/common/src/util.cpp +++ b/libraries/common/src/util.cpp @@ -11,6 +11,10 @@ std::string jsonToUnstyledString(const Json::Value &value) { return Json::writeString(builder, value); } +libff::alt_bn128_G2 getBlsPublicKey(const libff::alt_bn128_Fr &bls_secret) { + return bls_secret * libff::alt_bn128_G2::one(); +} + void thisThreadSleepForSeconds(unsigned sec) { std::this_thread::sleep_for(std::chrono::seconds(sec)); } void thisThreadSleepForMilliSeconds(unsigned millisec) { diff --git a/libraries/config/include/config/config.hpp b/libraries/config/include/config/config.hpp index 275a16dce4..00043b9e6a 100644 --- a/libraries/config/include/config/config.hpp +++ b/libraries/config/include/config/config.hpp @@ -44,6 +44,7 @@ struct FullNodeConfig { std::filesystem::file_time_type last_json_update_time; dev::Secret node_secret; vrf_wrapper::vrf_sk_t vrf_secret; + libff::alt_bn128_Fr bls_secret; fs::path data_path; fs::path db_path; fs::path log_path; diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp index ff440d3553..fea36feb0e 100644 --- a/libraries/config/include/config/hardfork.hpp +++ b/libraries/config/include/config/hardfork.hpp @@ -51,7 +51,7 @@ struct HardforksConfig { MagnoliaHardfork magnolia_hf; // Ficus hardfork: implementation of pillar block & bls signatures required for bridge - uint64_t ficus_hf_block_num; + uint64_t ficus_hf_block_num = -1; HAS_RLP_FIELDS }; diff --git a/libraries/config/include/config/state_config.hpp b/libraries/config/include/config/state_config.hpp index ca8593ea70..39e9101926 100644 --- a/libraries/config/include/config/state_config.hpp +++ b/libraries/config/include/config/state_config.hpp @@ -28,7 +28,7 @@ struct ValidatorInfo { addr_t address; addr_t owner; vrf_wrapper::vrf_pk_t vrf_key; - libff::alt_bn128_G2 bls_key; + std::optional bls_key; uint16_t commission = 0; std::string endpoint; std::string description; diff --git a/libraries/config/src/config.cpp b/libraries/config/src/config.cpp index c3f8e6225e..9c25aaabfa 100644 --- a/libraries/config/src/config.cpp +++ b/libraries/config/src/config.cpp @@ -151,6 +151,26 @@ FullNodeConfig::FullNodeConfig(const Json::Value &string_or_object, const Json:: } catch (const dev::Exception &e) { throw ConfigException(std::string("Could not parse vrf_public: ") + e.what()); } + + try { + bls_secret = libff::alt_bn128_Fr(wallet["bls_secret"].asString().c_str()); + } catch (const dev::Exception &e) { + throw ConfigException(std::string("Could not parse bls_secret: ") + e.what()); + } + + try { + if (!wallet["bls_public"].isNull()) { + libff::alt_bn128_G2 config_bls_public; + std::stringstream(wallet["bls_public"].asString()) >> config_bls_public; + + if (config_bls_public != getBlsPublicKey(bls_secret)) { + throw ConfigException(std::string("Bls secret key and public key in wallet do not match")); + } + } + } catch (const dev::Exception &e) { + throw ConfigException(std::string("Could not parse bls_public: ") + e.what()); + } + // TODO configurable opts_final_chain.expected_max_trx_per_block = 1000; opts_final_chain.max_trie_full_node_levels_to_cache = 4; diff --git a/libraries/config/src/state_config.cpp b/libraries/config/src/state_config.cpp index ff257c48ba..424cfbc0a9 100644 --- a/libraries/config/src/state_config.cpp +++ b/libraries/config/src/state_config.cpp @@ -56,7 +56,9 @@ Json::Value enc_json(const ValidatorInfo& obj) { json["address"] = dev::toJS(obj.address); json["owner"] = dev::toJS(obj.owner); json["vrf_key"] = dev::toJS(obj.vrf_key); - json["bls_key"] = dev::toJS(obj.bls_key); + if (obj.bls_key.has_value()) { + json["bls_key"] = dev::toJS(*obj.bls_key); + } json["commission"] = dev::toJS(obj.commission); json["endpoint"] = obj.endpoint; json["description"] = obj.description; @@ -68,7 +70,9 @@ void dec_json(const Json::Value& json, ValidatorInfo& obj) { obj.address = addr_t(json["address"].asString()); obj.owner = addr_t(json["owner"].asString()); obj.vrf_key = vrf_wrapper::vrf_pk_t(json["vrf_key"].asString()); - std::stringstream(json["bls_key"].asString()) >> obj.bls_key; + if (!json["bls_key"].isNull()) { + std::stringstream(json["bls_key"].asString()) >> *obj.bls_key; + } obj.commission = dev::getUInt(json["commission"]); obj.endpoint = json["endpoint"].asString(); obj.description = json["description"].asString(); diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index 6ea8a09702..75fd46cba3 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -2,6 +2,7 @@ #include +#include "config/config.hpp" #include "final_chain/data.hpp" #include "logger/logger.hpp" #include "pillar_chain/bls_signature.hpp" @@ -29,7 +30,8 @@ class FinalChain; class PillarChainManager { public: PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, - std::shared_ptr vote_mgr, std::shared_ptr key_manager, addr_t node_addr); + std::shared_ptr vote_mgr, std::shared_ptr key_manager, + const libff::alt_bn128_Fr& bls_secret_key, addr_t node_addr); /** * @Process new final block @@ -83,8 +85,7 @@ class PillarChainManager { const addr_t node_addr_; - // TODO: from wallet-config file - std::pair bls_keys_; + const libff::alt_bn128_Fr kBlsSecretKey; // Last processed pillar block // TODO: might be just atomic hash 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 fb230f2654..2316e5cc94 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 @@ -13,15 +13,14 @@ namespace taraxa { PillarChainManager::PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, std::shared_ptr vote_mgr, std::shared_ptr key_manager, - addr_t node_addr) + const libff::alt_bn128_Fr& bls_secret_key, addr_t node_addr) : db_(std::move(db)), network_{}, final_chain_{std::move(final_chain)}, vote_mgr_(std::move(vote_mgr)), key_manager_(std::move(key_manager)), node_addr_(node_addr), - // TODO: from wallet-config - bls_keys_(libBLS::Bls::KeyGeneration()), + kBlsSecretKey(bls_secret_key), // TODO: last_pillar_block_ might be optional ??? last_pillar_block_{std::make_shared(0, blk_hash_t{0}, blk_hash_t{0})}, last_pillar_block_signatures_{}, @@ -84,7 +83,7 @@ void PillarChainManager::newFinalBlock(const std::shared_ptr lock(mutex_); signature = std::make_shared(last_pillar_block_->getHash(), block_data->final_chain_blk->number, - node_addr_, bls_keys_.first); + node_addr_, kBlsSecretKey); } addVerifiedBlsSig(signature); diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp index 97a3d3f3c4..592734e94a 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.hpp @@ -20,7 +20,7 @@ class ExtBlsSigPacketHandler : public PacketHandler { ExtBlsSigPacketHandler(const FullNodeConfig& conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, std::shared_ptr pillar_chain_manager, const addr_t& node_addr, - const std::string& logs_prefix); + const std::string& log_channel); protected: void processBlsSignature(const std::shared_ptr& signature, const std::shared_ptr& peer); diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp index 28b7c9e11d..4f4ce0f5f2 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/v1/init_packets_handlers.hpp @@ -4,6 +4,7 @@ #include "network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_block_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_sync_packet_handler.hpp" +#include "network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_dag_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/status_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/transaction_packet_handler.hpp" @@ -67,7 +68,8 @@ static const TaraxaCapability::InitPacketsHandlers kInitV1Handlers = // TODO: should ut be registered also for V1 ? packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, node_addr, logs_prefix); - + packets_handlers->registerHandler(config, peers_state, packets_stats, + pillar_chain_mgr, node_addr, logs_prefix); packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, node_addr, logs_prefix); diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp index dc683c7496..df726eafa4 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/common/ext_bls_sig_packet_handler.cpp @@ -9,8 +9,8 @@ namespace taraxa::network::tarcap { ExtBlsSigPacketHandler::ExtBlsSigPacketHandler(const FullNodeConfig &conf, std::shared_ptr peers_state, std::shared_ptr packets_stats, std::shared_ptr pillar_chain_manager, - const addr_t &node_addr, const std::string &logs_prefix) - : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, logs_prefix + "BLS_SIG_PH"), + const addr_t &node_addr, const std::string &log_channel) + : PacketHandler(conf, std::move(peers_state), std::move(packets_stats), node_addr, log_channel), pillar_chain_manager_{std::move(pillar_chain_manager)} {} void ExtBlsSigPacketHandler::processBlsSignature(const std::shared_ptr &signature, diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp index 9f46c5f73e..0797fba6e5 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp @@ -21,9 +21,14 @@ void GetBlsSigsBundlePacketHandler::validatePacketRlpFormat( void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet_data, const std::shared_ptr &peer) { - const PillarBlock::Hash pillar_block_hash = packet_data.rlp_.toHash(); + // TODO: use without [0] ? + const PillarBlock::Hash pillar_block_hash = packet_data.rlp_[0].toHash(); const auto signatures = pillar_chain_manager_->getVerifiedBlsSignatures(pillar_block_hash); + if (signatures.empty()) { + LOG(log_dg_) << "No BLS signatures for " << pillar_block_hash; + return; + } // TODO: split packet to multiple with kGetBlsSigsPacketSize sigs containing each dev::RLPStream s(signatures.size()); diff --git a/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp b/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp index cbe423483c..9226d1ec5f 100644 --- a/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp +++ b/libraries/core_libs/network/src/tarcap/taraxa_capability.cpp @@ -7,6 +7,7 @@ #include "network/tarcap/packets_handlers/latest/bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_block_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/dag_sync_packet_handler.hpp" +#include "network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_dag_sync_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_next_votes_bundle_packet_handler.hpp" #include "network/tarcap/packets_handlers/latest/get_pbft_sync_packet_handler.hpp" @@ -251,6 +252,8 @@ const TaraxaCapability::InitPacketsHandlers TaraxaCapability::kInitLatestVersion logs_prefix); packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, node_addr, logs_prefix); + packets_handlers->registerHandler(config, peers_state, packets_stats, + pillar_chain_mgr, node_addr, logs_prefix); packets_handlers->registerHandler(config, peers_state, packets_stats, pillar_chain_mgr, node_addr, logs_prefix); diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index 9d788194c7..38f455f7ff 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -138,7 +138,8 @@ void FullNode::init() { conf_.genesis.dag.block_proposer, dag_mgr_, trx_mgr_, final_chain_, db_, key_manager_, node_addr, getSecretKey(), getVrfSecretKey(), conf_.genesis.pbft.gas_limit, conf_.genesis.dag.gas_limit, conf_.genesis.state); - pillar_chain_ = std::make_shared(db_, final_chain_, vote_mgr_, key_manager_, node_addr); + pillar_chain_ = + std::make_shared(db_, final_chain_, vote_mgr_, key_manager_, conf_.bls_secret, node_addr); network_ = std::make_shared(conf_, genesis_hash, conf_.net_file_path().string(), kp_, db_, pbft_mgr_, pbft_chain_, vote_mgr_, dag_mgr_, trx_mgr_, std::move(slashing_manager), pillar_chain_); diff --git a/libraries/vdf/CMakeLists.txt b/libraries/vdf/CMakeLists.txt index 912c1dcf32..f8a80bbad3 100644 --- a/libraries/vdf/CMakeLists.txt +++ b/libraries/vdf/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES add_library(vdf ${SOURCES} ${HEADERS}) target_include_directories(vdf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${MPFR_INCLUDES}) + target_link_libraries(vdf PUBLIC logger taraxa-vdf From 6559ebe8df960fe51499f9d567a8d602935efc58 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Fri, 20 Oct 2023 11:28:40 -0700 Subject: [PATCH 11/20] rebase me... --- tests/final_chain_test.cpp | 20 ++++---- tests/full_node_test.cpp | 80 +++++++++++++++++++++++++++++++ tests/test_util/src/test_util.cpp | 14 +++++- 3 files changed, 104 insertions(+), 10 deletions(-) diff --git a/tests/final_chain_test.cpp b/tests/final_chain_test.cpp index ed060a58a5..942e7aafdd 100644 --- a/tests/final_chain_test.cpp +++ b/tests/final_chain_test.cpp @@ -32,17 +32,19 @@ struct FinalChainTest : WithDataDir { uint64_t expected_blk_num = 0; dev::KeyPair dag_proposer_keys = dev::KeyPair::create(); dev::KeyPair pbft_proposer_keys = dev::KeyPair::create(); + void create_validators() { dev::KeyPair validator_owner_keys = dev::KeyPair::create(); cfg.genesis.state.initial_balances[validator_owner_keys.address()] = 10 * cfg.genesis.state.dpos.validator_maximum_stake; for (const auto& keys : {dag_proposer_keys, pbft_proposer_keys}) { const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - state_api::ValidatorInfo validator{keys.address(), validator_owner_keys.address(), vrf_key, 0, "", "", {}}; + state_api::ValidatorInfo validator{keys.address(), validator_owner_keys.address(), vrf_key, {}, 0, "", "", {}}; validator.delegations.emplace(validator_owner_keys.address(), cfg.genesis.state.dpos.validator_maximum_stake); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); } } + void init() { SUT = NewFinalChain(db, cfg); const auto& effective_balances = effective_initial_balances(cfg.genesis.state); @@ -295,7 +297,7 @@ TEST_F(FinalChainTest, initial_validators) { for (const auto& vk : validator_keys) { const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_key, 0, "", "", {}}; + state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_key, {}, 0, "", "", {}}; validator.delegations.emplace(key.address(), cfg.genesis.state.dpos.validator_maximum_stake); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); } @@ -820,7 +822,7 @@ TEST_F(FinalChainTest, remove_jailed_validator_votes_from_total) { for (const auto& vk : validator_keys) { const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_key, 0, "", "", {}}; + state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_key, {}, 0, "", "", {}}; validator.delegations.emplace(key.address(), cfg.genesis.state.dpos.validator_maximum_stake); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); } @@ -845,11 +847,10 @@ TEST_F(FinalChainTest, remove_jailed_validator_votes_from_total) { auto trx = makeDoubleVotingProofTx(vote_a, vote_b, 1, key); auto res = advance({trx}, {true}); - advance({}); - advance({}); - advance({}); - advance({}); - advance({}); + for (size_t idx = 0; idx < 5; idx++) { + advance({}); + } + const auto total_votes = SUT->dpos_eligible_total_vote_count(SUT->last_block_number()); EXPECT_EQ(total_votes_before - votes_per_address, total_votes); } @@ -859,9 +860,10 @@ TEST_F(FinalChainTest, initial_validator_exceed_maximum_stake) { const dev::KeyPair key = dev::KeyPair::create(); const dev::KeyPair validator_key = dev::KeyPair::create(); const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); + const auto bls_pub_key = libBLS::Bls::KeyGeneration().second; fillConfigForGenesisTests(key.address()); - state_api::ValidatorInfo validator{validator_key.address(), key.address(), vrf_key, 0, "", "", {}}; + state_api::ValidatorInfo validator{validator_key.address(), key.address(), vrf_key, bls_pub_key, 0, "", "", {}}; validator.delegations.emplace(key.address(), cfg.genesis.state.dpos.validator_maximum_stake); validator.delegations.emplace(validator_key.address(), cfg.genesis.state.dpos.minimum_deposit); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); diff --git a/tests/full_node_test.cpp b/tests/full_node_test.cpp index 711602cd97..eb8a6406af 100644 --- a/tests/full_node_test.cpp +++ b/tests/full_node_test.cpp @@ -336,10 +336,90 @@ TEST_F(FullNodeTest, db_test) { EXPECT_FALSE(db.getProposalPeriodForDagLevel(107)); } +std::string blsSecretToStr(const libff::alt_bn128_Fr &el, size_t base = 10) { + mpz_t t; + mpz_init(t); + el.as_bigint().to_mpz(t); + char arr[mpz_sizeinbase(t, 10) + 2]; + mpz_get_str(arr, base, t); + mpz_clear(t); + + return std::string(arr); +} + +template +std::string fieldElementToString(const T &el, int base = 16) { + std::string ret; + mpz_t t; + mpz_init(t); + + try { + el.as_bigint().to_mpz(t); + char arr[mpz_sizeinbase(t, 10) + 2]; + mpz_get_str(arr, base, t); + ret = std::string(arr); + } catch (std::exception &e) { + std::cout << "err: " << e.what() << std::endl; + } catch (...) { + std::cout << "unknown err: " << std::endl; + } + + mpz_clear(t); + return ret; +} + +std::string hexStringFromBigint(libff::bigint _x) { + uint8_t x[32]; + for (unsigned i = 0; i < 4; i++) + for (unsigned j = 0; j < 8; j++) x[i * 8 + j] = uint8_t(uint64_t(_x.data[3 - i]) >> (8 * (7 - j))); + + std::stringstream ss; + ss << std::setfill('0'); + for (unsigned i = 0; i < 32; i++) { + ss << std::hex << std::setw(2) << (int)x[i]; + } + + std::string str = ss.str(); + return str.erase(0, std::min(str.find_first_not_of('0'), str.size() - 1)); +}; + TEST_F(FullNodeTest, sync_five_nodes) { using namespace std; auto node_cfgs = make_node_cfgs(5, 1, 20); + for (const auto &cfg : node_cfgs) { + std::cout << "cfg.genesis.state.hardforks.ficus_hf_block_num: " << cfg.genesis.state.hardforks.ficus_hf_block_num + << std::endl; + std::cout << "cfg.bls_secret: " << blsSecretToStr(cfg.bls_secret) << std::endl; + + auto pub_key = getBlsPublicKey(cfg.bls_secret); + + std::stringstream pk_ss; + pk_ss << std::hex << pub_key; + std::cout << "cfg.bls_pub: " << pk_ss.str() << std::endl; + std::cout << "cfg.bls_pub.size: " << pk_ss.str().size() << std::endl; + for (auto c : pk_ss.str()) { + std::uint8_t wtf = static_cast(c); + std::cout << wtf << " "; + } + std::cout << std::endl; + + pub_key.to_affine_coordinates(); + + std::cout << "pub_key.X.c0 str: " << fieldElementToString(pub_key.X.c0) << std::endl; + + std::cout << "pub_key.X.c0: " << fieldElementToString(pub_key.X.c0).size() << std::endl; + std::cout << "pub_key.X.c1: " << fieldElementToString(pub_key.X.c1).size() << std::endl; + std::cout << "pub_key.Y.c0: " << fieldElementToString(pub_key.Y.c0).size() << std::endl; + std::cout << "pub_key.Y.c1: " << fieldElementToString(pub_key.Y.c1).size() << std::endl; + + std::cout << "2 pub_key.X.c0 str: " << hexStringFromBigint(pub_key.X.c0.as_bigint()) << std::endl; + std::cout << "2 pub_key.X.c0: " << hexStringFromBigint(pub_key.X.c0.as_bigint()).size() << std::endl; + std::cout << "2 pub_key.X.c1: " << hexStringFromBigint(pub_key.X.c1.as_bigint()).size() << std::endl; + std::cout << "2 pub_key.Y.c0: " << hexStringFromBigint(pub_key.Y.c0.as_bigint()).size() << std::endl; + std::cout << "2 pub_key.Y.c1: " << hexStringFromBigint(pub_key.Y.c1.as_bigint()).size() << std::endl; + } + auto nodes = launch_nodes(node_cfgs); class context { diff --git a/tests/test_util/src/test_util.cpp b/tests/test_util/src/test_util.cpp index b1ca6064af..0f4c89f145 100644 --- a/tests/test_util/src/test_util.cpp +++ b/tests/test_util/src/test_util.cpp @@ -2,6 +2,8 @@ #include "pbft/pbft_manager.hpp" #include "vote_manager/vote_manager.hpp" +// TODO: should ne #include +#include namespace taraxa { @@ -183,6 +185,9 @@ std::pair clearAllVotes(const std::vectorws_port = 8778 + i; cfg.node_secret = dev::KeyPair::create().secret(); cfg.vrf_secret = taraxa::vdf_sortition::getVrfKeyPair().second; + cfg.bls_secret = libBLS::Bls::KeyGeneration().first; cfg.network.listen_port = 10003 + i; cfg.genesis.gas_price.minimum_price = 0; @@ -210,6 +216,7 @@ NodesTest::NodesTest() { taraxa::NodeConfig{"7b1fcf0ec1078320117b96e9e9ad9032c06d030cf4024a598347a4623a14a421d4f030cf25ef368ab394a45e9" "20e14b57a259a09c41767dd50d1da27b627412a", "127.0.0.1", 10003}); + cfg.genesis.state.hardforks.ficus_hf_block_num = 0; node_cfgs.emplace_back(cfg); } node_cfgs.front().node_secret = dev::Secret("3800b2875669d9b2053c1aff9224ecfdc411423aac5b5a73d7a45ced1c3b9dcd"); @@ -269,10 +276,15 @@ std::vector NodesTest::make_node_cfgs(size_t total_count continue; } + std::optional bls_key; + if (cfg.genesis.state.hardforks.ficus_hf_block_num == 0) { + bls_key = getBlsPublicKey(cfg.bls_secret); + } + taraxa::state_api::BalanceMap delegations; delegations.emplace(node_addr, cfg.genesis.state.dpos.eligibility_balance_threshold); initial_validators.emplace_back(taraxa::state_api::ValidatorInfo{ - node_addr, node_addr, taraxa::vrf_wrapper::getVrfPublicKey(cfg.vrf_secret), 100, "", "", delegations}); + node_addr, node_addr, taraxa::vrf_wrapper::getVrfPublicKey(cfg.vrf_secret), bls_key, 100, "", "", delegations}); } for (size_t idx = 0; idx < total_count; idx++) { From 1bfe0618d48eeb616f0f4d80fd626985211f6288 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 8 Nov 2023 12:11:56 -0800 Subject: [PATCH 12/20] fix bls signature rlp parsing --- .../consensus/include/pillar_chain/bls_signature.hpp | 2 ++ .../consensus/src/pillar_chain/bls_signature.cpp | 2 +- .../packets_handlers/latest/bls_sig_packet_handler.hpp | 2 +- .../packets_handlers/latest/bls_sig_packet_handler.cpp | 2 +- libraries/core_libs/node/src/node.cpp | 8 ++++---- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp index d66ea6ee62..3c9ab96367 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -21,6 +21,8 @@ class BlsSignature { public: using Hash = uint256_hash_t; + constexpr static size_t kRlpSize{4}; + public: BlsSignature(const dev::RLP& rlp); BlsSignature(PillarBlock::Hash pillar_block_hash, PbftPeriod period, const addr_t& validator, diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp index 4402ebbd8f..d3fbbf702e 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -33,7 +33,7 @@ addr_t BlsSignature::getSignerAddr() const { return signer_addr_; } libff::alt_bn128_G1 BlsSignature::getSignature() const { return signature_; } dev::bytes BlsSignature::getRlp() const { - dev::RLPStream s(4); + dev::RLPStream s(kRlpSize); s << pillar_block_hash_; s << period_; s << signer_addr_; diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp index 9f891221c1..9f7ff83519 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/bls_sig_packet_handler.hpp @@ -22,7 +22,7 @@ class BlsSigPacketHandler : public ExtBlsSigPacketHandler { virtual void process(const threadpool::PacketData& packet_data, const std::shared_ptr& peer) override; protected: - constexpr static size_t kBlsSigPacketSize{1}; + constexpr static size_t kBlsSigPacketSize{BlsSignature::kRlpSize}; }; } // namespace taraxa::network::tarcap diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp index 6c382e3eac..72dfb83827 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/bls_sig_packet_handler.cpp @@ -39,7 +39,7 @@ void BlsSigPacketHandler::onNewBlsSig(const std::shared_ptr &signa void BlsSigPacketHandler::sendBlsSig(const std::shared_ptr &peer, const std::shared_ptr &signature) { - dev::RLPStream s(1); + dev::RLPStream s; s.appendRaw(signature->getRlp()); if (sealAndSend(peer->getId(), SubprotocolPacketType::BlsSigPacket, std::move(s))) { diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index 38f455f7ff..eddaae6710 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -124,10 +124,10 @@ void FullNode::init() { } pbft_chain_ = std::make_shared(node_addr, db_); - dag_mgr_ = std::make_shared(conf_.genesis.dag_genesis_block, node_addr, conf_.genesis.sortition, - conf_.genesis.dag, trx_mgr_, pbft_chain_, final_chain_, db_, key_manager_, - conf_.genesis.pbft.gas_limit, conf_.genesis.state, conf_.light_node_history, - conf_.max_levels_per_period, conf_.dag_expiry_limit); + dag_mgr_ = std::make_shared( + conf_.genesis.dag_genesis_block, node_addr, conf_.genesis.sortition, conf_.genesis.dag, trx_mgr_, pbft_chain_, + final_chain_, db_, key_manager_, conf_.genesis.pbft.gas_limit, conf_.genesis.state, conf_.is_light_node, + conf_.light_node_history, conf_.max_levels_per_period, conf_.dag_expiry_limit); auto slashing_manager = std::make_shared(final_chain_, trx_mgr_, gas_pricer_, conf_, kp_.secret()); vote_mgr_ = std::make_shared(node_addr, conf_.genesis.pbft, kp_.secret(), conf_.vrf_secret, db_, pbft_chain_, final_chain_, key_manager_, slashing_manager); From f9c1fff53631cec9d4ce987c8bdeb714044eff0d Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 8 Nov 2023 13:48:12 -0800 Subject: [PATCH 13/20] fix bls signature validation --- .../include/pillar_chain/bls_signature.hpp | 3 ++- .../consensus/src/pillar_chain/bls_signature.cpp | 16 ++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp index 3c9ab96367..baf78aa9b2 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -38,8 +38,9 @@ class BlsSignature { /** * @return bls signature rlp + * @param include_sig */ - dev::bytes getRlp() const; + dev::bytes getRlp(bool include_sig = true) const; /** * @return bls signature hash diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp index d3fbbf702e..1b0e168047 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -32,22 +32,26 @@ addr_t BlsSignature::getSignerAddr() const { return signer_addr_; } libff::alt_bn128_G1 BlsSignature::getSignature() const { return signature_; } -dev::bytes BlsSignature::getRlp() const { - dev::RLPStream s(kRlpSize); +dev::bytes BlsSignature::getRlp(bool include_sig) const { + size_t rlp_size = include_sig ? kRlpSize : kRlpSize - 1; + + dev::RLPStream s(rlp_size); s << pillar_block_hash_; s << period_; s << signer_addr_; - std::stringstream sig_ss; - sig_ss << signature_; - s << sig_ss.str(); + if (include_sig) { + std::stringstream sig_ss; + sig_ss << signature_; + s << sig_ss.str(); + } return s.invalidate(); } BlsSignature::Hash BlsSignature::getHash() const { if (!cached_hash_.has_value()) { - cached_hash_ = dev::sha3(getRlp()); + cached_hash_ = dev::sha3(getRlp(false)); } return *cached_hash_; From cd94a3f41beb2bb7c5ac9abc848670195f30a0f0 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Thu, 9 Nov 2023 09:45:53 -0800 Subject: [PATCH 14/20] change default configs --- .../cli/include/cli/config_jsons/devnet/devnet_genesis.json | 3 ++- .../cli/include/cli/config_jsons/mainnet/mainnet_genesis.json | 2 +- .../cli/include/cli/config_jsons/testnet/testnet_genesis.json | 2 +- libraries/config/src/hardfork.cpp | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) 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 775d3bf7e3..5e67df766c 100644 --- a/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/devnet/devnet_genesis.json @@ -289,6 +289,7 @@ "magnolia_hf": { "block_num": 0, "jail_time": 1000 - } + }, + "ficus_hf_block_num": -1 } } 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 b66c3d0c68..16caae3857 100644 --- a/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/mainnet/mainnet_genesis.json @@ -1641,6 +1641,6 @@ "block_num" : 5730000, "jail_time": 163459 }, - "ficus_hf_block_num": 0 + "ficus_hf_block_num": -1 } } \ No newline at end of file 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 71cab08498..bf781db4ae 100644 --- a/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json +++ b/libraries/cli/include/cli/config_jsons/testnet/testnet_genesis.json @@ -141,6 +141,6 @@ "block_num": 297000, "jail_time": 163459 }, - "ficus_hf_block_num": 0 + "ficus_hf_block_num": -1 } } diff --git a/libraries/config/src/hardfork.cpp b/libraries/config/src/hardfork.cpp index c993692120..73fa0a1276 100644 --- a/libraries/config/src/hardfork.cpp +++ b/libraries/config/src/hardfork.cpp @@ -70,7 +70,8 @@ void dec_json(const Json::Value& json, HardforksConfig& obj) { dec_json(e, obj.magnolia_hf); } - obj.ficus_hf_block_num = dev::getUInt(json["ficus_hf_block_num"]); + obj.ficus_hf_block_num = + json["ficus_hf_block_num"].isUInt64() ? dev::getUInt(json["ficus_hf_block_num"]) : uint64_t(-1); } RLP_FIELDS_DEFINE(HardforksConfig, fix_redelegate_block_num, redelegations, rewards_distribution_frequency, magnolia_hf, From e901eb9546427678ac4112a45fce868a2740bd77 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Tue, 14 Nov 2023 15:51:34 -0800 Subject: [PATCH 15/20] fix some of the tests --- tests/test_util/gtest.hpp | 6 ++++++ tests/test_util/src/test_util.cpp | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/test_util/gtest.hpp b/tests/test_util/gtest.hpp index ef4f01e94f..bee6fee3e5 100644 --- a/tests/test_util/gtest.hpp +++ b/tests/test_util/gtest.hpp @@ -8,6 +8,9 @@ #include "common/static_init.hpp" #include "config/config.hpp" +// TODO: should ne #include +#include + namespace fs = std::filesystem; using ::taraxa::util::lazy::Lazy; @@ -45,6 +48,9 @@ struct WithDataDir : virtual BaseTest { WithDataDir() : BaseTest() { std::filesystem::remove_all(data_dir); std::filesystem::create_directories(data_dir); + + // Required for libBLS::Bls::KeyGeneration() + libBLS::ThresholdUtils::initCurve(); } virtual ~WithDataDir() { std::filesystem::remove_all(data_dir); } diff --git a/tests/test_util/src/test_util.cpp b/tests/test_util/src/test_util.cpp index 0f4c89f145..6d6c82b65c 100644 --- a/tests/test_util/src/test_util.cpp +++ b/tests/test_util/src/test_util.cpp @@ -2,8 +2,6 @@ #include "pbft/pbft_manager.hpp" #include "vote_manager/vote_manager.hpp" -// TODO: should ne #include -#include namespace taraxa { @@ -185,9 +183,6 @@ std::pair clearAllVotes(const std::vector Date: Fri, 17 Nov 2023 13:16:21 -0800 Subject: [PATCH 16/20] add stakes_changes into pillar block --- .../include/pillar_chain/pillar_block.hpp | 14 ++- .../pillar_chain/pillar_chain_manager.hpp | 12 +++ .../src/pillar_chain/pillar_block.cpp | 17 +++- .../src/pillar_chain/pillar_chain_manager.cpp | 97 ++++++++++++++++--- 4 files changed, 127 insertions(+), 13 deletions(-) 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 32c3b3b73f..73cd5ebb96 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -17,9 +17,18 @@ class PillarBlock { public: using Hash = uint256_hash_t; + // Validator stake change + struct ValidatorStakeChange { + addr_t addr; + dev::s256 stake; // can be both positive or negative + + dev::bytes getRlp() const; + }; + public: // TODO: use real merkle root - PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, blk_hash_t previous_pillar_block_hash); + PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, + std::vector&& validator_stakes_changes, blk_hash_t previous_pillar_block_hash); /** * @return pillar block hash @@ -44,6 +53,9 @@ class PillarBlock { // TODO: replace with actual merkle root blk_hash_t epoch_blocks_merkle_root_{0}; + // Delta change of validators stakes between current and latest pillar block + std::vector validators_stakes_changes_{}; + Hash previous_pillar_block_hash_{0}; const Hash kCachedHash; diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index 75fd46cba3..73f2288240 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -76,6 +76,16 @@ class PillarChainManager { */ std::vector> getVerifiedBlsSignatures(const PillarBlock::Hash pillar_block_hash) const; + private: + /** + * @brief Return a vector of validators stakes changes between the current and previous pillar block + * Changes are ordered based on validators addresses + * + * @param block + * @return ordered vector of validators stakes changes + */ + std::vector getOrderedValidatorsStakesChanges(EthBlockNumber block) const; + private: std::shared_ptr db_; std::weak_ptr network_; @@ -89,6 +99,8 @@ class PillarChainManager { // Last processed pillar block // TODO: might be just atomic hash + // TODO: !!! Important to load last pillar block from db on restart etc... If not, pillar chain mgr will not work + // properly std::shared_ptr last_pillar_block_; // 2t+1 threshold for last pillar block period 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 0a9cb5de84..7bc4a2debb 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -6,19 +6,34 @@ namespace taraxa { +dev::bytes PillarBlock::ValidatorStakeChange::getRlp() const { + dev::RLPStream s(2); + s << addr; + s << stake; + + return s.invalidate(); +} + PillarBlock::PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, + std::vector&& validator_stakes_changes, PillarBlock::Hash previous_pillar_block_hash) : period_(period), epoch_blocks_merkle_root_(epoch_blocks_merkle_root), + validators_stakes_changes_(std::move(validator_stakes_changes)), previous_pillar_block_hash_(previous_pillar_block_hash), kCachedHash(dev::sha3(getRlp())) {} dev::bytes PillarBlock::getRlp() const { - dev::RLPStream s(3); + dev::RLPStream s(4); s << period_; s << epoch_blocks_merkle_root_; s << previous_pillar_block_hash_; + s.appendList(validators_stakes_changes_.size()); + for (const auto& stake_change : validators_stakes_changes_) { + s.appendRaw(stake_change.getRlp()); + } + return s.invalidate(); } 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 2316e5cc94..77f7a0d45e 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 @@ -21,23 +21,32 @@ PillarChainManager::PillarChainManager(std::shared_ptr db, key_manager_(std::move(key_manager)), node_addr_(node_addr), kBlsSecretKey(bls_secret_key), - // TODO: last_pillar_block_ might be optional ??? - last_pillar_block_{std::make_shared(0, blk_hash_t{0}, blk_hash_t{0})}, + last_pillar_block_{nullptr}, last_pillar_block_signatures_{}, mutex_{} { libBLS::ThresholdUtils::initCurve(); + // TODO: load last_pillar_block_ from db + LOG_OBJECTS_CREATE("PILLAR_CHAIN"); } void PillarChainManager::newFinalBlock(const std::shared_ptr& block_data) { + const auto block_num = block_data->final_chain_blk->number; + // There should always be last_pillar_block_, except for the very first pillar block + assert(block_num <= kEpochBlocksNum || last_pillar_block_); + // TODO: add each final block to final blocks merkle tree const auto epoch_blocks_merkle_root = block_data->final_chain_blk->hash; // Create pillar block and broadcast BLS signature - if (block_data->final_chain_blk->number % kEpochBlocksNum == 0) { - const auto pillar_block = std::make_shared(block_data->final_chain_blk->number, - epoch_blocks_merkle_root, last_pillar_block_->getHash()); + if (block_num % kEpochBlocksNum == 0) { + // TODO: this will not work for light node + // Get validators stakes changes between the current and previous pillar block + auto stakes_changes = getOrderedValidatorsStakesChanges(block_num); + + const auto pillar_block = std::make_shared(block_num, epoch_blocks_merkle_root, + std::move(stakes_changes), last_pillar_block_->getHash()); // Get 2t+1 threshold // Note: do not use signature->getPeriod() - 1 as in votes processing - signature are made after the block is @@ -60,10 +69,10 @@ void PillarChainManager::newFinalBlock(const std::shared_ptrfinal_chain_blk->number % (kEpochBlocksNum + kBlsSigBroadcastDelayBlocks) == 0) { + if (block_num % (kEpochBlocksNum + kBlsSigBroadcastDelayBlocks) == 0) { // Check if node is eligible validator try { - if (!final_chain_->dpos_is_eligible(block_data->final_chain_blk->number, node_addr_)) { + if (!final_chain_->dpos_is_eligible(block_num, node_addr_)) { return; } } catch (state_api::ErrFutureBlock& e) { @@ -71,7 +80,7 @@ void PillarChainManager::newFinalBlock(const std::shared_ptrgetBlsKey(block_data->final_chain_blk->number, node_addr_)) { + if (!key_manager_->getBlsKey(block_num, node_addr_)) { LOG(log_er_) << "No bls public key registered in dpos contract !"; return; } @@ -82,8 +91,7 @@ void PillarChainManager::newFinalBlock(const std::shared_ptr signature; { std::shared_lock lock(mutex_); - signature = std::make_shared(last_pillar_block_->getHash(), block_data->final_chain_blk->number, - node_addr_, kBlsSecretKey); + signature = std::make_shared(last_pillar_block_->getHash(), block_num, node_addr_, kBlsSecretKey); } addVerifiedBlsSig(signature); @@ -97,7 +105,7 @@ void PillarChainManager::newFinalBlock(const std::shared_ptrfinal_chain_blk->number % kCheckLatestBlockBlsSigs == 0) { + if (block_num % kCheckLatestBlockBlsSigs == 0) { PillarBlock::Hash last_pillar_block_hash; { std::shared_lock lock(mutex_); @@ -230,6 +238,73 @@ std::vector> PillarChainManager::getVerifiedBlsSig return signatures; } +std::vector PillarChainManager::getOrderedValidatorsStakesChanges( + EthBlockNumber block) const { + assert(block % kEpochBlocksNum == 0); + + auto current_stakes = final_chain_->dpos_validators_total_stakes(block); + + // First pillar block - return all current stakes + if (!last_pillar_block_) { + std::vector changes; + changes.reserve(current_stakes.size()); + std::transform(current_stakes.begin(), current_stakes.end(), std::back_inserter(changes), [](auto& stake) { + return PillarBlock::ValidatorStakeChange{stake.addr, stake.stake}; + }); + + return changes; + } + + auto transformToMap = [](const std::vector& changes) { + std::map changes_map; + for (const auto& change : changes) { + // Convert ValidatorStake.stake uint256 to ValidatorStakeChange.stake int256 + changes_map[change.addr] = PillarBlock::ValidatorStakeChange{change.addr, change.stake}; + } + + return changes_map; + }; + + auto previous_stakes = final_chain_->dpos_validators_total_stakes(last_pillar_block_->getPeriod()); + + auto current_stakes_map = transformToMap(current_stakes); + auto previous_stakes_map = transformToMap(previous_stakes); + + // First create ordered map so the changes are ordered by validator addresses + std::map changes_map; + for (auto& current_stake : current_stakes_map) { + auto previous_stake = previous_stakes_map.find(current_stake.first); + + // Previous stakes does not contain validator address from current stakes -> new stake(delegator) + if (previous_stake == previous_stakes_map.end()) { + changes_map.emplace(std::move(current_stake)); + continue; + } + + // Previous stakes contains validator address from current stakes -> substitute the stakes + changes_map[current_stake.first] = PillarBlock::ValidatorStakeChange{ + current_stake.first, current_stake.second.stake - previous_stake->second.stake}; + + // Delete item from previous_stakes - based on left stakes we know which delegators undelegated all tokens + previous_stakes_map.erase(previous_stake); + } + + // All previous stakes that were not deleted are delegators who undelegated all of their tokens between current and + // previous pillar block. Add these stakes as negative numbers into changes + for (auto& previous_stake_left : previous_stakes_map) { + previous_stake_left.second.stake *= -1; + changes_map.emplace(std::move(previous_stake_left)); + } + + // Transform ordered map of changes to vector + std::vector changes; + changes.reserve(changes_map.size()); + std::transform(changes_map.begin(), changes_map.end(), std::back_inserter(changes), + [](auto& stake_change) { return std::move(stake_change.second); }); + + return changes; +} + void PillarChainManager::setNetwork(std::weak_ptr network) { network_ = std::move(network); } } // namespace taraxa From 15217993ea9bf657b72b698c361f6259c9009750 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Tue, 21 Nov 2023 10:26:44 -0800 Subject: [PATCH 17/20] add state_root to pillar block --- libraries/config/include/config/hardfork.hpp | 11 +- libraries/config/src/hardfork.cpp | 20 +++- .../include/pillar_chain/pillar_block.hpp | 9 +- .../pillar_chain/pillar_chain_manager.hpp | 16 ++- .../src/pillar_chain/pillar_block.cpp | 6 +- .../src/pillar_chain/pillar_chain_manager.cpp | 112 ++++++++++-------- libraries/core_libs/node/src/node.cpp | 12 +- 7 files changed, 114 insertions(+), 72 deletions(-) diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp index fea36feb0e..fbe7cde7e7 100644 --- a/libraries/config/include/config/hardfork.hpp +++ b/libraries/config/include/config/hardfork.hpp @@ -23,6 +23,15 @@ struct MagnoliaHardfork { Json::Value enc_json(const MagnoliaHardfork& obj); void dec_json(const Json::Value& json, MagnoliaHardfork& obj); +struct FicusHardfork { + uint64_t block_num = -1; + uint64_t pillar_block_periods = 0; // number of blocks + + HAS_RLP_FIELDS +}; +Json::Value enc_json(const FicusHardfork& obj); +void dec_json(const Json::Value& json, FicusHardfork& obj); + struct HardforksConfig { // disable it by default (set to max uint64) uint64_t fix_redelegate_block_num = -1; @@ -51,7 +60,7 @@ struct HardforksConfig { MagnoliaHardfork magnolia_hf; // Ficus hardfork: implementation of pillar block & bls signatures required for bridge - uint64_t ficus_hf_block_num = -1; + FicusHardfork ficus_hf; HAS_RLP_FIELDS }; diff --git a/libraries/config/src/hardfork.cpp b/libraries/config/src/hardfork.cpp index 73fa0a1276..e55f6829ec 100644 --- a/libraries/config/src/hardfork.cpp +++ b/libraries/config/src/hardfork.cpp @@ -29,6 +29,19 @@ void dec_json(const Json::Value& json, MagnoliaHardfork& obj) { } RLP_FIELDS_DEFINE(MagnoliaHardfork, block_num, jail_time) +Json::Value enc_json(const FicusHardfork& obj) { + Json::Value json(Json::objectValue); + json["block_num"] = dev::toJS(obj.block_num); + json["pillar_block_periods"] = dev::toJS(obj.pillar_block_periods); + return json; +} + +void dec_json(const Json::Value& json, FicusHardfork& obj) { + obj.block_num = json["block_num"].isUInt64() ? dev::getUInt(json["block_num"]) : uint64_t(-1); + obj.pillar_block_periods = dev::getUInt(json["pillar_block_periods"]); +} +RLP_FIELDS_DEFINE(FicusHardfork, block_num, pillar_block_periods) + Json::Value enc_json(const HardforksConfig& obj) { Json::Value json(Json::objectValue); json["fix_redelegate_block_num"] = dev::toJS(obj.fix_redelegate_block_num); @@ -44,7 +57,7 @@ Json::Value enc_json(const HardforksConfig& obj) { } json["magnolia_hf"] = enc_json(obj.magnolia_hf); - json["ficus_hf_block_num"] = dev::toJS(obj.ficus_hf_block_num); + json["ficus_hf"] = enc_json(obj.ficus_hf); return json; } @@ -70,9 +83,8 @@ void dec_json(const Json::Value& json, HardforksConfig& obj) { dec_json(e, obj.magnolia_hf); } - obj.ficus_hf_block_num = - json["ficus_hf_block_num"].isUInt64() ? dev::getUInt(json["ficus_hf_block_num"]) : uint64_t(-1); + dec_json(json["ficus_hf"], obj.ficus_hf); } RLP_FIELDS_DEFINE(HardforksConfig, fix_redelegate_block_num, redelegations, rewards_distribution_frequency, magnolia_hf, - ficus_hf_block_num) + ficus_hf) 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 73cd5ebb96..57bc893e21 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -26,9 +26,8 @@ class PillarBlock { }; public: - // TODO: use real merkle root - PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, - std::vector&& validator_stakes_changes, blk_hash_t previous_pillar_block_hash); + PillarBlock(PbftPeriod period, h256 state_root, std::vector&& validator_stakes_changes, + blk_hash_t previous_pillar_block_hash); /** * @return pillar block hash @@ -50,8 +49,8 @@ class PillarBlock { // Pillar block pbft period PbftPeriod period_; - // TODO: replace with actual merkle root - blk_hash_t epoch_blocks_merkle_root_{0}; + // Pbft block(for period_) state root + h256 state_root{}; // Delta change of validators stakes between current and latest pillar block std::vector validators_stakes_changes_{}; diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index 73f2288240..a9677406e1 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -34,11 +34,18 @@ class PillarChainManager { const libff::alt_bn128_Fr& bls_secret_key, addr_t node_addr); /** - * @Process new final block + * @Process Creates new pillar block and broadcasts bls signature * * @param block_data */ - void newFinalBlock(const std::shared_ptr& block_data); + void createPillarBlock(const std::shared_ptr& block_data); + + /** + * @brief Check if there is 2t+1 BLS signatures for latest pillar block. If not, request them + * + * @param block_num - current block number + */ + void checkTwoTPlusOneBlsSignatures(EthBlockNumber block_num) const; /** * @brief Set network as a weak pointer @@ -122,12 +129,13 @@ class PillarChainManager { // Nodes start to broadcast BLS signatures for pillar blocks with small delay to make sure that // all up-to-date nodes already processed the pillar block // TODO: validation: kBlsSigBroadcastDelayBlocks should be way smaller than kEpochBlocksNum - static constexpr uint16_t kBlsSigBroadcastDelayBlocks = 5; + // TODO: remove - broadcast signature right away + // static constexpr uint16_t kBlsSigBroadcastDelayBlocks = 5; // How often to check if node has 2t+1 bls signature for the latest pillar block & potentially trigger syncing // TODO: validation: kCheckLatestBlockBlsSigs should be way smaller than kEpochBlocksNum and bigger than // kBlsSigBroadcastDelayBlocks - static constexpr uint16_t kCheckLatestBlockBlsSigs = 10; + static constexpr uint16_t kCheckLatestBlockBlsSigs = 25; LOG_OBJECTS_DEFINE }; 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 7bc4a2debb..8cae733d6d 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -14,11 +14,11 @@ dev::bytes PillarBlock::ValidatorStakeChange::getRlp() const { return s.invalidate(); } -PillarBlock::PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, +PillarBlock::PillarBlock(PbftPeriod period, h256 state_root, std::vector&& validator_stakes_changes, PillarBlock::Hash previous_pillar_block_hash) : period_(period), - epoch_blocks_merkle_root_(epoch_blocks_merkle_root), + state_root(state_root), validators_stakes_changes_(std::move(validator_stakes_changes)), previous_pillar_block_hash_(previous_pillar_block_hash), kCachedHash(dev::sha3(getRlp())) {} @@ -26,7 +26,7 @@ PillarBlock::PillarBlock(PbftPeriod period, blk_hash_t epoch_blocks_merkle_root, dev::bytes PillarBlock::getRlp() const { dev::RLPStream s(4); s << period_; - s << epoch_blocks_merkle_root_; + s << state_root; s << previous_pillar_block_hash_; s.appendList(validators_stakes_changes_.size()); 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 77f7a0d45e..513fe2f0e5 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 @@ -31,31 +31,28 @@ PillarChainManager::PillarChainManager(std::shared_ptr db, LOG_OBJECTS_CREATE("PILLAR_CHAIN"); } -void PillarChainManager::newFinalBlock(const std::shared_ptr& block_data) { +void PillarChainManager::createPillarBlock(const std::shared_ptr& block_data) { const auto block_num = block_data->final_chain_blk->number; + // There should always be last_pillar_block_, except for the very first pillar block assert(block_num <= kEpochBlocksNum || last_pillar_block_); - // TODO: add each final block to final blocks merkle tree - const auto epoch_blocks_merkle_root = block_data->final_chain_blk->hash; - - // Create pillar block and broadcast BLS signature - if (block_num % kEpochBlocksNum == 0) { - // TODO: this will not work for light node - // Get validators stakes changes between the current and previous pillar block - auto stakes_changes = getOrderedValidatorsStakesChanges(block_num); + // TODO: this will not work for light node + // Get validators stakes changes between the current and previous pillar block + auto stakes_changes = getOrderedValidatorsStakesChanges(block_num); - const auto pillar_block = std::make_shared(block_num, epoch_blocks_merkle_root, - std::move(stakes_changes), last_pillar_block_->getHash()); + const auto pillar_block = std::make_shared(block_num, block_data->final_chain_blk->state_root, + std::move(stakes_changes), last_pillar_block_->getHash()); - // Get 2t+1 threshold - // Note: do not use signature->getPeriod() - 1 as in votes processing - signature are made after the block is - // finalized, not before as votes - const auto two_t_plus_one = vote_mgr_->getPbftTwoTPlusOne(pillar_block->getPeriod(), PbftVoteTypes::cert_vote); - // getPbftTwoTPlusOne returns empty optional only when requested period is too far ahead and that should never - // happen as newFinalBlock is triggered only after the block is finalized - assert(two_t_plus_one.has_value()); + // Get 2t+1 threshold + // Note: do not use signature->getPeriod() - 1 as in votes processing - signature are made after the block is + // finalized, not before as votes + const auto two_t_plus_one = vote_mgr_->getPbftTwoTPlusOne(block_num, PbftVoteTypes::cert_vote); + // getPbftTwoTPlusOne returns empty optional only when requested period is too far ahead and that should never + // happen as newFinalBlock is triggered only after the block is finalized + assert(two_t_plus_one.has_value()); + { std::scoped_lock lock(mutex_); last_pillar_block_ = pillar_block; last_pillar_block_signatures_.clear(); @@ -63,59 +60,70 @@ void PillarChainManager::newFinalBlock(const std::shared_ptrdpos_is_eligible(block_num, node_addr_)) { - return; - } - } catch (state_api::ErrFutureBlock& e) { - assert(false); // This should never happen as newFinalBlock is triggered after the new block is finalized - return; - } + // TODO: do not create & gossip own sig or request other signatures if the node is in syncing state - if (!key_manager_->getBlsKey(block_num, node_addr_)) { - LOG(log_er_) << "No bls public key registered in dpos contract !"; + // Check if node is eligible validator + try { + if (!final_chain_->dpos_is_eligible(block_num, node_addr_)) { return; } + } catch (state_api::ErrFutureBlock& e) { + assert(false); // This should never happen as newFinalBlock is triggered after the new block is finalized + return; + } - // Create and broadcast bls signature with kBlsSigBroadcastDelayBlocks delay to make sure other up-to-date nodes - // already processed the latest pillar block - // TODO: maybe dont use the delay and accept signatures with right period ??? - std::shared_ptr signature; - { - std::shared_lock lock(mutex_); - signature = std::make_shared(last_pillar_block_->getHash(), block_num, node_addr_, kBlsSecretKey); - } + if (!key_manager_->getBlsKey(block_num, node_addr_)) { + LOG(log_er_) << "No bls public key registered in dpos contract !"; + return; + } - addVerifiedBlsSig(signature); + // Creates bls signature + // TODO: maybe dont use the delay and accept signatures with right period ??? + std::shared_ptr signature; + { + // TODO: pillar_block can be used instead of last_pillar_block_ -> no lock needed ? + std::shared_lock lock(mutex_); + signature = std::make_shared(last_pillar_block_->getHash(), block_num, node_addr_, kBlsSecretKey); + } + // Broadcasts bls signature + if (addVerifiedBlsSig(signature)) { if (auto net = network_.lock()) { net->gossipBlsSignature(signature); } + } +} +void PillarChainManager::checkTwoTPlusOneBlsSignatures(EthBlockNumber block_num) const { + // Perform the check only every kCheckLatestBlockBlsSigs blocks + if (block_num % kCheckLatestBlockBlsSigs != 0) { return; } - // Check (& request) 2t+1 signatures - // TODO: fix bls sigs requesting - do it every N blocks after pillar block was created - if (block_num % kCheckLatestBlockBlsSigs == 0) { - PillarBlock::Hash last_pillar_block_hash; - { - std::shared_lock lock(mutex_); - last_pillar_block_hash = last_pillar_block_->getHash(); + PillarBlock::Hash last_pillar_block_hash; + { + std::shared_lock lock(mutex_); + + // No last pillar block registered... This should happen only before the first pillar block is created + if (!last_pillar_block_) [[unlikely]] { + return; } - // TODO: Request signature only if node does not have 2t+1 bls signatures - if (auto net = network_.lock()) { - net->requestBlsSigBundle(last_pillar_block_hash); + // Check 2t+1 signatures + if (last_pillar_block_signatures_weight_ >= last_pillar_block_two_t_plus_one_) { + // There is >= 2t+1 bls signatures + return; } + + last_pillar_block_hash = last_pillar_block_->getHash(); + } + + // There is < 2t+1 bls signatures, request it + if (auto net = network_.lock()) { + net->requestBlsSigBundle(last_pillar_block_hash); } } diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index eddaae6710..ee0acadd6c 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -322,11 +322,17 @@ void FullNode::start() { }, subscription_pool_); - // TODO: send new block to pillar chain for processing final_chain_->block_finalized_.subscribe( - [pillar_chain_weak = as_weak(pillar_chain_)](const auto &res) { + [pillar_block_periods = conf_.genesis.state.hardforks.ficus_hf.pillar_block_periods, + pillar_chain_weak = as_weak(pillar_chain_)](const auto &res) { if (auto pillar_chain = pillar_chain_weak.lock()) { - pillar_chain->newFinalBlock(res); + const auto block_num = res->final_chain_blk->number; + + if (block_num % pillar_block_periods == 0) { + pillar_chain->createPillarBlock(res); + } else { + pillar_chain->checkTwoTPlusOneBlsSignatures(block_num); + } } }, subscription_pool_); From 5737ad3fd5bfd6582fad309fdbc43a8b55fc3ef8 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 22 Nov 2023 20:24:43 -0800 Subject: [PATCH 18/20] refactor the way bls signatures are stored and processed --- .../include/pillar_chain/pillar_block.hpp | 8 +- .../pillar_chain/pillar_chain_manager.hpp | 58 ++++--- .../src/pillar_chain/pillar_chain_manager.cpp | 156 +++++++++++++----- .../network/include/network/network.hpp | 3 +- .../get_bls_sigs_bundle_packet_handler.hpp | 3 +- libraries/core_libs/network/src/network.cpp | 4 +- .../get_bls_sigs_bundle_packet_handler.cpp | 17 +- tests/test_util/src/test_util.cpp | 4 +- 8 files changed, 175 insertions(+), 78 deletions(-) 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 57bc893e21..0dc00edb93 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -47,15 +47,15 @@ class PillarBlock { private: // Pillar block pbft period - PbftPeriod period_; + const PbftPeriod period_{0}; // Pbft block(for period_) state root - h256 state_root{}; + const h256 state_root{}; // Delta change of validators stakes between current and latest pillar block - std::vector validators_stakes_changes_{}; + const std::vector validators_stakes_changes_{}; - Hash previous_pillar_block_hash_{0}; + const Hash previous_pillar_block_hash_{0}; const Hash kCachedHash; }; diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index a9677406e1..bbd2903dcc 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -28,6 +28,20 @@ class FinalChain; * @brief PillarChainMgr class contains functionality related to pillar chain */ class PillarChainManager { + public: + struct BlsSignatures { + struct PillarBlockBlsSignatures { + std::unordered_map> signatures; + uint64_t weight{0}; // Signatures weight + }; + + std::unordered_map pillar_block_signatures; + std::unordered_map unique_signers; + + // 2t+1 threshold for pillar block period + uint64_t two_t_plus_one{0}; + }; + public: PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, std::shared_ptr vote_mgr, std::shared_ptr key_manager, @@ -61,6 +75,14 @@ class PillarChainManager { */ bool isRelevantBlsSig(const std::shared_ptr signature) const; + /** + * @brief Checks if signature is unique per period & validator (signer) + * + * @param signature + * @return true if unique, otherwise false + */ + bool isUniqueBlsSig(const std::shared_ptr signature) const; + /** * @brief Validates bls signature * @@ -79,9 +101,14 @@ class PillarChainManager { /** * @brief Get all bls signatures for specified pillar block - * @return all bls signatures + * + * @param period + * @param pillar_block_hash + * + * @return all bls signatures for specified period and pillar block hash */ - std::vector> getVerifiedBlsSignatures(const PillarBlock::Hash pillar_block_hash) const; + std::vector> getVerifiedBlsSignatures(PbftPeriod period, + const PillarBlock::Hash pillar_block_hash) const; private: /** @@ -106,35 +133,22 @@ class PillarChainManager { // Last processed pillar block // TODO: might be just atomic hash - // TODO: !!! Important to load last pillar block from db on restart etc... If not, pillar chain mgr will not work - // properly + // TODO: !!! Important to load last pillar block from db in ctor (on restart etc...) If not, pillar chain mgr will not + // work properly std::shared_ptr last_pillar_block_; - // 2t+1 threshold for last pillar block period - uint64_t last_pillar_block_two_t_plus_one_; + // Bls signatures for last_pillar_block_.period and potential +1 future pillar block period + std::map bls_signatures_; - // Last processed pillar block signatures - std::unordered_map> last_pillar_block_signatures_; - - // Last processed pillar block signatures weight - uint64_t last_pillar_block_signatures_weight_; - - // Protects last_pillar_block_ & last_pillar_block_signatures_ & last_pillar_block_signatures_weight_ + // Protects last_pillar_block_ & bls_signatures mutable std::shared_mutex mutex_; // How often is pillar block created - // TODO: put in config + // TODO: use from config static constexpr uint16_t kEpochBlocksNum = 100; - // Nodes start to broadcast BLS signatures for pillar blocks with small delay to make sure that - // all up-to-date nodes already processed the pillar block - // TODO: validation: kBlsSigBroadcastDelayBlocks should be way smaller than kEpochBlocksNum - // TODO: remove - broadcast signature right away - // static constexpr uint16_t kBlsSigBroadcastDelayBlocks = 5; - // How often to check if node has 2t+1 bls signature for the latest pillar block & potentially trigger syncing - // TODO: validation: kCheckLatestBlockBlsSigs should be way smaller than kEpochBlocksNum and bigger than - // kBlsSigBroadcastDelayBlocks + // TODO: validation: kCheckLatestBlockBlsSigs should be way smaller than kEpochBlocksNum static constexpr uint16_t kCheckLatestBlockBlsSigs = 25; LOG_OBJECTS_DEFINE 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 513fe2f0e5..166499cedb 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 @@ -22,7 +22,7 @@ PillarChainManager::PillarChainManager(std::shared_ptr db, node_addr_(node_addr), kBlsSecretKey(bls_secret_key), last_pillar_block_{nullptr}, - last_pillar_block_signatures_{}, + bls_signatures_{}, mutex_{} { libBLS::ThresholdUtils::initCurve(); @@ -43,23 +43,13 @@ void PillarChainManager::createPillarBlock(const std::shared_ptr(block_num, block_data->final_chain_blk->state_root, std::move(stakes_changes), last_pillar_block_->getHash()); - - // Get 2t+1 threshold - // Note: do not use signature->getPeriod() - 1 as in votes processing - signature are made after the block is - // finalized, not before as votes - const auto two_t_plus_one = vote_mgr_->getPbftTwoTPlusOne(block_num, PbftVoteTypes::cert_vote); - // getPbftTwoTPlusOne returns empty optional only when requested period is too far ahead and that should never - // happen as newFinalBlock is triggered only after the block is finalized - assert(two_t_plus_one.has_value()); - { std::scoped_lock lock(mutex_); last_pillar_block_ = pillar_block; - last_pillar_block_signatures_.clear(); - last_pillar_block_signatures_weight_ = 0; - if (two_t_plus_one.has_value()) [[likely]] { - last_pillar_block_two_t_plus_one_ = *two_t_plus_one; - } + // Erase bls signatures for previous pillar block + std::erase_if(bls_signatures_, [new_pillar_block_period = pillar_block->getPeriod()](const auto& item) { + return item.first != new_pillar_block_period; + }); } // Create and broadcast own bls signature @@ -71,6 +61,7 @@ void PillarChainManager::createPillarBlock(const std::shared_ptr signature; - { - // TODO: pillar_block can be used instead of last_pillar_block_ -> no lock needed ? - std::shared_lock lock(mutex_); - signature = std::make_shared(last_pillar_block_->getHash(), block_num, node_addr_, kBlsSecretKey); - } + auto signature = std::make_shared(pillar_block->getHash(), block_num, node_addr_, kBlsSecretKey); // Broadcasts bls signature - if (addVerifiedBlsSig(signature)) { + if (validateBlsSignature(signature) && addVerifiedBlsSig(signature)) { if (auto net = network_.lock()) { net->gossipBlsSignature(signature); } @@ -103,7 +88,7 @@ void PillarChainManager::checkTwoTPlusOneBlsSignatures(EthBlockNumber block_num) return; } - PillarBlock::Hash last_pillar_block_hash; + std::shared_ptr last_pillar_block{nullptr}; { std::shared_lock lock(mutex_); @@ -113,38 +98,98 @@ void PillarChainManager::checkTwoTPlusOneBlsSignatures(EthBlockNumber block_num) } // Check 2t+1 signatures - if (last_pillar_block_signatures_weight_ >= last_pillar_block_two_t_plus_one_) { + const auto period_signatures = bls_signatures_.find(last_pillar_block_->getPeriod()); + if (period_signatures == bls_signatures_.end()) [[unlikely]] { + return; + } + + const auto pillar_block_signatures = + period_signatures->second.pillar_block_signatures.find(last_pillar_block_->getHash()); + if (pillar_block_signatures == period_signatures->second.pillar_block_signatures.end()) [[unlikely]] { + return; + } + + if (pillar_block_signatures->second.weight >= period_signatures->second.two_t_plus_one) { // There is >= 2t+1 bls signatures return; } - last_pillar_block_hash = last_pillar_block_->getHash(); + last_pillar_block = last_pillar_block_; } // There is < 2t+1 bls signatures, request it if (auto net = network_.lock()) { - net->requestBlsSigBundle(last_pillar_block_hash); + net->requestBlsSigBundle(last_pillar_block->getPeriod(), last_pillar_block->getHash()); } } bool PillarChainManager::isRelevantBlsSig(const std::shared_ptr signature) const { std::shared_lock lock(mutex_); - if (last_pillar_block_->getHash() != signature->getPillarBlockHash()) { + const auto signature_period = signature->getPeriod(); + // TODO: last_pillar_block_ might be empty + if (signature_period == last_pillar_block_->getPeriod()) { + if (signature->getPillarBlockHash() != last_pillar_block_->getHash()) { + LOG(log_er_) << "Received signature's block hash " << signature->getPillarBlockHash() + << " != last pillar block hash " << last_pillar_block_->getHash(); + return false; + } + } else if (signature_period != last_pillar_block_->getPeriod() + kEpochBlocksNum /* +1 future pillar block */) { + LOG(log_er_) << "Received signature's period " << signature_period << ", last pillar block period " + << last_pillar_block_->getPeriod(); return false; } - if (last_pillar_block_signatures_.contains(signature->getHash())) { + const auto found_period_signatures = bls_signatures_.find(signature_period); + if (found_period_signatures == bls_signatures_.end()) { + return true; + } + + const auto found_pillar_block_signatures = + found_period_signatures->second.pillar_block_signatures.find(signature->getPillarBlockHash()); + if (found_pillar_block_signatures == found_period_signatures->second.pillar_block_signatures.end()) { + return true; + } + + if (found_pillar_block_signatures->second.signatures.contains(signature->getHash())) { return false; } return true; } +bool PillarChainManager::isUniqueBlsSig(const std::shared_ptr signature) const { + std::shared_lock lock(mutex_); + + const auto found_period_signatures = bls_signatures_.find(signature->getPeriod()); + if (found_period_signatures == bls_signatures_.end()) { + return true; + } + + const auto found_signer = found_period_signatures->second.unique_signers.find(signature->getSignerAddr()); + if (found_signer == found_period_signatures->second.unique_signers.end()) { + return true; + } + + if (found_signer->second == signature->getHash()) { + return true; + } + + LOG(log_er_) << "Non unique bls sig: " << signature->getHash() << ". Existing bls signature " << found_signer->second + << " for period " << signature->getPeriod() << " and signer " << signature->getSignerAddr(); + return false; +} + bool PillarChainManager::validateBlsSignature(const std::shared_ptr signature) const { const auto sig_period = signature->getPeriod(); const auto sig_author = signature->getSignerAddr(); + // Check if signature is unique per period & validator (signer) + if (!isUniqueBlsSig(signature)) { + LOG(log_er_) << "Bls Signature " << signature->getHash() << " is not unique per period & validator"; + return false; + } + // Check if signer registered his bls key const auto bls_pub_key = key_manager_->getBlsKey(sig_period, sig_author); if (!bls_pub_key) { @@ -195,20 +240,48 @@ bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& { std::scoped_lock lock(mutex_); - if (!last_pillar_block_signatures_.emplace(std::make_pair(signature->getHash(), signature)).second) { + + auto period_signatures = bls_signatures_.find(signature->getPeriod()); + if (period_signatures == bls_signatures_.end()) { + // Get 2t+1 threshold + // Note: do not use signature->getPeriod() - 1 as in votes processing - signature are made after the block is + // finalized, not before as votes + const auto two_t_plus_one = vote_mgr_->getPbftTwoTPlusOne(signature->getPeriod(), PbftVoteTypes::cert_vote); + // getPbftTwoTPlusOne returns empty optional only when requested period is too far ahead and that should never + // happen as this exception is caught above when calling dpos_eligible_vote_count + assert(two_t_plus_one.has_value()); + + period_signatures = + bls_signatures_.insert({signature->getPeriod(), BlsSignatures{.two_t_plus_one = *two_t_plus_one}}).first; + } + + auto pillar_block_signatures = + period_signatures->second.pillar_block_signatures.insert({signature->getPillarBlockHash(), {}}).first; + + if (!pillar_block_signatures->second.signatures.emplace(signature->getHash(), signature).second) { // Signature is already saved return true; } - if ((last_pillar_block_signatures_weight_ += signer_vote_count) < last_pillar_block_two_t_plus_one_) { + pillar_block_signatures->second.weight += signer_vote_count; + + const auto unique_signer = + period_signatures->second.unique_signers.emplace(signature->getSignerAddr(), signature->getHash()); + if (!unique_signer.second) { + LOG(log_er_) << "Signer's " << signature->getSignerAddr() << " existing signature " << unique_signer.first->second + << ", new signature " << signature->getHash() << " for period " << signature->getPeriod(); + assert(false); + } + + if (pillar_block_signatures->second.weight < period_signatures->second.two_t_plus_one) { // Signatures weight < 2t+1 return true; } - pillar_block_hash = last_pillar_block_signatures_.begin()->second->getPillarBlockHash(); + pillar_block_hash = signature->getPillarBlockHash(); - signers_addresses_rlp.appendList(last_pillar_block_signatures_.size()); - for (const auto& bls_sig : last_pillar_block_signatures_) { + signers_addresses_rlp.appendList(pillar_block_signatures->second.signatures.size()); + for (const auto& bls_sig : pillar_block_signatures->second.signatures) { signers_addresses_rlp << bls_sig.second->getSignerAddr(); bls_signatures.push_back(bls_sig.second->getSignature()); } @@ -231,15 +304,22 @@ bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& } std::vector> PillarChainManager::getVerifiedBlsSignatures( - const PillarBlock::Hash pillar_block_hash) const { + PbftPeriod period, const PillarBlock::Hash pillar_block_hash) const { std::shared_lock lock(mutex_); - if (pillar_block_hash != last_pillar_block_->getHash()) { + const auto found_period_signatures = bls_signatures_.find(period); + if (found_period_signatures == bls_signatures_.end()) { + return {}; + } + + const auto found_pillar_block_signatures = + found_period_signatures->second.pillar_block_signatures.find(pillar_block_hash); + if (found_pillar_block_signatures == found_period_signatures->second.pillar_block_signatures.end()) { return {}; } std::vector> signatures; - signatures.reserve(last_pillar_block_signatures_.size()); - for (const auto& sig : last_pillar_block_signatures_) { + signatures.reserve(found_pillar_block_signatures->second.signatures.size()); + for (const auto& sig : found_pillar_block_signatures->second.signatures) { signatures.push_back(sig.second); } diff --git a/libraries/core_libs/network/include/network/network.hpp b/libraries/core_libs/network/include/network/network.hpp index a75f57baac..c4d4f6864e 100644 --- a/libraries/core_libs/network/include/network/network.hpp +++ b/libraries/core_libs/network/include/network/network.hpp @@ -71,9 +71,10 @@ class Network { /** * @brief Request bls signatures bundle packet from random peer * + * @param period * @param pillar_block_hash */ - void requestBlsSigBundle(const PillarBlock::Hash &pillar_block_hash); + void requestBlsSigBundle(PbftPeriod period, const PillarBlock::Hash &pillar_block_hash); // METHODS USED IN TESTS ONLY template diff --git a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp index 71df6ddac8..4a77f489c2 100644 --- a/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp +++ b/libraries/core_libs/network/include/network/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.hpp @@ -13,7 +13,8 @@ class GetBlsSigsBundlePacketHandler : public PacketHandler { std::shared_ptr pillar_chain_manager, const addr_t& node_addr, const std::string& logs_prefix); - void requestBlsSigsBundle(const PillarBlock::Hash& pillar_block_hash, const std::shared_ptr& peer); + void requestBlsSigsBundle(PbftPeriod period, const PillarBlock::Hash& pillar_block_hash, + const std::shared_ptr& peer); // Packet type that is processed by this handler static constexpr SubprotocolPacketType kPacketType_ = SubprotocolPacketType::GetBlsSigsBundlePacket; diff --git a/libraries/core_libs/network/src/network.cpp b/libraries/core_libs/network/src/network.cpp index afb5cd8f51..4cf49b77a9 100644 --- a/libraries/core_libs/network/src/network.cpp +++ b/libraries/core_libs/network/src/network.cpp @@ -340,7 +340,7 @@ std::shared_ptr Network::getMaxChainPeer() const { return max_chain_peer; } -void Network::requestBlsSigBundle(const PillarBlock::Hash &pillar_block_hash) { +void Network::requestBlsSigBundle(PbftPeriod period, const PillarBlock::Hash &pillar_block_hash) { for (const auto &tarcap : tarcaps_) { // Try to get most up-to-date peer const auto peer = @@ -352,7 +352,7 @@ void Network::requestBlsSigBundle(const PillarBlock::Hash &pillar_block_hash) { // TODO: is it good enough to request it just from 1 peer without knowing if he has all of the signatures ? tarcap.second->getSpecificHandler()->requestBlsSigsBundle( - pillar_block_hash, peer); + period, pillar_block_hash, peer); } } diff --git a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp index 0797fba6e5..dcbee79b07 100644 --- a/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp +++ b/libraries/core_libs/network/src/tarcap/packets_handlers/latest/get_bls_sigs_bundle_packet_handler.cpp @@ -21,12 +21,12 @@ void GetBlsSigsBundlePacketHandler::validatePacketRlpFormat( void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet_data, const std::shared_ptr &peer) { - // TODO: use without [0] ? - const PillarBlock::Hash pillar_block_hash = packet_data.rlp_[0].toHash(); + const PbftPeriod period = packet_data.rlp_[0].toInt(); + const PillarBlock::Hash pillar_block_hash = packet_data.rlp_[1].toHash(); - const auto signatures = pillar_chain_manager_->getVerifiedBlsSignatures(pillar_block_hash); + const auto signatures = pillar_chain_manager_->getVerifiedBlsSignatures(period, pillar_block_hash); if (signatures.empty()) { - LOG(log_dg_) << "No BLS signatures for " << pillar_block_hash; + LOG(log_dg_) << "No BLS signatures for period " << period << "and pillar block hash " << pillar_block_hash; return; } @@ -45,14 +45,15 @@ void GetBlsSigsBundlePacketHandler::process(const threadpool::PacketData &packet } } -void GetBlsSigsBundlePacketHandler::requestBlsSigsBundle(const PillarBlock::Hash &pillar_block_hash, +void GetBlsSigsBundlePacketHandler::requestBlsSigsBundle(PbftPeriod period, const PillarBlock::Hash &pillar_block_hash, const std::shared_ptr &peer) { - dev::RLPStream s(1); + dev::RLPStream s(2); + s << period; s << pillar_block_hash; sealAndSend(peer->getId(), SubprotocolPacketType::GetBlsSigsBundlePacket, std::move(s)); - LOG(log_dg_) << "Requested BLS signatures bundle for pillar block " << pillar_block_hash << " from peer " - << peer->getId(); + LOG(log_dg_) << "Requested BLS signatures bundle for period " << period << " and pillar block " << pillar_block_hash + << " from peer " << peer->getId(); } } // namespace taraxa::network::tarcap diff --git a/tests/test_util/src/test_util.cpp b/tests/test_util/src/test_util.cpp index 6d6c82b65c..3e6150e67e 100644 --- a/tests/test_util/src/test_util.cpp +++ b/tests/test_util/src/test_util.cpp @@ -211,7 +211,7 @@ NodesTest::NodesTest() { taraxa::NodeConfig{"7b1fcf0ec1078320117b96e9e9ad9032c06d030cf4024a598347a4623a14a421d4f030cf25ef368ab394a45e9" "20e14b57a259a09c41767dd50d1da27b627412a", "127.0.0.1", 10003}); - cfg.genesis.state.hardforks.ficus_hf_block_num = 0; + cfg.genesis.state.hardforks.ficus_hf.block_num = 0; node_cfgs.emplace_back(cfg); } node_cfgs.front().node_secret = dev::Secret("3800b2875669d9b2053c1aff9224ecfdc411423aac5b5a73d7a45ced1c3b9dcd"); @@ -272,7 +272,7 @@ std::vector NodesTest::make_node_cfgs(size_t total_count } std::optional bls_key; - if (cfg.genesis.state.hardforks.ficus_hf_block_num == 0) { + if (cfg.genesis.state.hardforks.ficus_hf.block_num == 0) { bls_key = getBlsPublicKey(cfg.bls_secret); } From b011a6b4c2111b354e13c4e75fdde42669b46232 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Wed, 29 Nov 2023 17:32:27 -0800 Subject: [PATCH 19/20] save pillar block & bls signature into db --- libraries/config/include/config/hardfork.hpp | 12 ++- libraries/config/src/hardfork.cpp | 8 +- .../include/pillar_chain/bls_signature.hpp | 7 ++ .../include/pillar_chain/pillar_block.hpp | 19 ++-- .../pillar_chain/pillar_chain_manager.hpp | 18 ++-- .../src/pillar_chain/bls_signature.cpp | 11 ++ .../src/pillar_chain/pillar_block.cpp | 26 ++++- .../src/pillar_chain/pillar_chain_manager.cpp | 101 ++++++++---------- libraries/core_libs/node/src/node.cpp | 11 +- .../storage/include/storage/storage.hpp | 16 +++ libraries/core_libs/storage/src/storage.cpp | 63 +++++++++++ tests/full_node_test.cpp | 2 +- tests/rewards_stats_test.cpp | 3 +- 13 files changed, 204 insertions(+), 93 deletions(-) diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp index fbe7cde7e7..e04d468ff2 100644 --- a/libraries/config/include/config/hardfork.hpp +++ b/libraries/config/include/config/hardfork.hpp @@ -23,14 +23,16 @@ struct MagnoliaHardfork { Json::Value enc_json(const MagnoliaHardfork& obj); void dec_json(const Json::Value& json, MagnoliaHardfork& obj); -struct FicusHardfork { +struct FicusHardforkConfig { uint64_t block_num = -1; - uint64_t pillar_block_periods = 0; // number of blocks + uint64_t pillar_block_periods{100}; // number of blocks - how often is the new pillar block created + uint64_t signatures_check_periods{ + 25}; // number of blocks - how often is 2t+1 bls signatures for latest pillar block checked HAS_RLP_FIELDS }; -Json::Value enc_json(const FicusHardfork& obj); -void dec_json(const Json::Value& json, FicusHardfork& obj); +Json::Value enc_json(const FicusHardforkConfig& obj); +void dec_json(const Json::Value& json, FicusHardforkConfig& obj); struct HardforksConfig { // disable it by default (set to max uint64) @@ -60,7 +62,7 @@ struct HardforksConfig { MagnoliaHardfork magnolia_hf; // Ficus hardfork: implementation of pillar block & bls signatures required for bridge - FicusHardfork ficus_hf; + FicusHardforkConfig ficus_hf; HAS_RLP_FIELDS }; diff --git a/libraries/config/src/hardfork.cpp b/libraries/config/src/hardfork.cpp index e55f6829ec..445ae426a6 100644 --- a/libraries/config/src/hardfork.cpp +++ b/libraries/config/src/hardfork.cpp @@ -29,18 +29,20 @@ void dec_json(const Json::Value& json, MagnoliaHardfork& obj) { } RLP_FIELDS_DEFINE(MagnoliaHardfork, block_num, jail_time) -Json::Value enc_json(const FicusHardfork& obj) { +Json::Value enc_json(const FicusHardforkConfig& obj) { Json::Value json(Json::objectValue); json["block_num"] = dev::toJS(obj.block_num); json["pillar_block_periods"] = dev::toJS(obj.pillar_block_periods); + json["signatures_check_periods"] = dev::toJS(obj.signatures_check_periods); return json; } -void dec_json(const Json::Value& json, FicusHardfork& obj) { +void dec_json(const Json::Value& json, FicusHardforkConfig& obj) { obj.block_num = json["block_num"].isUInt64() ? dev::getUInt(json["block_num"]) : uint64_t(-1); obj.pillar_block_periods = dev::getUInt(json["pillar_block_periods"]); + obj.signatures_check_periods = dev::getUInt(json["signatures_check_periods"]); } -RLP_FIELDS_DEFINE(FicusHardfork, block_num, pillar_block_periods) +RLP_FIELDS_DEFINE(FicusHardforkConfig, block_num, pillar_block_periods, signatures_check_periods) Json::Value enc_json(const HardforksConfig& obj) { Json::Value json(Json::objectValue); diff --git a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp index baf78aa9b2..48716313ec 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/bls_signature.hpp @@ -42,6 +42,13 @@ class BlsSignature { */ dev::bytes getRlp(bool include_sig = true) const; + /** + * @return Optimized rlp containing only signer address + signature + * + * @note It is used for saving 2t+1 bls signatures where pillar block hash & period is known + */ + dev::bytes getOptimizedRlp() const; + /** * @return bls signature hash */ 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 0dc00edb93..85b0434008 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_block.hpp @@ -1,5 +1,8 @@ #pragma once +#include + +#include "common/encoding_rlp.hpp" #include "common/types.hpp" namespace taraxa { @@ -19,13 +22,16 @@ class PillarBlock { // Validator stake change struct ValidatorStakeChange { - addr_t addr; - dev::s256 stake; // can be both positive or negative + addr_t addr_; + dev::s256 stake_; // can be both positive or negative + ValidatorStakeChange(addr_t addr, dev::s256 stake); + ValidatorStakeChange(const dev::RLP& rlp); dev::bytes getRlp() const; }; public: + PillarBlock(const dev::RLP& rlp); PillarBlock(PbftPeriod period, h256 state_root, std::vector&& validator_stakes_changes, blk_hash_t previous_pillar_block_hash); @@ -39,7 +45,6 @@ class PillarBlock { */ PbftPeriod getPeriod() const; - private: /** * @return pillar block rlp */ @@ -47,15 +52,15 @@ class PillarBlock { private: // Pillar block pbft period - const PbftPeriod period_{0}; + PbftPeriod period_{0}; // Pbft block(for period_) state root - const h256 state_root{}; + h256 state_root_{}; // Delta change of validators stakes between current and latest pillar block - const std::vector validators_stakes_changes_{}; + std::vector validators_stakes_changes_{}; - const Hash previous_pillar_block_hash_{0}; + Hash previous_pillar_block_hash_{0}; const Hash kCachedHash; }; diff --git a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp index bbd2903dcc..0579255424 100644 --- a/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp +++ b/libraries/core_libs/consensus/include/pillar_chain/pillar_chain_manager.hpp @@ -43,9 +43,10 @@ class PillarChainManager { }; public: - PillarChainManager(std::shared_ptr db, std::shared_ptr final_chain, - std::shared_ptr vote_mgr, std::shared_ptr key_manager, - const libff::alt_bn128_Fr& bls_secret_key, addr_t node_addr); + PillarChainManager(const FicusHardforkConfig& ficusHfConfig, std::shared_ptr db, + std::shared_ptr final_chain, std::shared_ptr vote_mgr, + std::shared_ptr key_manager, const libff::alt_bn128_Fr& bls_secret_key, + addr_t node_addr); /** * @Process Creates new pillar block and broadcasts bls signature @@ -121,6 +122,9 @@ class PillarChainManager { std::vector getOrderedValidatorsStakesChanges(EthBlockNumber block) const; private: + // Node config + const FicusHardforkConfig kFicusHfConfig; + std::shared_ptr db_; std::weak_ptr network_; std::shared_ptr final_chain_; @@ -143,14 +147,6 @@ class PillarChainManager { // Protects last_pillar_block_ & bls_signatures mutable std::shared_mutex mutex_; - // How often is pillar block created - // TODO: use from config - static constexpr uint16_t kEpochBlocksNum = 100; - - // How often to check if node has 2t+1 bls signature for the latest pillar block & potentially trigger syncing - // TODO: validation: kCheckLatestBlockBlsSigs should be way smaller than kEpochBlocksNum - static constexpr uint16_t kCheckLatestBlockBlsSigs = 25; - LOG_OBJECTS_DEFINE }; diff --git a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp index 1b0e168047..62195e1211 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/bls_signature.cpp @@ -49,6 +49,17 @@ dev::bytes BlsSignature::getRlp(bool include_sig) const { return s.invalidate(); } +dev::bytes BlsSignature::getOptimizedRlp() const { + dev::RLPStream s(2); + s << signer_addr_; + + std::stringstream sig_ss; + sig_ss << signature_; + s << sig_ss.str(); + + return s.invalidate(); +} + BlsSignature::Hash BlsSignature::getHash() const { if (!cached_hash_.has_value()) { cached_hash_ = dev::sha3(getRlp(false)); 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 8cae733d6d..c0133c8255 100644 --- a/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp +++ b/libraries/core_libs/consensus/src/pillar_chain/pillar_block.cpp @@ -6,19 +6,37 @@ namespace taraxa { +PillarBlock::ValidatorStakeChange::ValidatorStakeChange(addr_t addr, dev::s256 stake) : addr_(addr), stake_(stake) {} + +PillarBlock::ValidatorStakeChange::ValidatorStakeChange(const dev::RLP& rlp) { + util::rlp_tuple(util::RLPDecoderRef(rlp, true), addr_, stake_); +} + dev::bytes PillarBlock::ValidatorStakeChange::getRlp() const { dev::RLPStream s(2); - s << addr; - s << stake; + s << addr_; + s << stake_; return s.invalidate(); } +PillarBlock::PillarBlock(const dev::RLP& rlp) { + dev::bytes stakes_changes; + util::rlp_tuple(util::RLPDecoderRef(rlp, true), period_, state_root_, previous_pillar_block_hash_, stakes_changes); + + dev::RLP stakes_changes_rlp(stakes_changes); + + validators_stakes_changes_.reserve(stakes_changes_rlp.itemCount()); + for (const auto stake_change_rlp : stakes_changes_rlp) { + validators_stakes_changes_.emplace_back(stake_change_rlp); + } +} + PillarBlock::PillarBlock(PbftPeriod period, h256 state_root, std::vector&& validator_stakes_changes, PillarBlock::Hash previous_pillar_block_hash) : period_(period), - state_root(state_root), + state_root_(state_root), validators_stakes_changes_(std::move(validator_stakes_changes)), previous_pillar_block_hash_(previous_pillar_block_hash), kCachedHash(dev::sha3(getRlp())) {} @@ -26,7 +44,7 @@ PillarBlock::PillarBlock(PbftPeriod period, h256 state_root, dev::bytes PillarBlock::getRlp() const { dev::RLPStream s(4); s << period_; - s << state_root; + s << state_root_; s << previous_pillar_block_hash_; s.appendList(validators_stakes_changes_.size()); 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 166499cedb..14fa471603 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 @@ -10,23 +10,24 @@ namespace taraxa { -PillarChainManager::PillarChainManager(std::shared_ptr db, +PillarChainManager::PillarChainManager(const FicusHardforkConfig& ficusHfConfig, std::shared_ptr db, std::shared_ptr final_chain, std::shared_ptr vote_mgr, std::shared_ptr key_manager, const libff::alt_bn128_Fr& bls_secret_key, addr_t node_addr) - : db_(std::move(db)), + : kFicusHfConfig(ficusHfConfig), + db_(std::move(db)), network_{}, final_chain_{std::move(final_chain)}, vote_mgr_(std::move(vote_mgr)), key_manager_(std::move(key_manager)), node_addr_(node_addr), kBlsSecretKey(bls_secret_key), - last_pillar_block_{nullptr}, + last_pillar_block_{db_->getLatestPillarBlock()}, bls_signatures_{}, mutex_{} { libBLS::ThresholdUtils::initCurve(); - // TODO: load last_pillar_block_ from db + // TODO: load latest own bls signature from db LOG_OBJECTS_CREATE("PILLAR_CHAIN"); } @@ -35,7 +36,7 @@ void PillarChainManager::createPillarBlock(const std::shared_ptrfinal_chain_blk->number; // There should always be last_pillar_block_, except for the very first pillar block - assert(block_num <= kEpochBlocksNum || last_pillar_block_); + assert(block_num <= kFicusHfConfig.pillar_block_periods || last_pillar_block_); // TODO: this will not work for light node // Get validators stakes changes between the current and previous pillar block @@ -52,16 +53,18 @@ void PillarChainManager::createPillarBlock(const std::shared_ptrsavePillarBlock(pillar_block); + // Create and broadcast own bls signature // TODO: do not create & gossip own sig or request other signatures if the node is in syncing state - // Check if node is eligible validator + // Check if node is an eligible validator try { if (!final_chain_->dpos_is_eligible(block_num, node_addr_)) { return; } } catch (state_api::ErrFutureBlock& e) { - // TODO: true ??? assert(false); // This should never happen as newFinalBlock is triggered after the new block is finalized return; } @@ -76,6 +79,8 @@ void PillarChainManager::createPillarBlock(const std::shared_ptrgossipBlsSignature(signature); } @@ -83,11 +88,6 @@ void PillarChainManager::createPillarBlock(const std::shared_ptr last_pillar_block{nullptr}; { std::shared_lock lock(mutex_); @@ -98,18 +98,18 @@ void PillarChainManager::checkTwoTPlusOneBlsSignatures(EthBlockNumber block_num) } // Check 2t+1 signatures - const auto period_signatures = bls_signatures_.find(last_pillar_block_->getPeriod()); - if (period_signatures == bls_signatures_.end()) [[unlikely]] { + const auto found_period_signatures = bls_signatures_.find(last_pillar_block_->getPeriod()); + if (found_period_signatures == bls_signatures_.end()) [[unlikely]] { return; } - const auto pillar_block_signatures = - period_signatures->second.pillar_block_signatures.find(last_pillar_block_->getHash()); - if (pillar_block_signatures == period_signatures->second.pillar_block_signatures.end()) [[unlikely]] { + const auto found_pillar_block_signatures = + found_period_signatures->second.pillar_block_signatures.find(last_pillar_block_->getHash()); + if (found_pillar_block_signatures == found_period_signatures->second.pillar_block_signatures.end()) [[unlikely]] { return; } - if (pillar_block_signatures->second.weight >= period_signatures->second.two_t_plus_one) { + if (found_pillar_block_signatures->second.weight >= found_period_signatures->second.two_t_plus_one) { // There is >= 2t+1 bls signatures return; } @@ -127,14 +127,20 @@ bool PillarChainManager::isRelevantBlsSig(const std::shared_ptr si std::shared_lock lock(mutex_); const auto signature_period = signature->getPeriod(); - // TODO: last_pillar_block_ might be empty - if (signature_period == last_pillar_block_->getPeriod()) { + // Empty last_pillar_block_ means there was no pillar block created yet at all + if (!last_pillar_block_ && signature_period != kFicusHfConfig.pillar_block_periods) [[unlikely]] { + LOG(log_er_) << "Received signature's period " << signature_period + << ", no pillar block created yet. Accepting signatures with " << kFicusHfConfig.pillar_block_periods + << " period"; + return false; + } else if (signature_period == last_pillar_block_->getPeriod()) { if (signature->getPillarBlockHash() != last_pillar_block_->getHash()) { LOG(log_er_) << "Received signature's block hash " << signature->getPillarBlockHash() << " != last pillar block hash " << last_pillar_block_->getHash(); return false; } - } else if (signature_period != last_pillar_block_->getPeriod() + kEpochBlocksNum /* +1 future pillar block */) { + } else if (signature_period != + last_pillar_block_->getPeriod() + kFicusHfConfig.pillar_block_periods /* +1 future pillar block */) { LOG(log_er_) << "Received signature's period " << signature_period << ", last pillar block period " << last_pillar_block_->getPeriod(); return false; @@ -234,10 +240,7 @@ bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& return false; } - std::vector bls_signatures; - dev::RLPStream signers_addresses_rlp; - PillarBlock::Hash pillar_block_hash; - + std::vector> signatures_copy; { std::scoped_lock lock(mutex_); @@ -278,27 +281,13 @@ bool PillarChainManager::addVerifiedBlsSig(const std::shared_ptr& return true; } - pillar_block_hash = signature->getPillarBlockHash(); - - signers_addresses_rlp.appendList(pillar_block_signatures->second.signatures.size()); - for (const auto& bls_sig : pillar_block_signatures->second.signatures) { - signers_addresses_rlp << bls_sig.second->getSignerAddr(); - bls_signatures.push_back(bls_sig.second->getSignature()); - } + signatures_copy.reserve(pillar_block_signatures->second.signatures.size()); + std::transform(pillar_block_signatures->second.signatures.begin(), pillar_block_signatures->second.signatures.end(), + std::back_inserter(signatures_copy), [](const auto& p) { return p.second; }); } - // Create aggregated bls signature and save it to db - libff::alt_bn128_G1 aggregated_signature = libBLS::Bls::Aggregate(bls_signatures); - - std::stringstream aggregated_signature_ss; - aggregated_signature_ss << aggregated_signature; - - dev::RLPStream bls_aggregated_sig_rlp(3); - bls_aggregated_sig_rlp << pillar_block_hash; - bls_aggregated_sig_rlp << aggregated_signature_ss.str(); - bls_aggregated_sig_rlp.appendRaw(signers_addresses_rlp.invalidate()); - - // TODO: save bls_aggregated_sig_rlp to db + // Save 2t+1 bls signatures to db + db_->saveTwoTPlusOneBlsSignatures(signatures_copy); return true; } @@ -328,7 +317,7 @@ std::vector> PillarChainManager::getVerifiedBlsSig std::vector PillarChainManager::getOrderedValidatorsStakesChanges( EthBlockNumber block) const { - assert(block % kEpochBlocksNum == 0); + assert(block % kFicusHfConfig.pillar_block_periods == 0); auto current_stakes = final_chain_->dpos_validators_total_stakes(block); @@ -336,18 +325,17 @@ std::vector PillarChainManager::getOrderedVal if (!last_pillar_block_) { std::vector changes; changes.reserve(current_stakes.size()); - std::transform(current_stakes.begin(), current_stakes.end(), std::back_inserter(changes), [](auto& stake) { - return PillarBlock::ValidatorStakeChange{stake.addr, stake.stake}; - }); + std::transform(current_stakes.begin(), current_stakes.end(), std::back_inserter(changes), + [](auto& stake) { return PillarBlock::ValidatorStakeChange(stake.addr, stake.stake); }); return changes; } - auto transformToMap = [](const std::vector& changes) { + auto transformToMapChanges = [](const std::vector& stakes) { std::map changes_map; - for (const auto& change : changes) { + for (const auto& stake : stakes) { // Convert ValidatorStake.stake uint256 to ValidatorStakeChange.stake int256 - changes_map[change.addr] = PillarBlock::ValidatorStakeChange{change.addr, change.stake}; + changes_map.emplace(stake.addr, PillarBlock::ValidatorStakeChange(stake.addr, dev::s256(stake.stake))); } return changes_map; @@ -355,8 +343,8 @@ std::vector PillarChainManager::getOrderedVal auto previous_stakes = final_chain_->dpos_validators_total_stakes(last_pillar_block_->getPeriod()); - auto current_stakes_map = transformToMap(current_stakes); - auto previous_stakes_map = transformToMap(previous_stakes); + auto current_stakes_map = transformToMapChanges(current_stakes); + auto previous_stakes_map = transformToMapChanges(previous_stakes); // First create ordered map so the changes are ordered by validator addresses std::map changes_map; @@ -370,8 +358,9 @@ std::vector PillarChainManager::getOrderedVal } // Previous stakes contains validator address from current stakes -> substitute the stakes - changes_map[current_stake.first] = PillarBlock::ValidatorStakeChange{ - current_stake.first, current_stake.second.stake - previous_stake->second.stake}; + changes_map.emplace(current_stake.first, + PillarBlock::ValidatorStakeChange(current_stake.first, + current_stake.second.stake_ - previous_stake->second.stake_)); // Delete item from previous_stakes - based on left stakes we know which delegators undelegated all tokens previous_stakes_map.erase(previous_stake); @@ -380,7 +369,7 @@ std::vector PillarChainManager::getOrderedVal // All previous stakes that were not deleted are delegators who undelegated all of their tokens between current and // previous pillar block. Add these stakes as negative numbers into changes for (auto& previous_stake_left : previous_stakes_map) { - previous_stake_left.second.stake *= -1; + previous_stake_left.second.stake_ *= -1; changes_map.emplace(std::move(previous_stake_left)); } diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index ee0acadd6c..72b08363c7 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -138,8 +138,8 @@ void FullNode::init() { conf_.genesis.dag.block_proposer, dag_mgr_, trx_mgr_, final_chain_, db_, key_manager_, node_addr, getSecretKey(), getVrfSecretKey(), conf_.genesis.pbft.gas_limit, conf_.genesis.dag.gas_limit, conf_.genesis.state); - pillar_chain_ = - std::make_shared(db_, final_chain_, vote_mgr_, key_manager_, conf_.bls_secret, node_addr); + pillar_chain_ = std::make_shared(conf_.genesis.state.hardforks.ficus_hf, db_, final_chain_, + vote_mgr_, key_manager_, conf_.bls_secret, node_addr); network_ = std::make_shared(conf_, genesis_hash, conf_.net_file_path().string(), kp_, db_, pbft_mgr_, pbft_chain_, vote_mgr_, dag_mgr_, trx_mgr_, std::move(slashing_manager), pillar_chain_); @@ -323,14 +323,15 @@ void FullNode::start() { subscription_pool_); final_chain_->block_finalized_.subscribe( - [pillar_block_periods = conf_.genesis.state.hardforks.ficus_hf.pillar_block_periods, + [ficus_hf_config = conf_.genesis.state.hardforks.ficus_hf, pillar_chain_weak = as_weak(pillar_chain_)](const auto &res) { if (auto pillar_chain = pillar_chain_weak.lock()) { const auto block_num = res->final_chain_blk->number; - if (block_num % pillar_block_periods == 0) { + if (block_num % ficus_hf_config.pillar_block_periods == 0) { pillar_chain->createPillarBlock(res); - } else { + } else if (block_num % ficus_hf_config.signatures_check_periods == 0) { + // TODO: could be optimized - do not checked after there is 2t+1 signatures pillar_chain->checkTwoTPlusOneBlsSignatures(block_num); } } diff --git a/libraries/core_libs/storage/include/storage/storage.hpp b/libraries/core_libs/storage/include/storage/storage.hpp index 7e66789733..8791d38318 100644 --- a/libraries/core_libs/storage/include/storage/storage.hpp +++ b/libraries/core_libs/storage/include/storage/storage.hpp @@ -14,6 +14,8 @@ #include "logger/logger.hpp" #include "pbft/pbft_block.hpp" #include "pbft/period_data.hpp" +#include "pillar_chain/bls_signature.hpp" +#include "pillar_chain/pillar_block.hpp" #include "storage/uint_comparator.hpp" #include "transaction/transaction.hpp" #include "vote_manager/verified_votes.hpp" @@ -122,6 +124,13 @@ class DbStorage : public std::enable_shared_from_this { COLUMN_W_COMP(block_rewards_stats, getIntComparator()); + // Pillar blocks + COLUMN_W_COMP(pillar_blocks, getIntComparator()); + // 2t+1 bls aggregated signature for pillar blocks + COLUMN_W_COMP(aggregated_bls_signatures, getIntComparator()); + // Latest pillar block own bls signature + COLUMN(latest_pillar_block_own_signature); + #undef COLUMN #undef COLUMN_W_COMP }; @@ -205,6 +214,13 @@ class DbStorage : public std::enable_shared_from_this { blk_hash_t getPeriodBlockHash(PbftPeriod period) const; std::optional getPeriodTransactions(PbftPeriod period) const; + void savePillarBlock(const std::shared_ptr& pillar_block); + std::shared_ptr getPillarBlock(PbftPeriod period) const; + std::shared_ptr getLatestPillarBlock() const; + void saveOwnLatestBlsSignature(const std::shared_ptr& bls_signature); + std::shared_ptr getOwnLatestBlsSignature() const; + void saveTwoTPlusOneBlsSignatures(const std::vector>& bls_signatures); + /** * @brief Gets finalized transactions from provided hashes * diff --git a/libraries/core_libs/storage/src/storage.cpp b/libraries/core_libs/storage/src/storage.cpp index 048290e626..0fd4fdcd0d 100644 --- a/libraries/core_libs/storage/src/storage.cpp +++ b/libraries/core_libs/storage/src/storage.cpp @@ -679,6 +679,69 @@ dev::bytes DbStorage::getPeriodDataRaw(PbftPeriod period) const { return asBytes(lookup(toSlice(period), Columns::period_data)); } +void DbStorage::savePillarBlock(const std::shared_ptr& pillar_block) { + dev::RLPStream s; + s.appendRaw(pillar_block->getRlp()); + + insert(Columns::pillar_blocks, toSlice(pillar_block->getPeriod()), toSlice(s.invalidate())); +} + +std::shared_ptr DbStorage::getPillarBlock(PbftPeriod period) const { + const auto bytes = asBytes(lookup(toSlice(period), Columns::pillar_blocks)); + if (bytes.empty()) { + return nullptr; + } + + return std::make_shared(dev::RLP(bytes)); +} + +std::shared_ptr DbStorage::getLatestPillarBlock() const { + level_t level = 0; + auto it = std::unique_ptr(db_->NewIterator(read_options_, handle(Columns::pillar_blocks))); + it->SeekToLast(); + if (!it->Valid()) { + return nullptr; + } + + return std::make_shared(dev::RLP(it->value().data())); +} + +// void DbStorage::saveOwnLatestBlsSignature(const std::shared_ptr& bls_signature) { +// +// } +// +// std::shared_ptr DbStorage::getOwnLatestBlsSignature() const { +// const auto bytes = asBytes(lookup(toSlice(period), Columns::latest_pillar_block_own_signature)); +// return std::make_shared(dev::RLP(bytes)); +// } + +void DbStorage::saveTwoTPlusOneBlsSignatures(const std::vector>& bls_signatures) { + assert(!bls_signatures.empty()); + + std::vector bls_signatures_g1; + dev::RLPStream signers_addresses_rlp; + + signers_addresses_rlp.appendList(bls_signatures.size()); + for (const auto& bls_sig : bls_signatures) { + signers_addresses_rlp << bls_sig->getSignerAddr(); + bls_signatures_g1.push_back(bls_sig->getSignature()); + } + + // Create aggregated bls signature and save it to db + libff::alt_bn128_G1 aggregated_signature = libBLS::Bls::Aggregate(bls_signatures_g1); + + std::stringstream aggregated_signature_ss; + aggregated_signature_ss << aggregated_signature; + + dev::RLPStream bls_aggregated_sig_rlp(3); + bls_aggregated_sig_rlp << (*bls_signatures.begin())->getPillarBlockHash(); + bls_aggregated_sig_rlp << aggregated_signature_ss.str(); + bls_aggregated_sig_rlp.appendRaw(signers_addresses_rlp.invalidate()); + + insert(Columns::aggregated_bls_signatures, toSlice((*bls_signatures.begin())->getPeriod()), + toSlice(bls_aggregated_sig_rlp.invalidate())); +} + void DbStorage::saveTransaction(Transaction const& trx) { insert(Columns::transactions, toSlice(trx.getHash().asBytes()), toSlice(trx.rlp())); } diff --git a/tests/full_node_test.cpp b/tests/full_node_test.cpp index eb8a6406af..69d0308ef9 100644 --- a/tests/full_node_test.cpp +++ b/tests/full_node_test.cpp @@ -388,7 +388,7 @@ TEST_F(FullNodeTest, sync_five_nodes) { auto node_cfgs = make_node_cfgs(5, 1, 20); for (const auto &cfg : node_cfgs) { - std::cout << "cfg.genesis.state.hardforks.ficus_hf_block_num: " << cfg.genesis.state.hardforks.ficus_hf_block_num + std::cout << "cfg.genesis.state.hardforks.ficus_hf_block_num: " << cfg.genesis.state.hardforks.ficus_hf.block_num << std::endl; std::cout << "cfg.bls_secret: " << blsSecretToStr(cfg.bls_secret) << std::endl; diff --git a/tests/rewards_stats_test.cpp b/tests/rewards_stats_test.cpp index 53daec009f..7992ed63ee 100644 --- a/tests/rewards_stats_test.cpp +++ b/tests/rewards_stats_test.cpp @@ -20,7 +20,8 @@ struct RewardsStatsTest : NodesTest {}; class TestableRewardsStats : public rewards::Stats { public: TestableRewardsStats(const HardforksConfig::RewardsDistributionMap& rdm, std::shared_ptr db) - : rewards::Stats(100, HardforksConfig{0, {}, rdm, MagnoliaHardfork{0, 0}}, db, [](auto) { return 100; }) {} + : rewards::Stats(100, HardforksConfig{0, {}, rdm, MagnoliaHardfork{0, 0}, FicusHardforkConfig{0, 0}}, db, + [](auto) { return 100; }) {} auto getStats() { return blocks_stats_; } }; From e6e4a025af9044e2aaeb4af16b5e1d23c3e3b9b0 Mon Sep 17 00:00:00 2001 From: Jakub Fornadel Date: Tue, 5 Dec 2023 11:22:34 -0800 Subject: [PATCH 20/20] fix tests and update evm --- libraries/cli/src/tools.cpp | 5 +--- .../common/include/common/encoding_rlp.hpp | 6 +--- libraries/common/include/common/util.hpp | 1 + libraries/common/src/util.cpp | 7 +++++ libraries/config/include/config/hardfork.hpp | 7 ++--- .../consensus/src/final_chain/state_api.cpp | 14 +++++----- .../src/pillar_chain/pillar_chain_manager.cpp | 12 +++++--- libraries/core_libs/node/src/node.cpp | 28 +++++++++---------- tests/final_chain_test.cpp | 22 +++++++++------ tests/rewards_stats_test.cpp | 2 +- tests/test_util/src/test_util.cpp | 10 +++++-- 11 files changed, 63 insertions(+), 51 deletions(-) diff --git a/libraries/cli/src/tools.cpp b/libraries/cli/src/tools.cpp index 3001ebc9e8..4dcc792915 100644 --- a/libraries/cli/src/tools.cpp +++ b/libraries/cli/src/tools.cpp @@ -252,10 +252,7 @@ Json::Value createWalletJson(const dev::KeyPair& account, const taraxa::vrf_wrap json["vrf_public"] = pk.toString(); json["bls_secret"] = blsSecretToStr(bls_secret); - - std::stringstream bls_pub_key_ss; - bls_pub_key_ss << bls_pub_key; - json["bls_public"] = bls_pub_key_ss.str(); + json["bls_public"] = blsPubKeyToStr(bls_pub_key); return json; } diff --git a/libraries/common/include/common/encoding_rlp.hpp b/libraries/common/include/common/encoding_rlp.hpp index 0fdfd33335..3a20191b0e 100644 --- a/libraries/common/include/common/encoding_rlp.hpp +++ b/libraries/common/include/common/encoding_rlp.hpp @@ -44,11 +44,7 @@ inline auto rlp(RLPEncoderRef encoding, T const& target) -> decltype(target.rlp( inline auto rlp(RLPEncoderRef encoding, std::string const& target) { encoding.append(target); } -inline auto rlp(RLPEncoderRef encoding, const libff::alt_bn128_G2& target) { - std::stringstream sig_ss; - sig_ss << target; - encoding.append(sig_ss.str()); -} +inline auto rlp(RLPEncoderRef encoding, const libff::alt_bn128_G2& target) { encoding.append(blsPubKeyToStr(target)); } inline auto rlp(RLPEncoderRef encoding, bytes const& target) { encoding.append(target); } diff --git a/libraries/common/include/common/util.hpp b/libraries/common/include/common/util.hpp index fccdf07734..0b80d64b0a 100644 --- a/libraries/common/include/common/util.hpp +++ b/libraries/common/include/common/util.hpp @@ -33,6 +33,7 @@ namespace taraxa { std::string jsonToUnstyledString(const Json::Value &value); libff::alt_bn128_G2 getBlsPublicKey(const libff::alt_bn128_Fr &bls_secret); +std::string blsPubKeyToStr(const libff::alt_bn128_G2 &bls_pub_key); template std::weak_ptr as_weak(std::shared_ptr sp) { diff --git a/libraries/common/src/util.cpp b/libraries/common/src/util.cpp index 5beafcfc1c..f5fd8745b3 100644 --- a/libraries/common/src/util.cpp +++ b/libraries/common/src/util.cpp @@ -15,6 +15,13 @@ libff::alt_bn128_G2 getBlsPublicKey(const libff::alt_bn128_Fr &bls_secret) { return bls_secret * libff::alt_bn128_G2::one(); } +std::string blsPubKeyToStr(const libff::alt_bn128_G2 &bls_pub_key) { + std::stringstream bls_pub_key_ss; + bls_pub_key_ss << bls_pub_key; + + return bls_pub_key_ss.str(); +} + void thisThreadSleepForSeconds(unsigned sec) { std::this_thread::sleep_for(std::chrono::seconds(sec)); } void thisThreadSleepForMilliSeconds(unsigned millisec) { diff --git a/libraries/config/include/config/hardfork.hpp b/libraries/config/include/config/hardfork.hpp index e04d468ff2..5ba7df97cf 100644 --- a/libraries/config/include/config/hardfork.hpp +++ b/libraries/config/include/config/hardfork.hpp @@ -24,10 +24,9 @@ Json::Value enc_json(const MagnoliaHardfork& obj); void dec_json(const Json::Value& json, MagnoliaHardfork& obj); struct FicusHardforkConfig { - uint64_t block_num = -1; - uint64_t pillar_block_periods{100}; // number of blocks - how often is the new pillar block created - uint64_t signatures_check_periods{ - 25}; // number of blocks - how often is 2t+1 bls signatures for latest pillar block checked + uint64_t block_num{0}; + uint64_t pillar_block_periods{100}; // [periods] how often is the new pillar block created + uint64_t signatures_check_periods{25}; // [periods] how often is 2t+1 bls signatures for latest pillar block checked HAS_RLP_FIELDS }; diff --git a/libraries/core_libs/consensus/src/final_chain/state_api.cpp b/libraries/core_libs/consensus/src/final_chain/state_api.cpp index cd829d66c6..cc16147b49 100644 --- a/libraries/core_libs/consensus/src/final_chain/state_api.cpp +++ b/libraries/core_libs/consensus/src/final_chain/state_api.cpp @@ -259,19 +259,19 @@ std::vector StateAPI::dpos_validators_total_stakes(EthBlockNumbe } libff::alt_bn128_G2 StateAPI::dpos_get_bls_key(EthBlockNumber blk_num, const addr_t& addr) const { - dev::bytes sig_bytes = + dev::bytes bls_key_bytes = c_method_args_rlp(this_c_, blk_num, addr); // TODO: will this work ??? - std::stringstream sig_ss; - for (auto it = sig_bytes.begin(); it != sig_bytes.end(); it++) { - sig_ss << *it; + std::stringstream bls_key_ss; + for (auto it = bls_key_bytes.begin(); it != bls_key_bytes.end(); it++) { + bls_key_ss << *it; } - libff::alt_bn128_G2 signature; - sig_ss >> signature; + libff::alt_bn128_G2 bls_key; + bls_key_ss >> bls_key; - return signature; + return bls_key; } } // namespace taraxa::state_api 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 14fa471603..a7493659d0 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 @@ -35,15 +35,19 @@ PillarChainManager::PillarChainManager(const FicusHardforkConfig& ficusHfConfig, void PillarChainManager::createPillarBlock(const std::shared_ptr& block_data) { const auto block_num = block_data->final_chain_blk->number; - // There should always be last_pillar_block_, except for the very first pillar block - assert(block_num <= kFicusHfConfig.pillar_block_periods || last_pillar_block_); + PillarBlock::Hash last_pillar_block_hash{}; // null block hash + if (block_num > kFicusHfConfig.pillar_block_periods) [[likely]] { // Not the first pillar block epoch + // There should always be last_pillar_block_, except for the very first pillar block + assert(last_pillar_block_); + last_pillar_block_hash = last_pillar_block_->getHash(); + } - // TODO: this will not work for light node + // TODO: this will not work for light node - save previous pillar block validators stakes in memory & db // Get validators stakes changes between the current and previous pillar block auto stakes_changes = getOrderedValidatorsStakesChanges(block_num); const auto pillar_block = std::make_shared(block_num, block_data->final_chain_blk->state_root, - std::move(stakes_changes), last_pillar_block_->getHash()); + std::move(stakes_changes), last_pillar_block_hash); { std::scoped_lock lock(mutex_); last_pillar_block_ = pillar_block; diff --git a/libraries/core_libs/node/src/node.cpp b/libraries/core_libs/node/src/node.cpp index 72b08363c7..c7bfc44b8f 100644 --- a/libraries/core_libs/node/src/node.cpp +++ b/libraries/core_libs/node/src/node.cpp @@ -322,21 +322,21 @@ void FullNode::start() { }, subscription_pool_); - final_chain_->block_finalized_.subscribe( - [ficus_hf_config = conf_.genesis.state.hardforks.ficus_hf, - pillar_chain_weak = as_weak(pillar_chain_)](const auto &res) { - if (auto pillar_chain = pillar_chain_weak.lock()) { - const auto block_num = res->final_chain_blk->number; - - if (block_num % ficus_hf_config.pillar_block_periods == 0) { - pillar_chain->createPillarBlock(res); - } else if (block_num % ficus_hf_config.signatures_check_periods == 0) { - // TODO: could be optimized - do not checked after there is 2t+1 signatures - pillar_chain->checkTwoTPlusOneBlsSignatures(block_num); + final_chain_->block_finalized_.subscribe( + [ficus_hf_config = conf_.genesis.state.hardforks.ficus_hf, + pillar_chain_weak = as_weak(pillar_chain_)](const auto &res) { + if (auto pillar_chain = pillar_chain_weak.lock()) { + const auto block_num = res->final_chain_blk->number; + + if (block_num % ficus_hf_config.pillar_block_periods == 0) { + pillar_chain->createPillarBlock(res); + } else if (block_num % ficus_hf_config.signatures_check_periods == 0) { + // TODO: could be optimized - do not checked after there is 2t+1 signatures + pillar_chain->checkTwoTPlusOneBlsSignatures(block_num); + } } - } - }, - subscription_pool_); + }, + subscription_pool_); } vote_mgr_->setNetwork(network_); diff --git a/tests/final_chain_test.cpp b/tests/final_chain_test.cpp index 942e7aafdd..eae1e00e9e 100644 --- a/tests/final_chain_test.cpp +++ b/tests/final_chain_test.cpp @@ -38,8 +38,10 @@ struct FinalChainTest : WithDataDir { cfg.genesis.state.initial_balances[validator_owner_keys.address()] = 10 * cfg.genesis.state.dpos.validator_maximum_stake; for (const auto& keys : {dag_proposer_keys, pbft_proposer_keys}) { - const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - state_api::ValidatorInfo validator{keys.address(), validator_owner_keys.address(), vrf_key, {}, 0, "", "", {}}; + const auto vrf_pub_key = taraxa::vrf_wrapper::getVrfKeyPair().first; + const auto bls_puk_key = libBLS::Bls::KeyGeneration().second; + state_api::ValidatorInfo validator{ + keys.address(), validator_owner_keys.address(), vrf_pub_key, bls_puk_key, 0, "", "", {}}; validator.delegations.emplace(validator_owner_keys.address(), cfg.genesis.state.dpos.validator_maximum_stake); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); } @@ -296,8 +298,9 @@ TEST_F(FinalChainTest, initial_validators) { fillConfigForGenesisTests(key.address()); for (const auto& vk : validator_keys) { - const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_key, {}, 0, "", "", {}}; + const auto vrf_pub_key = taraxa::vrf_wrapper::getVrfKeyPair().first; + const auto bls_puk_key = libBLS::Bls::KeyGeneration().second; + state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_pub_key, bls_puk_key, 0, "", "", {}}; validator.delegations.emplace(key.address(), cfg.genesis.state.dpos.validator_maximum_stake); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); } @@ -821,8 +824,9 @@ TEST_F(FinalChainTest, remove_jailed_validator_votes_from_total) { cfg.genesis.state.hardforks.magnolia_hf.jail_time = 50; for (const auto& vk : validator_keys) { - const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_key, {}, 0, "", "", {}}; + const auto vrf_pub_key = taraxa::vrf_wrapper::getVrfKeyPair().first; + const auto bls_puk_key = libBLS::Bls::KeyGeneration().second; + state_api::ValidatorInfo validator{vk.address(), key.address(), vrf_pub_key, bls_puk_key, 0, "", "", {}}; validator.delegations.emplace(key.address(), cfg.genesis.state.dpos.validator_maximum_stake); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); } @@ -859,11 +863,11 @@ TEST_F(FinalChainTest, remove_jailed_validator_votes_from_total) { TEST_F(FinalChainTest, initial_validator_exceed_maximum_stake) { const dev::KeyPair key = dev::KeyPair::create(); const dev::KeyPair validator_key = dev::KeyPair::create(); - const auto [vrf_key, _] = taraxa::vrf_wrapper::getVrfKeyPair(); - const auto bls_pub_key = libBLS::Bls::KeyGeneration().second; + const auto vrf_pub_key = taraxa::vrf_wrapper::getVrfKeyPair().first; + const auto bls_puk_key = libBLS::Bls::KeyGeneration().second; fillConfigForGenesisTests(key.address()); - state_api::ValidatorInfo validator{validator_key.address(), key.address(), vrf_key, bls_pub_key, 0, "", "", {}}; + state_api::ValidatorInfo validator{validator_key.address(), key.address(), vrf_pub_key, bls_puk_key, 0, "", "", {}}; validator.delegations.emplace(key.address(), cfg.genesis.state.dpos.validator_maximum_stake); validator.delegations.emplace(validator_key.address(), cfg.genesis.state.dpos.minimum_deposit); cfg.genesis.state.dpos.initial_validators.emplace_back(validator); diff --git a/tests/rewards_stats_test.cpp b/tests/rewards_stats_test.cpp index 7992ed63ee..7b14de7125 100644 --- a/tests/rewards_stats_test.cpp +++ b/tests/rewards_stats_test.cpp @@ -20,7 +20,7 @@ struct RewardsStatsTest : NodesTest {}; class TestableRewardsStats : public rewards::Stats { public: TestableRewardsStats(const HardforksConfig::RewardsDistributionMap& rdm, std::shared_ptr db) - : rewards::Stats(100, HardforksConfig{0, {}, rdm, MagnoliaHardfork{0, 0}, FicusHardforkConfig{0, 0}}, db, + : rewards::Stats(100, HardforksConfig{0, {}, rdm, MagnoliaHardfork{0, 0}, FicusHardforkConfig{}}, db, [](auto) { return 100; }) {} auto getStats() { return blocks_stats_; } }; diff --git a/tests/test_util/src/test_util.cpp b/tests/test_util/src/test_util.cpp index 3e6150e67e..ef55a7e6ab 100644 --- a/tests/test_util/src/test_util.cpp +++ b/tests/test_util/src/test_util.cpp @@ -73,10 +73,14 @@ SharedTransaction make_dpos_trx(const FullNodeConfig& sender_node_cfg, const u25 auto proof = dev::sign(sender_node_cfg.node_secret, dev::sha3(addr)).asBytes(); // We need this for eth compatibility proof[64] += 27; + + const auto vrf_pub_key = vrf_wrapper::getVrfPublicKey(sender_node_cfg.vrf_secret); + const auto bls_pub_key = getBlsPublicKey(sender_node_cfg.bls_secret); + const auto input = final_chain::ContractInterface::packFunctionCall( - "registerValidator(address,bytes,bytes,uint16,string,string)", addr, proof, - vrf_wrapper::getVrfPublicKey(sender_node_cfg.vrf_secret).asBytes(), 10, dev::asBytes("test"), - dev::asBytes("test")); + "registerValidator(address,bytes,bytes,bytes,uint16,string,string)", addr, proof, vrf_pub_key.asBytes(), + dev::asBytes(blsPubKeyToStr(bls_pub_key)), 10, dev::asBytes("test"), dev::asBytes("test")); + return std::make_shared(nonce, value, gas_price, TEST_TX_GAS_LIMIT, std::move(input), sender_node_cfg.node_secret, kContractAddress, sender_node_cfg.genesis.chain_id); }