From 16a45660911a53020d7f0ab0536101c901e6d721 Mon Sep 17 00:00:00 2001 From: ton Date: Sat, 11 Apr 2020 18:08:57 +0400 Subject: [PATCH] validator bugfix + old key blocks download improvement --- crypto/block/transaction.h | 6 - tl/generate/scheme/ton_api.tl | 6 + tl/generate/scheme/ton_api.tlo | Bin 60752 -> 61524 bytes validator/full-node-master.cpp | 65 ++++++++ validator/full-node-master.hpp | 6 + validator/full-node-shard.cpp | 69 ++++++++- validator/full-node-shard.hpp | 8 +- validator/impl/collator-impl.h | 15 +- validator/impl/collator.cpp | 212 +++++++++++++++----------- validator/impl/validate-query.cpp | 8 +- validator/net/download-proof.cpp | 32 +++- validator/net/download-proof.hpp | 3 +- validator/net/get-next-key-blocks.cpp | 6 +- 13 files changed, 315 insertions(+), 121 deletions(-) diff --git a/crypto/block/transaction.h b/crypto/block/transaction.h index e7191e07..c1cfbc54 100644 --- a/crypto/block/transaction.h +++ b/crypto/block/transaction.h @@ -151,8 +151,6 @@ struct ActionPhaseConfig { struct CreditPhase { td::RefInt256 due_fees_collected; block::CurrencyCollection credit; - // td::RefInt256 credit; - // Ref credit_extra; }; struct ComputePhase { @@ -233,8 +231,6 @@ struct Account { ton::UnixTime last_paid; vm::CellStorageStat storage_stat; block::CurrencyCollection balance; - // td::RefInt256 balance; - // Ref extra_balance; td::RefInt256 due_payment; Ref orig_total_state; // ^Account Ref total_state; // ^Account @@ -325,8 +321,6 @@ struct Transaction { Ref root; Ref new_total_state; Ref new_inner_state; - // Ref extra_balance; - // Ref msg_extra; Ref new_code, new_data, new_library; Ref in_msg, in_msg_state; Ref in_msg_body; diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 2dae941e..d85a17ef 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -401,7 +401,9 @@ tonNode.getNextBlockDescription prev_block:tonNode.blockIdExt = tonNode.BlockDes tonNode.getNextBlocksDescription prev_block:tonNode.blockIdExt limit:int = tonNode.BlocksDescription; tonNode.getPrevBlocksDescription next_block:tonNode.blockIdExt limit:int cutoff_seqno:int = tonNode.BlocksDescription; tonNode.prepareBlockProof block:tonNode.blockIdExt allow_partial:Bool = tonNode.PreparedProof; +tonNode.prepareKeyBlockProof block:tonNode.blockIdExt allow_partial:Bool = tonNode.PreparedProof; tonNode.prepareBlockProofs blocks:(vector tonNode.blockIdExt) allow_partial:Bool = tonNode.PreparedProof; +tonNode.prepareKeyBlockProofs blocks:(vector tonNode.blockIdExt) allow_partial:Bool = tonNode.PreparedProof; tonNode.prepareBlock block:tonNode.blockIdExt = tonNode.Prepared; tonNode.prepareBlocks blocks:(vector tonNode.blockIdExt) = tonNode.Prepared; tonNode.preparePersistentState block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt = tonNode.PreparedState; @@ -415,9 +417,13 @@ tonNode.downloadPersistentState block:tonNode.blockIdExt masterchain_block:tonNo tonNode.downloadPersistentStateSlice block:tonNode.blockIdExt masterchain_block:tonNode.blockIdExt offset:long max_size:long = tonNode.Data; tonNode.downloadZeroState block:tonNode.blockIdExt = tonNode.Data; tonNode.downloadBlockProof block:tonNode.blockIdExt = tonNode.Data; +tonNode.downloadKeyBlockProof block:tonNode.blockIdExt = tonNode.Data; tonNode.downloadBlockProofs blocks:(vector tonNode.blockIdExt) = tonNode.DataList; +tonNode.downloadKeyBlockProofs blocks:(vector tonNode.blockIdExt) = tonNode.DataList; tonNode.downloadBlockProofLink block:tonNode.blockIdExt = tonNode.Data; +tonNode.downloadKeyBlockProofLink block:tonNode.blockIdExt = tonNode.Data; tonNode.downloadBlockProofLinks blocks:(vector tonNode.blockIdExt) = tonNode.DataList; +tonNode.downloadKeyBlockProofLinks blocks:(vector tonNode.blockIdExt) = tonNode.DataList; tonNode.getArchiveInfo masterchain_seqno:int = tonNode.ArchiveInfo; tonNode.getArchiveSlice archive_id:long offset:long max_size:int = tonNode.Data; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index b26e1fa0424e67c6ed4124ffca7ccd4b975b6505..6c933ea27d3b929422b6d1c1113ece159f4cf9eb 100644 GIT binary patch delta 285 zcmca`i}}g}<_$W>7(+Je9=j}~WaXj!Mz$nB&o4hERWBvKJTE6dF~vKz(kUlDIXj>z zKR<2qzb9_0m$aS;DdJV;lbJVJ@qxQWKGc^IK$bx-}U9A3o`g_|B< zVb`$mF)NpWDK02VEl4a%MR6$u1H+z7&f>`nv}GncWC~1fd1<5k promise) { + if (query.block_->seqno_ == 0) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "cannot download proof for zero state")); + return; + } + auto P = td::PromiseCreator::lambda( + [allow_partial = query.allow_partial_, promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + auto x = create_serialize_tl_object(); + promise.set_value(std::move(x)); + } else if (allow_partial) { + auto x = create_serialize_tl_object(); + promise.set_value(std::move(x)); + } else { + auto x = create_serialize_tl_object(); + promise.set_value(std::move(x)); + } + }); + + if (query.allow_partial_) { + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof_link, + create_block_id(query.block_), std::move(P)); + } else { + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof, + create_block_id(query.block_), std::move(P)); + } +} + void FullNodeMasterImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlockProof &query, td::Promise promise) { auto P = td::PromiseCreator::lambda( @@ -190,6 +219,42 @@ void FullNodeMasterImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNo create_block_id(query.block_), false, std::move(P)); } +void FullNodeMasterImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProof &query, + td::Promise promise) { + if (query.block_->seqno_ == 0) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "cannot download proof for zero state")); + return; + } + auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "unknown block proof")); + } else { + promise.set_value(R.move_as_ok()); + } + }); + + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof, + create_block_id(query.block_), std::move(P)); +} + +void FullNodeMasterImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProofLink &query, + td::Promise promise) { + if (query.block_->seqno_ == 0) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "cannot download proof for zero state")); + return; + } + auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "unknown block proof")); + } else { + promise.set_value(R.move_as_ok()); + } + }); + + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof_link, + create_block_id(query.block_), std::move(P)); +} + void FullNodeMasterImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareZeroState &query, td::Promise promise) { auto P = diff --git a/validator/full-node-master.hpp b/validator/full-node-master.hpp index 9b703992..5e9d22e1 100644 --- a/validator/full-node-master.hpp +++ b/validator/full-node-master.hpp @@ -44,10 +44,16 @@ class FullNodeMasterImpl : public FullNodeMaster { td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareBlockProof &query, td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareKeyBlockProof &query, + td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlockProof &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlockProofLink &query, td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProof &query, + td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProofLink &query, + td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareBlock &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlock &query, diff --git a/validator/full-node-shard.cpp b/validator/full-node-shard.cpp index ec56e5a3..b70904fa 100644 --- a/validator/full-node-shard.cpp +++ b/validator/full-node-shard.cpp @@ -287,6 +287,35 @@ void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNod create_block_id(query.block_), false, std::move(P)); } +void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareKeyBlockProof &query, + td::Promise promise) { + if (query.block_->seqno_ == 0) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "cannot download proof for zero state")); + return; + } + auto P = td::PromiseCreator::lambda( + [allow_partial = query.allow_partial_, promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + auto x = create_serialize_tl_object(); + promise.set_value(std::move(x)); + } else if (allow_partial) { + auto x = create_serialize_tl_object(); + promise.set_value(std::move(x)); + } else { + auto x = create_serialize_tl_object(); + promise.set_value(std::move(x)); + } + }); + + if (query.allow_partial_) { + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof_link, + create_block_id(query.block_), std::move(P)); + } else { + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof, + create_block_id(query.block_), std::move(P)); + } +} + void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlockProof &query, td::Promise promise) { auto P = td::PromiseCreator::lambda( @@ -333,6 +362,42 @@ void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNod create_block_id(query.block_), false, std::move(P)); } +void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProof &query, + td::Promise promise) { + if (query.block_->seqno_ == 0) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "cannot download proof for zero state")); + return; + } + auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "unknown block proof")); + } else { + promise.set_value(R.move_as_ok()); + } + }); + + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof, + create_block_id(query.block_), std::move(P)); +} + +void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProofLink &query, + td::Promise promise) { + if (query.block_->seqno_ == 0) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "cannot download proof for zero state")); + return; + } + auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result R) mutable { + if (R.is_error()) { + promise.set_error(td::Status::Error(ErrorCode::protoviolation, "unknown block proof")); + } else { + promise.set_value(R.move_as_ok()); + } + }); + + td::actor::send_closure(validator_manager_, &ValidatorManagerInterface::get_key_block_proof_link, + create_block_id(query.block_), std::move(P)); +} + void FullNodeShardImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareZeroState &query, td::Promise promise) { auto P = @@ -639,7 +704,7 @@ void FullNodeShardImpl::download_persistent_state(BlockIdExt id, BlockIdExt mast void FullNodeShardImpl::download_block_proof(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout, td::Promise promise) { auto &b = choose_neighbour(); - td::actor::create_actor("downloadproofreq", block_id, false, adnl_id_, overlay_id_, b.adnl_id, + td::actor::create_actor("downloadproofreq", block_id, false, false, adnl_id_, overlay_id_, b.adnl_id, priority, timeout, validator_manager_, rldp_, overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise))) .release(); @@ -648,7 +713,7 @@ void FullNodeShardImpl::download_block_proof(BlockIdExt block_id, td::uint32 pri void FullNodeShardImpl::download_block_proof_link(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout, td::Promise promise) { auto &b = choose_neighbour(); - td::actor::create_actor("downloadproofreq", block_id, true, adnl_id_, overlay_id_, + td::actor::create_actor("downloadproofreq", block_id, true, false, adnl_id_, overlay_id_, adnl::AdnlNodeIdShort::zero(), priority, timeout, validator_manager_, rldp_, overlays_, adnl_, client_, create_neighbour_promise(b, std::move(promise))) .release(); diff --git a/validator/full-node-shard.hpp b/validator/full-node-shard.hpp index 854be55e..f8b5f3e3 100644 --- a/validator/full-node-shard.hpp +++ b/validator/full-node-shard.hpp @@ -64,7 +64,7 @@ class FullNodeShardImpl : public FullNodeShard { return 2; } static constexpr td::uint64 proto_capabilities() { - return 0; + return 1; } static constexpr td::uint32 max_neighbours() { return 16; @@ -94,10 +94,16 @@ class FullNodeShardImpl : public FullNodeShard { td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareBlockProof &query, td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareKeyBlockProof &query, + td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlockProof &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlockProofLink &query, td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProof &query, + td::Promise promise); + void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadKeyBlockProofLink &query, + td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_prepareBlock &query, td::Promise promise); void process_query(adnl::AdnlNodeIdShort src, ton_api::tonNode_downloadBlock &query, diff --git a/validator/impl/collator-impl.h b/validator/impl/collator-impl.h index 7af5b785..b1a7a034 100644 --- a/validator/impl/collator-impl.h +++ b/validator/impl/collator-impl.h @@ -47,9 +47,9 @@ class Collator final : public td::actor::Actor { } using LtCellRef = block::LtCellRef; using NewOutMsg = block::NewOutMsg; - const ShardIdFull shard; + const ShardIdFull shard_; ton::BlockId new_id; - bool busy{false}; + bool busy_{false}; bool before_split_{false}; bool after_split_{false}; bool after_merge_{false}; @@ -69,7 +69,7 @@ class Collator final : public td::actor::Actor { std::vector> prev_states; std::vector> prev_block_data; Ed25519_PublicKey created_by_; - Ref validator_set; + Ref validator_set_; td::actor::ActorId manager; td::Timestamp timeout; td::Promise main_promise; @@ -90,13 +90,13 @@ class Collator final : public td::actor::Actor { td::Timestamp timeout, td::Promise promise); ~Collator() override = default; bool is_busy() const { - return busy; + return busy_; } ShardId get_shard() const { - return shard.shard; + return shard_.shard; } WorkchainId workchain() const { - return shard.workchain; + return shard_.workchain; } static constexpr td::uint32 priority() { return 2; @@ -232,6 +232,7 @@ class Collator final : public td::actor::Actor { bool create_ticktock_transactions(int mask); bool create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, ton::LogicalTime req_start_lt, int mask); Ref create_ordinary_transaction(Ref msg_root); + bool check_cur_validator_set(); bool unpack_last_mc_state(); bool unpack_last_state(); bool unpack_merge_last_state(); @@ -248,7 +249,7 @@ class Collator final : public td::actor::Actor { bool request_neighbor_msg_queues(); void update_max_lt(ton::LogicalTime lt); bool is_masterchain() const { - return shard.is_masterchain(); + return shard_.is_masterchain(); } bool is_our_address(Ref addr_ref) const; bool is_our_address(ton::AccountIdPrefixFull addr_prefix) const; diff --git a/validator/impl/collator.cpp b/validator/impl/collator.cpp index 20053ada..0550d609 100644 --- a/validator/impl/collator.cpp +++ b/validator/impl/collator.cpp @@ -58,25 +58,25 @@ Collator::Collator(ShardIdFull shard, UnixTime min_ts, BlockIdExt min_masterchai std::vector prev, td::Ref validator_set, Ed25519_PublicKey collator_id, td::actor::ActorId manager, td::Timestamp timeout, td::Promise promise) - : shard(shard) + : shard_(shard) , min_ts(min_ts) , min_mc_block_id{min_masterchain_block_id} , prev_blocks(std::move(prev)) , created_by_(collator_id) - , validator_set(std::move(validator_set)) + , validator_set_(std::move(validator_set)) , manager(manager) , timeout(timeout) , main_promise(std::move(promise)) { } void Collator::start_up() { - LOG(DEBUG) << "Collator for shard " << shard.to_str() << " started"; + LOG(DEBUG) << "Collator for shard " << shard_.to_str() << " started"; LOG(DEBUG) << "Previous block #1 is " << prev_blocks.at(0).to_str(); if (prev_blocks.size() > 1) { LOG(DEBUG) << "Previous block #2 is " << prev_blocks.at(1).to_str(); } // 1. check validity of parameters, especially prev_blocks, shard and min_mc_block_id - if (shard.workchain != ton::masterchainId && shard.workchain != ton::basechainId) { + if (workchain() != ton::masterchainId && workchain() != ton::basechainId) { fatal_error(-667, "can create block candidates only for masterchain (-1) and base workchain (0)"); return; } @@ -84,16 +84,16 @@ void Collator::start_up() { fatal_error(-666, "collator is busy creating another block candidate"); return; } - if (!shard.is_valid_ext()) { + if (!shard_.is_valid_ext()) { fatal_error(-666, "requested to generate a block for an invalid shard"); return; } - td::uint64 x = td::lower_bit64(shard.shard); + td::uint64 x = td::lower_bit64(get_shard()); if (x < 8) { fatal_error(-666, "cannot split a shard more than 60 times"); return; } - if (is_masterchain() && !shard.is_masterchain_ext()) { + if (is_masterchain() && !shard_.is_masterchain_ext()) { fatal_error(-666, "sub-shards cannot exist in the masterchain"); return; } @@ -114,8 +114,8 @@ void Collator::start_up() { fatal_error(-666, "cannot merge shards in masterchain"); return; } - if (!(shard_is_parent(shard, ShardIdFull(prev_blocks[0])) && shard_is_parent(shard, ShardIdFull(prev_blocks[1])) && - prev_blocks[0].id.shard < prev_blocks[1].id.shard)) { + if (!(shard_is_parent(shard_, ShardIdFull(prev_blocks[0])) && + shard_is_parent(shard_, ShardIdFull(prev_blocks[1])) && prev_blocks[0].id.shard < prev_blocks[1].id.shard)) { fatal_error( -666, "the two previous blocks for a merge operation are not siblings or are not children of current shard"); return; @@ -127,7 +127,7 @@ void Collator::start_up() { } } after_merge_ = true; - LOG(INFO) << "AFTER_MERGE set for the new block of " << shard.to_str(); + LOG(INFO) << "AFTER_MERGE set for the new block of " << shard_.to_str(); } else { CHECK(prev_blocks.size() == 1); // creating next block @@ -135,12 +135,12 @@ void Collator::start_up() { fatal_error(-666, "previous block does not have a valid id"); return; } - if (ShardIdFull(prev_blocks[0]) != shard) { + if (ShardIdFull(prev_blocks[0]) != shard_) { after_split_ = true; - right_child_ = ton::is_right_child(shard); - LOG(INFO) << "AFTER_SPLIT set for the new block of " << shard.to_str() << " (generating " + right_child_ = ton::is_right_child(shard_); + LOG(INFO) << "AFTER_SPLIT set for the new block of " << shard_.to_str() << " (generating " << (right_child_ ? "right" : "left") << " child)"; - if (!shard_is_parent(ShardIdFull(prev_blocks[0]), shard)) { + if (!shard_is_parent(ShardIdFull(prev_blocks[0]), shard_)) { fatal_error(-666, "previous block does not belong to the shard we are generating a new block for"); return; } @@ -156,7 +156,7 @@ void Collator::start_up() { return; } } - busy = true; + busy_ = true; step = 1; if (!is_masterchain()) { // 2. learn latest masterchain state and block id @@ -198,7 +198,7 @@ void Collator::start_up() { // 4. load external messages LOG(DEBUG) << "sending get_external_messages() query to Manager"; ++pending; - td::actor::send_closure_later(manager, &ValidatorManager::get_external_messages, shard, + td::actor::send_closure_later(manager, &ValidatorManager::get_external_messages, shard_, [self = get_self()](td::Result>> res) -> void { LOG(DEBUG) << "got answer to get_external_messages() query"; td::actor::send_closure_later(std::move(self), &Collator::after_get_external_messages, @@ -248,10 +248,10 @@ std::string show_shard(const ton::ShardIdFull blk_id) { bool Collator::fatal_error(td::Status error) { error.ensure_error(); - LOG(ERROR) << "cannot generate block candidate for " << show_shard(shard) << " : " << error.to_string(); - if (busy) { + LOG(ERROR) << "cannot generate block candidate for " << show_shard(shard_) << " : " << error.to_string(); + if (busy_) { main_promise(std::move(error)); - busy = false; + busy_ = false; } stop(); return false; @@ -548,11 +548,33 @@ bool Collator::unpack_last_mc_state() { return true; } +bool Collator::check_cur_validator_set() { + CatchainSeqno cc_seqno = 0; + auto nodes = config_->compute_validator_set_cc(shard_, now_, &cc_seqno); + if (nodes.empty()) { + return fatal_error("cannot compute validator set for shard "s + shard_.to_str() + " from old masterchain state"); + } + std::vector export_nodes; + if (validator_set_.not_null()) { + if (validator_set_->get_catchain_seqno() != cc_seqno) { + return fatal_error(PSTRING() << "current validator set catchain seqno mismatch: this validator set has cc_seqno=" + << validator_set_->get_catchain_seqno() << ", only validator set with cc_seqno=" + << cc_seqno << " is entitled to create block in shardchain " << shard_.to_str()); + } + export_nodes = validator_set_->export_vector(); + } + if (export_nodes != nodes /* && !is_fake_ */) { + return fatal_error( + "current validator set mismatch: this validator set is not entitled to create block in shardchain "s + + shard_.to_str()); + } + return true; +} + bool Collator::request_neighbor_msg_queues() { assert(config_ && shard_conf_); - auto neighbor_list = shard_conf_->get_neighbor_shard_hash_ids(shard); - LOG(DEBUG) << "got a preliminary list of " << neighbor_list.size() << " neighbors for " - << block::ShardId{shard}.to_str(); + auto neighbor_list = shard_conf_->get_neighbor_shard_hash_ids(shard_); + LOG(DEBUG) << "got a preliminary list of " << neighbor_list.size() << " neighbors for " << shard_.to_str(); for (ton::BlockId blk_id : neighbor_list) { auto shard_ptr = shard_conf_->get_shard_hash(ton::ShardIdFull(blk_id)); if (shard_ptr.is_null()) { @@ -711,9 +733,9 @@ bool Collator::unpack_one_last_state(block::ShardState& ss, BlockIdExt blkid, Re } bool Collator::split_last_state(block::ShardState& ss) { - LOG(INFO) << "Splitting previous state " << ss.id_.to_str() << " to subshard " << shard.to_str(); + LOG(INFO) << "Splitting previous state " << ss.id_.to_str() << " to subshard " << shard_.to_str(); CHECK(after_split_); - auto sib_shard = ton::shard_sibling(shard); + auto sib_shard = ton::shard_sibling(shard_); auto res1 = ss.compute_split_out_msg_queue(sib_shard); if (res1.is_error()) { return fatal_error(res1.move_as_error()); @@ -724,7 +746,7 @@ bool Collator::split_last_state(block::ShardState& ss) { return fatal_error(res2.move_as_error()); } sibling_processed_upto_ = res2.move_as_ok(); - auto res3 = ss.split(shard); + auto res3 = ss.split(shard_); if (res3.is_error()) { return fatal_error(std::move(res3)); } @@ -763,10 +785,10 @@ bool Collator::add_trivial_neighbor_after_merge() { std::size_t n = neighbors_.size(); for (std::size_t i = 0; i < n; i++) { auto& nb = neighbors_.at(i); - if (ton::shard_intersects(nb.shard(), shard)) { + if (ton::shard_intersects(nb.shard(), shard_)) { ++found; - LOG(DEBUG) << "neighbor #" << i << " : " << nb.blk_.to_str() << " intersects our shard " << shard.to_str(); - if (!ton::shard_is_parent(shard, nb.shard()) || found > 2) { + LOG(DEBUG) << "neighbor #" << i << " : " << nb.blk_.to_str() << " intersects our shard " << shard_.to_str(); + if (!ton::shard_is_parent(shard_, nb.shard()) || found > 2) { return fatal_error("impossible shard configuration in add_trivial_neighbor_after_merge()"); } auto prev_shard = prev_blocks.at(found - 1).shard_full(); @@ -777,7 +799,7 @@ bool Collator::add_trivial_neighbor_after_merge() { if (found == 1) { nb.set_queue_root(out_msg_queue_->get_root_cell()); nb.processed_upto = processed_upto_; - nb.blk_.id.shard = shard.shard; + nb.blk_.id.shard = get_shard(); LOG(DEBUG) << "adjusted neighbor #" << i << " : " << nb.blk_.to_str() << " with shard expansion (immediate after-merge adjustment)"; } else { @@ -828,11 +850,11 @@ bool Collator::add_trivial_neighbor() { std::size_t n = neighbors_.size(); for (std::size_t i = 0; i < n; i++) { auto& nb = neighbors_.at(i); - if (ton::shard_intersects(nb.shard(), shard)) { + if (ton::shard_intersects(nb.shard(), shard_)) { ++found; - LOG(DEBUG) << "neighbor #" << i << " : " << nb.blk_.to_str() << " intersects our shard " << shard.to_str(); + LOG(DEBUG) << "neighbor #" << i << " : " << nb.blk_.to_str() << " intersects our shard " << shard_.to_str(); if (nb.shard() == prev_shard) { - if (prev_shard == shard) { + if (prev_shard == shard_) { // case 1. Normal. CHECK(found == 1); nb = *descr_ref; @@ -840,7 +862,7 @@ bool Collator::add_trivial_neighbor() { nb.processed_upto = processed_upto_; LOG(DEBUG) << "adjusted neighbor #" << i << " : " << nb.blk_.to_str() << " (simple replacement)"; cs = 1; - } else if (ton::shard_is_parent(nb.shard(), shard)) { + } else if (ton::shard_is_parent(nb.shard(), shard_)) { // case 2. Immediate after-split. CHECK(found == 1); CHECK(after_split_); @@ -850,20 +872,20 @@ bool Collator::add_trivial_neighbor() { auto& nb2 = neighbors_.at(i); nb2.set_queue_root(sibling_out_msg_queue_->get_root_cell()); nb2.processed_upto = sibling_processed_upto_; - nb2.blk_.id.shard = ton::shard_sibling(shard.shard); + nb2.blk_.id.shard = ton::shard_sibling(get_shard()); LOG(DEBUG) << "adjusted neighbor #" << i << " : " << nb2.blk_.to_str() << " with shard shrinking to our sibling (immediate after-split adjustment)"; auto& nb1 = neighbors_.at(n); nb1.set_queue_root(out_msg_queue_->get_root_cell()); nb1.processed_upto = processed_upto_; - nb1.blk_.id.shard = shard.shard; + nb1.blk_.id.shard = get_shard(); LOG(DEBUG) << "created neighbor #" << n << " : " << nb1.blk_.to_str() << " with shard shrinking to our (immediate after-split adjustment)"; cs = 2; } else { return fatal_error("impossible shard configuration in add_trivial_neighbor()"); } - } else if (ton::shard_is_parent(nb.shard(), shard) && shard == prev_shard) { + } else if (ton::shard_is_parent(nb.shard(), shard_) && shard_ == prev_shard) { // case 3. Continued after-split CHECK(found == 1); CHECK(!after_split_); @@ -871,14 +893,14 @@ bool Collator::add_trivial_neighbor() { CHECK(!sibling_processed_upto_); neighbors_.emplace_back(*descr_ref); auto& nb2 = neighbors_.at(i); - auto sib_shard = ton::shard_sibling(shard); + auto sib_shard = ton::shard_sibling(shard_); // compute the part of virtual sibling's OutMsgQueue with destinations in our shard sibling_out_msg_queue_ = std::make_unique(nb2.outmsg_root, 352, block::tlb::aug_OutMsgQueue); td::BitArray<96> pfx; - pfx.bits().store_int(shard.workchain, 32); - (pfx.bits() + 32).store_uint(shard.shard, 64); - int l = ton::shard_prefix_length(shard); + pfx.bits().store_int(workchain(), 32); + (pfx.bits() + 32).store_uint(get_shard(), 64); + int l = ton::shard_prefix_length(shard_); CHECK(sibling_out_msg_queue_->cut_prefix_subdict(pfx.bits(), 32 + l)); int res2 = block::filter_out_msg_queue(*sibling_out_msg_queue_, nb2.shard(), sib_shard); if (res2 < 0) { @@ -888,7 +910,7 @@ bool Collator::add_trivial_neighbor() { if (!nb2.processed_upto->split(sib_shard)) { return fatal_error("error splitting ProcessedUpto for our virtual sibling"); } - nb2.blk_.id.shard = ton::shard_sibling(shard.shard); + nb2.blk_.id.shard = ton::shard_sibling(get_shard()); LOG(DEBUG) << "adjusted neighbor #" << i << " : " << nb2.blk_.to_str() << " with shard shrinking to our sibling (continued after-split adjustment)"; auto& nb1 = neighbors_.at(n); @@ -897,7 +919,7 @@ bool Collator::add_trivial_neighbor() { LOG(DEBUG) << "created neighbor #" << n << " : " << nb1.blk_.to_str() << " from our preceding state (continued after-split adjustment)"; cs = 3; - } else if (ton::shard_is_parent(shard, nb.shard()) && shard == prev_shard) { + } else if (ton::shard_is_parent(shard_, nb.shard()) && shard_ == prev_shard) { // case 4. Continued after-merge. if (found == 1) { cs = 4; @@ -946,7 +968,7 @@ bool Collator::check_prev_block(const BlockIdExt& listed, const BlockIdExt& prev bool Collator::check_prev_block_exact(const BlockIdExt& listed, const BlockIdExt& prev) { if (listed != prev) { - return fatal_error(PSTRING() << "cannot generate shardchain block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot generate shardchain block for shard " << shard_.to_str() << " after previous block " << prev.to_str() << " because masterchain configuration expects another previous block " << listed.to_str() << " and we are immediately after a split/merge event"); @@ -982,28 +1004,28 @@ bool Collator::check_this_shard_mc_info() { << (prev_blocks.size() ? prev_blocks[0].to_str() : "(null)") << " because no shard for this workchain is declared yet"); } - auto left = config_->get_shard_hash(shard - 1, false); + auto left = config_->get_shard_hash(shard_ - 1, false); if (left.is_null()) { - return fatal_error(PSTRING() << "cannot create new block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot create new block for shard " << shard_.to_str() << " because there is no similar shard in existing masterchain configuration"); } - if (left->shard() == shard) { + if (left->shard() == shard_) { // no split/merge if (after_merge_ || after_split_) { return fatal_error( - PSTRING() << "cannot generate new shardchain block for " << shard.to_str() + PSTRING() << "cannot generate new shardchain block for " << shard_.to_str() << " after a supposed split or merge event because this event is not reflected in the masterchain"); } if (!check_prev_block(left->blk_, prev_blocks[0])) { return false; } if (left->before_split_) { - return fatal_error(PSTRING() << "cannot generate new unsplit shardchain block for " << shard.to_str() + return fatal_error(PSTRING() << "cannot generate new unsplit shardchain block for " << shard_.to_str() << " after previous block " << left->blk_.to_str() << " with before_split set"); } - auto sib = config_->get_shard_hash(shard_sibling(shard)); + auto sib = config_->get_shard_hash(shard_sibling(shard_)); if (left->before_merge_ && sib->before_merge_) { - return fatal_error(PSTRING() << "cannot generate new unmerged shardchain block for " << shard.to_str() + return fatal_error(PSTRING() << "cannot generate new unmerged shardchain block for " << shard_.to_str() << " after both " << left->blk_.to_str() << " and " << sib->blk_.to_str() << " set before_merge flags"); } @@ -1012,35 +1034,35 @@ bool Collator::check_this_shard_mc_info() { if (shard_splitting_enabled && tmp_now >= left->fsm_utime() && tmp_now + 13 < left->fsm_utime_end()) { now_upper_limit_ = left->fsm_utime_end() - 11; // ultimate value of now_ must be at most now_upper_limit_ before_split_ = true; - LOG(INFO) << "BEFORE_SPLIT set for the new block of shard " << shard.to_str(); + LOG(INFO) << "BEFORE_SPLIT set for the new block of shard " << shard_.to_str(); } } - } else if (shard_is_parent(shard, left->shard())) { + } else if (shard_is_parent(shard_, left->shard())) { // after merge if (!left->before_merge_) { - return fatal_error(PSTRING() << "cannot create new merged block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot create new merged block for shard " << shard_.to_str() << " because its left ancestor " << left->blk_.to_str() << " has no before_merge flag"); } - auto right = config_->get_shard_hash(shard + 1, false); + auto right = config_->get_shard_hash(shard_ + 1, false); if (right.is_null()) { return fatal_error( PSTRING() - << "cannot create new block for shard " << shard.to_str() + << "cannot create new block for shard " << shard_.to_str() << " after a preceding merge because there is no right ancestor shard in existing masterchain configuration"); } - if (!shard_is_parent(shard, right->shard())) { - return fatal_error(PSTRING() << "cannot create new block for shard " << shard.to_str() + if (!shard_is_parent(shard_, right->shard())) { + return fatal_error(PSTRING() << "cannot create new block for shard " << shard_.to_str() << " after a preceding merge because its right ancestor appears to be " << right->blk_.to_str()); } if (!right->before_merge_) { - return fatal_error(PSTRING() << "cannot create new merged block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot create new merged block for shard " << shard_.to_str() << " because its right ancestor " << right->blk_.to_str() << " has no before_merge flag"); } if (after_split_) { - return fatal_error(PSTRING() << "cannot create new block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot create new block for shard " << shard_.to_str() << " after a purported split because existing shard configuration suggests a merge"); } else if (after_merge_) { if (!(check_prev_block_exact(left->blk_, prev_blocks[0]) && @@ -1050,27 +1072,27 @@ bool Collator::check_this_shard_mc_info() { } else { auto cseqno = std::max(left->seqno(), right->seqno()); if (prev_blocks[0].seqno() <= cseqno) { - return fatal_error(PSTRING() << "cannot create new block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot create new block for shard " << shard_.to_str() << " after previous block " << prev_blocks[0].to_str() << " because masterchain contains newer possible ancestors " << left->blk_.to_str() << " and " << right->blk_.to_str()); } if (prev_blocks[0].seqno() >= cseqno + 8) { return fatal_error( - PSTRING() << "cannot create new block for shard " << shard.to_str() << " after previous block " + PSTRING() << "cannot create new block for shard " << shard_.to_str() << " after previous block " << prev_blocks[0].to_str() << " because this would lead to an unregistered chain of length > 8 (masterchain contains only " << left->blk_.to_str() << " and " << right->blk_.to_str() << ")"); } } - } else if (shard_is_parent(left->shard(), shard)) { + } else if (shard_is_parent(left->shard(), shard_)) { // after split if (!left->before_split_) { - return fatal_error(PSTRING() << "cannot generate new split shardchain block for " << shard.to_str() + return fatal_error(PSTRING() << "cannot generate new split shardchain block for " << shard_.to_str() << " after previous block " << left->blk_.to_str() << " without before_split"); } if (after_merge_) { - return fatal_error(PSTRING() << "cannot create new block for shard " << shard.to_str() + return fatal_error(PSTRING() << "cannot create new block for shard " << shard_.to_str() << " after a purported merge because existing shard configuration suggests a split"); } else if (after_split_) { if (!(check_prev_block_exact(left->blk_, prev_blocks[0]))) { @@ -1083,7 +1105,7 @@ bool Collator::check_this_shard_mc_info() { } } else { return fatal_error(PSTRING() << "masterchain configuration contains only block " << left->blk_.to_str() - << " which belongs to a different shard from ours " << shard.to_str()); + << " which belongs to a different shard from ours " << shard_.to_str()); } return true; } @@ -1109,7 +1131,7 @@ bool Collator::do_preinit() { last_block_seqno = prev_blocks[1].seqno(); } new_block_seqno = last_block_seqno + 1; - new_id = ton::BlockId{shard, new_block_seqno}; + new_id = ton::BlockId{shard_, new_block_seqno}; CHECK(!config_); CHECK(mc_state_root.not_null()); LOG(INFO) << "unpacking most recent masterchain state"; @@ -1123,6 +1145,9 @@ bool Collator::do_preinit() { if (!is_masterchain() && !check_this_shard_mc_info()) { return fatal_error("fatal error while checking masterchain configuration of the current shard"); } + if (!check_cur_validator_set()) { + return fatal_error("this validator set is not entitled to create a block for this shardchain"); + } CHECK(!prev_mc_block_seqno || mc_block_root.not_null()); if (!unpack_last_state()) { return fatal_error("cannot unpack previous state of current shardchain"); @@ -1642,7 +1667,7 @@ bool Collator::init_value_create() { value_flow_.minted.set_zero(); } } else if (workchain() == basechainId) { - value_flow_.created = block::CurrencyCollection{basechain_create_fee_ >> ton::shard_prefix_length(shard)}; + value_flow_.created = block::CurrencyCollection{basechain_create_fee_ >> ton::shard_prefix_length(shard_)}; } value_flow_.fees_collected += value_flow_.created; return true; @@ -1672,7 +1697,7 @@ bool Collator::do_collate() { // 1.3. create OutputQueueMerger from adjusted neighbors CHECK(!nb_out_msgs_); LOG(DEBUG) << "creating OutputQueueMerger"; - nb_out_msgs_ = std::make_unique(shard, neighbors_); + nb_out_msgs_ = std::make_unique(shard_, neighbors_); // 1.4. compute created / minted / recovered if (!init_value_create()) { return fatal_error("cannot compute the value to be created / minted / recovered"); @@ -1866,7 +1891,7 @@ std::unique_ptr Collator::make_account_from(td::ConstBitPtr addr if (account.is_null() && !force_create) { return nullptr; } - auto ptr = std::make_unique(shard.workchain, addr); + auto ptr = std::make_unique(workchain(), addr); if (account.is_null()) { ptr->created = true; if (!ptr->init_new(now_)) { @@ -1900,8 +1925,9 @@ td::Result Collator::make_account(td::ConstBitPtr addr, bool fo if (!new_acc) { return td::Status::Error(PSTRING() << "cannot load account " << addr.to_hex(256) << " from previous state"); } - if (!new_acc->belongs_to_shard(shard)) { - return td::Status::Error(PSTRING() << "account " << addr.to_hex(256) << " does not really belong to current shard"); + if (!new_acc->belongs_to_shard(shard_)) { + return td::Status::Error(PSTRING() << "account " << addr.to_hex(256) << " does not really belong to current shard " + << shard_.to_str()); } auto ins = accounts.emplace(addr, std::move(new_acc)); if (!ins.second) { @@ -1920,7 +1946,7 @@ bool Collator::combine_account_transactions() { // have transactions for this account vm::CellBuilder cb; if (!acc.create_account_block(cb)) { - return fatal_error(std::string{"cannot create AccountBlock for account "} + z.first.to_hex()); + return fatal_error("cannot create AccountBlock for account "s + z.first.to_hex()); } auto cell = cb.finalize(); auto csr = vm::load_cell_slice_ref(cell); @@ -2084,8 +2110,8 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t req_start_lt = std::max(req_start_lt, start_lt + 1); if (acc->last_trans_end_lt_ >= start_lt && acc->transactions.empty()) { return fatal_error(td::Status::Error(-666, PSTRING() - << "last transaction time in the state of account " - << shard.workchain << ":" << smc_addr.to_hex() << " is too large")); + << "last transaction time in the state of account " << workchain() + << ":" << smc_addr.to_hex() << " is too large")); } std::unique_ptr trans = std::make_unique( *acc, mask == 2 ? block::Transaction::tr_tick : block::Transaction::tr_tock, req_start_lt, now_); @@ -2154,7 +2180,7 @@ Ref Collator::create_ordinary_transaction(Ref msg_root) { return {}; } ton::WorkchainId wc; - if (!block::tlb::t_MsgAddressInt.extract_std_address(dest, wc, addr) || wc != shard.workchain) { + if (!block::tlb::t_MsgAddressInt.extract_std_address(dest, wc, addr) || wc != workchain()) { return {}; } LOG(DEBUG) << "inbound message to our smart contract " << addr.to_hex(); @@ -2166,7 +2192,7 @@ Ref Collator::create_ordinary_transaction(Ref msg_root) { block::Account* acc = acc_res.move_as_ok(); assert(acc); if (acc->last_trans_end_lt_ >= start_lt && acc->transactions.empty()) { - fatal_error(PSTRING() << "last transaction time in the state of account " << shard.workchain << ":" << addr.to_hex() + fatal_error(PSTRING() << "last transaction time in the state of account " << workchain() << ":" << addr.to_hex() << " is too large"); return {}; } @@ -2288,11 +2314,11 @@ bool Collator::is_our_address(Ref addr_ref) const { } bool Collator::is_our_address(ton::AccountIdPrefixFull addr_pfx) const { - return ton::shard_contains(shard, addr_pfx); + return ton::shard_contains(shard_, addr_pfx); } bool Collator::is_our_address(const ton::StdSmcAddress& addr) const { - return ton::shard_contains(shard.shard, addr); + return ton::shard_contains(get_shard(), addr); } // 1 = processed, 0 = enqueued, 3 = processed, all future messages must be enqueued @@ -2410,7 +2436,7 @@ bool Collator::enqueue_transit_message(Ref msg, Ref old_msg_ LOG(DEBUG) << "enqueueing transit message " << msg->get_hash().bits().to_hex(256); bool requeue = is_our_address(prev_prefix); // 1. perform hypercube routing - auto route_info = block::perform_hypercube_routing(cur_prefix, dest_prefix, shard); + auto route_info = block::perform_hypercube_routing(cur_prefix, dest_prefix, shard_); if ((unsigned)route_info.first > 96 || (unsigned)route_info.second > 96) { return fatal_error("cannot perform hypercube routing for a transit message"); } @@ -2572,7 +2598,7 @@ bool Collator::process_inbound_message(Ref enq_msg, ton::LogicalT return false; } // 5.2. next_prefix must belong to our shard - if (!ton::shard_contains(shard, next_prefix)) { + if (!ton::shard_contains(shard_, next_prefix)) { LOG(ERROR) << "inbound internal message does not have next hop address in our shard"; return false; } @@ -2594,8 +2620,8 @@ bool Collator::process_inbound_message(Ref enq_msg, ton::LogicalT } // 6. check whether we have already processed this message before using ProcessedUpTo (processed_upto) // (then silently ignore this message; NB: it can be ours after merge) - bool our = ton::shard_contains(shard, cur_prefix); - bool to_us = ton::shard_contains(shard, dest_prefix); + bool our = ton::shard_contains(shard_, cur_prefix); + bool to_us = ton::shard_contains(shard_, dest_prefix); block::EnqueuedMsgDescr enq_msg_descr{cur_prefix, next_prefix, info.created_lt, enqueued_lt, env.msg->get_hash().bits()}; @@ -2734,7 +2760,7 @@ int Collator::process_external_message(Ref msg) { // 1. create a Transaction processing this Message auto trans_root = create_ordinary_transaction(msg); if (trans_root.is_null()) { - if (busy) { + if (busy_) { // transaction rejected by account LOG(DEBUG) << "external message rejected by account, skipping"; return 0; @@ -2846,7 +2872,7 @@ bool Collator::enqueue_message(block::NewOutMsg msg, td::RefInt256 fwd_fees_rema return fatal_error("cannot enqueue a new message because its destination shard is invalid"); } // 1. perform hypercube routing - auto route_info = block::perform_hypercube_routing(src_prefix, dest_prefix, shard); + auto route_info = block::perform_hypercube_routing(src_prefix, dest_prefix, shard_); if ((unsigned)route_info.first > 96 || (unsigned)route_info.second > 96) { return fatal_error("cannot perform hypercube routing for a new outbound message"); } @@ -3155,10 +3181,10 @@ bool Collator::create_mc_state_extra() { cc_updated = true; LOG(INFO) << "increased masterchain catchain seqno to " << val_info.catchain_seqno; } - auto nodes = block::Config::do_compute_validator_set(ccvc, shard, *cur_validators, now_, val_info.catchain_seqno); + auto nodes = block::Config::do_compute_validator_set(ccvc, shard_, *cur_validators, now_, val_info.catchain_seqno); LOG_CHECK(!nodes.empty()) << "validator node list in unpacked validator set is empty"; - auto vlist_hash = block::compute_validator_set_hash(/* val_info.catchain_seqno */ 0, shard, std::move(nodes)); + auto vlist_hash = block::compute_validator_set_hash(/* val_info.catchain_seqno */ 0, shard_, std::move(nodes)); LOG(INFO) << "masterchain validator set hash changed from " << val_info.validator_list_hash_short << " to " << vlist_hash; val_info.nx_cc_updated = cc_updated & update_shard_cc; @@ -3542,7 +3568,7 @@ bool Collator::create_shard_state() { if (!(cb.store_long_bool(0x9023afe2, 32) // shard_state#9023afe2 && cb.store_long_bool(global_id_, 32) // global_id:int32 && global_id_ // { global_id != 0 } - && block::ShardId{shard}.serialize(cb) // shard_id:ShardIdent + && block::ShardId{shard_}.serialize(cb) // shard_id:ShardIdent && cb.store_long_bool(new_block_seqno, 32) // seq_no:uint32 && cb.store_long_bool(vert_seqno_, 32) // vert_seq_no:# && cb.store_long_bool(now_, 32) // gen_utime:uint32 @@ -3668,8 +3694,8 @@ bool Collator::compute_total_balance() { bool Collator::create_block_info(Ref& block_info) { vm::CellBuilder cb, cb2; bool mc = is_masterchain(); - td::uint32 val_hash = validator_set->get_validator_set_hash(); - CatchainSeqno cc_seqno = validator_set->get_catchain_seqno(); + td::uint32 val_hash = validator_set_->get_validator_set_hash(); + CatchainSeqno cc_seqno = validator_set_->get_catchain_seqno(); return cb.store_long_bool(0x9bc7a987, 32) // block_info#9bc7a987 && cb.store_long_bool(0, 32) // version:uint32 && cb.store_bool_bool(!mc) // not_master:(## 1) @@ -3682,7 +3708,7 @@ bool Collator::create_block_info(Ref& block_info) { && cb.store_long_bool((int)report_version_, 9) // vert_seqno_incr:(## 1) flags:(## 8) && cb.store_long_bool(new_block_seqno, 32) // seq_no:# && cb.store_long_bool(vert_seqno_, 32) // vert_seq_no:# - && block::ShardId{shard}.serialize(cb) // shard:ShardIdent + && block::ShardId{shard_}.serialize(cb) // shard:ShardIdent && cb.store_long_bool(now_, 32) // gen_utime:uint32 && cb.store_long_bool(start_lt, 64) // start_lt:uint64 && cb.store_long_bool(max_lt, 64) // end_lt:uint64 @@ -3891,7 +3917,7 @@ bool Collator::create_block_candidate() { // 3. create a BlockCandidate block_candidate = std::make_unique( created_by_, - ton::BlockIdExt{ton::BlockId{shard, new_block_seqno}, new_block->get_hash().bits(), + ton::BlockIdExt{ton::BlockId{shard_, new_block_seqno}, new_block->get_hash().bits(), block::compute_file_hash(blk_slice.as_slice())}, block::compute_file_hash(cdata_slice.as_slice()), blk_slice.clone(), cdata_slice.clone()); // 4. save block candidate @@ -3921,7 +3947,7 @@ void Collator::return_block_candidate(td::Result saved) { CHECK(block_candidate); LOG(INFO) << "sending new BlockCandidate to Promise"; main_promise(block_candidate->clone()); - busy = false; + busy_ = false; stop(); } } @@ -3965,7 +3991,7 @@ td::Result Collator::register_external_message_cell(Ref ext_msg, return td::Status::Error("destination of an inbound external message is an invalid blockchain address"); } // NB: previous checks are quite general and can be done at an outer level before multiplexing to correct Collator - if (!ton::shard_contains(shard, dest_prefix)) { + if (!ton::shard_contains(shard_, dest_prefix)) { return td::Status::Error("inbound external message has destination address not in this shard"); } if (verbosity > 2) { diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index e9067c73..b2f80d89 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -1737,14 +1737,20 @@ bool ValidateQuery::register_shard_block_creators(std::vector creat return true; } +// similar to Collator::check_cur_validator_set() bool ValidateQuery::check_cur_validator_set() { CatchainSeqno cc_seqno = 0; auto nodes = config_->compute_validator_set_cc(shard_, now_, &cc_seqno); if (nodes.empty()) { - return reject_query("cannot compute masterchain validator set from old masterchain state"); + return reject_query("cannot compute validator set for shard "s + shard_.to_str() + " from old masterchain state"); } std::vector export_nodes; if (validator_set_.not_null()) { + if (validator_set_->get_catchain_seqno() != cc_seqno) { + return reject_query(PSTRING() << "current validator set catchain seqno mismatch: this validator set has cc_seqno=" + << validator_set_->get_catchain_seqno() << ", only validator set with cc_seqno=" + << cc_seqno << " is entitled to create block " << id_.to_str()); + } export_nodes = validator_set_->export_vector(); } if (export_nodes != nodes /* && !is_fake_ */) { diff --git a/validator/net/download-proof.cpp b/validator/net/download-proof.cpp index dffcff9f..2ff95b88 100644 --- a/validator/net/download-proof.cpp +++ b/validator/net/download-proof.cpp @@ -30,15 +30,16 @@ namespace validator { namespace fullnode { -DownloadProof::DownloadProof(BlockIdExt block_id, bool allow_partial_proof, adnl::AdnlNodeIdShort local_id, - overlay::OverlayIdShort overlay_id, adnl::AdnlNodeIdShort download_from, - td::uint32 priority, td::Timestamp timeout, +DownloadProof::DownloadProof(BlockIdExt block_id, bool allow_partial_proof, bool is_key_block, + adnl::AdnlNodeIdShort local_id, overlay::OverlayIdShort overlay_id, + adnl::AdnlNodeIdShort download_from, td::uint32 priority, td::Timestamp timeout, td::actor::ActorId validator_manager, td::actor::ActorId rldp, td::actor::ActorId overlays, td::actor::ActorId adnl, td::actor::ActorId client, td::Promise promise) : block_id_(block_id) , allow_partial_proof_(allow_partial_proof) + , is_key_block_(is_key_block) , local_id_(local_id) , overlay_id_(overlay_id) , download_from_(download_from) @@ -155,8 +156,14 @@ void DownloadProof::got_node_to_download(adnl::AdnlNodeIdShort node) { } }); - auto query = create_serialize_tl_object(create_tl_block_id(block_id_), + td::BufferSlice query; + if (!is_key_block_) { + query = create_serialize_tl_object(create_tl_block_id(block_id_), + allow_partial_proof_); + } else { + query = create_serialize_tl_object(create_tl_block_id(block_id_), allow_partial_proof_); + } if (client_.empty()) { td::actor::send_closure(overlays_, &overlay::Overlays::send_query, download_from_, local_id_, overlay_id_, @@ -190,7 +197,12 @@ void DownloadProof::got_block_proof_description(td::BufferSlice proof_descriptio } }); - auto query = create_serialize_tl_object(create_tl_block_id(block_id_)); + td::BufferSlice query; + if (!is_key_block_) { + query = create_serialize_tl_object(create_tl_block_id(block_id_)); + } else { + query = create_serialize_tl_object(create_tl_block_id(block_id_)); + } if (client_.empty()) { td::actor::send_closure(overlays_, &overlay::Overlays::send_query_via, download_from_, local_id_, overlay_id_, "download block proof", std::move(P), td::Timestamp::in(3.0), @@ -214,8 +226,14 @@ void DownloadProof::got_block_proof_description(td::BufferSlice proof_descriptio } }); - auto query = - create_serialize_tl_object(create_tl_block_id(block_id_)); + td::BufferSlice query; + if (!is_key_block_) { + query = + create_serialize_tl_object(create_tl_block_id(block_id_)); + } else { + query = + create_serialize_tl_object(create_tl_block_id(block_id_)); + } if (client_.empty()) { td::actor::send_closure(overlays_, &overlay::Overlays::send_query_via, download_from_, local_id_, overlay_id_, "download block proof link", std::move(P), td::Timestamp::in(3.0), diff --git a/validator/net/download-proof.hpp b/validator/net/download-proof.hpp index 69bbd25e..0739dcaf 100644 --- a/validator/net/download-proof.hpp +++ b/validator/net/download-proof.hpp @@ -32,7 +32,7 @@ namespace fullnode { class DownloadProof : public td::actor::Actor { public: - DownloadProof(BlockIdExt block_id, bool allow_partial_proof, adnl::AdnlNodeIdShort local_id, + DownloadProof(BlockIdExt block_id, bool allow_partial_proof, bool is_key_block, adnl::AdnlNodeIdShort local_id, overlay::OverlayIdShort overlay_id, adnl::AdnlNodeIdShort download_from, td::uint32 priority, td::Timestamp timeout, td::actor::ActorId validator_manager, td::actor::ActorId rldp, td::actor::ActorId overlays, @@ -54,6 +54,7 @@ class DownloadProof : public td::actor::Actor { private: BlockIdExt block_id_; bool allow_partial_proof_; + bool is_key_block_; adnl::AdnlNodeIdShort local_id_; overlay::OverlayIdShort overlay_id_; diff --git a/validator/net/get-next-key-blocks.cpp b/validator/net/get-next-key-blocks.cpp index 5fe35566..3354b005 100644 --- a/validator/net/get-next-key-blocks.cpp +++ b/validator/net/get-next-key-blocks.cpp @@ -178,9 +178,9 @@ void GetNextKeyBlocks::download_next_proof() { } }); - td::actor::create_actor("downloadproofreq", block_id, false, local_id_, overlay_id_, download_from_, - priority_, timeout_, validator_manager_, rldp_, overlays_, adnl_, client_, - std::move(P)) + td::actor::create_actor("downloadproofreq", block_id, false, true, local_id_, overlay_id_, + download_from_, priority_, timeout_, validator_manager_, rldp_, overlays_, + adnl_, client_, std::move(P)) .release(); }