From 38ab70c037a49faf2db8b5a874c26163ce90cbc5 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Tue, 11 Jun 2024 11:29:52 +0300 Subject: [PATCH] Changes in validation * Configure collator list in validator-console * Remove "lite-validator" flags * Better compatibility in validate-query.cpp --- tl/generate/scheme/ton_api.tl | 9 ++ tl/generate/scheme/ton_api.tlo | Bin 96928 -> 97828 bytes .../validator-engine-console-query.cpp | 77 +++++++++++++++ .../validator-engine-console-query.h | 60 ++++++++++++ .../validator-engine-console.cpp | 3 + validator-engine/validator-engine.cpp | 87 ++++++++++++++--- validator-engine/validator-engine.hpp | 14 ++- validator/fabric.h | 2 +- validator/impl/validate-query.cpp | 20 ++-- validator/manager.cpp | 48 ++++------ validator/manager.hpp | 3 - validator/validator-group.cpp | 88 +++++++++++------- validator/validator-group.hpp | 16 +++- validator/validator-options.cpp | 16 ++++ validator/validator-options.hpp | 10 +- validator/validator.h | 22 ++++- 16 files changed, 368 insertions(+), 107 deletions(-) diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index a4956780..0d7f1249 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -626,6 +626,12 @@ engine.validator.customOverlayNode adnl_id:int256 msg_sender:Bool msg_sender_pri engine.validator.customOverlay name:string nodes:(vector engine.validator.customOverlayNode) = engine.validator.CustomOverlay; engine.validator.customOverlaysConfig overlays:(vector engine.validator.customOverlay) = engine.validator.CustomOverlaysConfig; +engine.validator.collatorsList.collator adnl_id:int256 trusted:Bool = engine.validator.collatorsList.Collator; +engine.validator.collatorsList.shard shard_id:tonNode.shardId collators:(vector engine.validator.collatorsList.collator) + = engine.validator.collatorsList.Shard; +engine.validator.collatorsList self_collate:Bool use_config_41:Bool shards:(vector engine.validator.collatorsList.shard) + = engine.validator.CollatorsList; + ---functions--- ---types--- @@ -752,6 +758,9 @@ engine.validator.addShard shard:tonNode.shardId = engine.validator.Success; engine.validator.delCollator adnl_id:int256 shard:tonNode.shardId = engine.validator.Success; engine.validator.delShard shard:tonNode.shardId = engine.validator.Success; +engine.validator.setCollatorsList list:engine.validator.collatorsList = engine.validator.Success; +engine.validator.showCollatorsList = engine.validator.CollatorsList; + ---types--- storage.pong = storage.Pong; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 9ffd9fd82766d1736b79d0a245f2275660325268..0d286bdc091a5b25e2a8deab3019aa84e0e73fe5 100644 GIT binary patch delta 587 zcmZ4Rm37G0TI4~`xT^i`UOiy9S-)A zqSE4$)Rf5umNKCrVOWS>mE(#bCLoGI0RhwmQVa4H6VzKAV2Sw5l<5ac7{w>eXPIm< zS3?411G*PLIyZN0zEjWGu|3t8v0aw6=S6X(;`EOJj3UC$$g#t~(7o)*=IM9B7-d*M t9-l5?#i+3TO#ov8Bdci80ez+EfkBL7swi4u!42{ka-eN@2x3go005-h!+`(* delta 71 zcmZ4ThjqbMR^CUm^{p77KyoARf04}|qA%Dt?~pZ-W?Z=Wt;PG~%`4{Ch;L5VcA=iJ XZM&fvW4r8jl@P`R#_bnE8ACJxv3MGm diff --git a/validator-engine-console/validator-engine-console-query.cpp b/validator-engine-console/validator-engine-console-query.cpp index 660915bb..3d22ff81 100644 --- a/validator-engine-console/validator-engine-console-query.cpp +++ b/validator-engine-console/validator-engine-console-query.cpp @@ -1316,3 +1316,80 @@ td::Status DelShardQuery::receive(td::BufferSlice data) { td::TerminalIO::out() << "successfully removed shard\n"; return td::Status::OK(); } + +td::Status SetCollatorsListQuery::run() { + TRY_RESULT_ASSIGN(file_name_, tokenizer_.get_token()); + TRY_STATUS(tokenizer_.check_endl()); + return td::Status::OK(); +} + +td::Status SetCollatorsListQuery::send() { + TRY_RESULT(data, td::read_file(file_name_)); + TRY_RESULT(json, td::json_decode(data.as_slice())); + auto list = ton::create_tl_object(); + TRY_STATUS(ton::ton_api::from_json(*list, json.get_object())); + auto b = ton::create_serialize_tl_object(std::move(list)); + td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); + return td::Status::OK(); +} + +td::Status SetCollatorsListQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX(f, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + td::TerminalIO::out() << "success\n"; + return td::Status::OK(); +} + +td::Status ClearCollatorsListQuery::run() { + TRY_STATUS(tokenizer_.check_endl()); + return td::Status::OK(); +} + +td::Status ClearCollatorsListQuery::send() { + auto list = ton::create_tl_object(); + list->self_collate_ = true; + auto b = ton::create_serialize_tl_object(std::move(list)); + td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); + return td::Status::OK(); +} + +td::Status ClearCollatorsListQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX(f, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + td::TerminalIO::out() << "success\n"; + return td::Status::OK(); +} + +td::Status ShowCollatorsListQuery::run() { + TRY_STATUS(tokenizer_.check_endl()); + return td::Status::OK(); +} + +td::Status ShowCollatorsListQuery::send() { + auto b = ton::create_serialize_tl_object(); + td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); + return td::Status::OK(); +} + +td::Status ShowCollatorsListQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX(list, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + td::TerminalIO::out() << "Collators list:\n"; + if (list->self_collate_) { + td::TerminalIO::out() << "self_collate = true\n"; + } + if (list->use_config_41_) { + td::TerminalIO::out() << "use_config_41 = true\n"; + } + if (list->shards_.empty()) { + td::TerminalIO::out() << "Shard list is empty\n"; + return td::Status::OK(); + } + for (const auto &shard : list->shards_) { + td::TerminalIO::out() << "Shard " << create_shard_id(shard->shard_id_).to_str() << "\n"; + for (const auto &collator : shard->collators_) { + td::TerminalIO::out() << " Collator " << collator->adnl_id_ << (collator->trusted_ ? " (trusted)" : "") << "\n"; + } + } + return td::Status::OK(); +} diff --git a/validator-engine-console/validator-engine-console-query.h b/validator-engine-console/validator-engine-console-query.h index ecdfa5e2..4d2a50a3 100644 --- a/validator-engine-console/validator-engine-console-query.h +++ b/validator-engine-console/validator-engine-console-query.h @@ -1342,3 +1342,63 @@ class DelShardQuery : public Query { td::int32 wc_; td::int64 shard_; }; + +class SetCollatorsListQuery : public Query { + public: + SetCollatorsListQuery(td::actor::ActorId console, Tokenizer tokenizer) + : Query(console, std::move(tokenizer)) { + } + td::Status run() override; + td::Status send() override; + td::Status receive(td::BufferSlice data) override; + static std::string get_name() { + return "setcollatorslist"; + } + static std::string get_help() { + return "setcollatorslist \tset list of collators from file "; + } + std::string name() const override { + return get_name(); + } + + private: + std::string file_name_; +}; + +class ClearCollatorsListQuery : public Query { + public: + ClearCollatorsListQuery(td::actor::ActorId console, Tokenizer tokenizer) + : Query(console, std::move(tokenizer)) { + } + td::Status run() override; + td::Status send() override; + td::Status receive(td::BufferSlice data) override; + static std::string get_name() { + return "clearcollatorslist"; + } + static std::string get_help() { + return "clearcollatorslist\tclear list of collators"; + } + std::string name() const override { + return get_name(); + } +}; + +class ShowCollatorsListQuery : public Query { + public: + ShowCollatorsListQuery(td::actor::ActorId console, Tokenizer tokenizer) + : Query(console, std::move(tokenizer)) { + } + td::Status run() override; + td::Status send() override; + td::Status receive(td::BufferSlice data) override; + static std::string get_name() { + return "showcollatorslist"; + } + static std::string get_help() { + return "showcollatorslist\tshow list of collators"; + } + std::string name() const override { + return get_name(); + } +}; diff --git a/validator-engine-console/validator-engine-console.cpp b/validator-engine-console/validator-engine-console.cpp index cd4c7c36..e9c26484 100644 --- a/validator-engine-console/validator-engine-console.cpp +++ b/validator-engine-console/validator-engine-console.cpp @@ -152,6 +152,9 @@ void ValidatorEngineConsole::run() { add_query_runner(std::make_unique>()); add_query_runner(std::make_unique>()); add_query_runner(std::make_unique>()); + add_query_runner(std::make_unique>()); + add_query_runner(std::make_unique>()); + add_query_runner(std::make_unique>()); } bool ValidatorEngineConsole::envelope_send_query(td::BufferSlice query, td::Promise promise) { diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index 585c4c74..4dd25030 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -1472,7 +1472,6 @@ td::Status ValidatorEngine::load_global_config() { } validator_options_.write().set_hardforks(std::move(h)); validator_options_.write().set_state_serializer_enabled(config_.state_serializer_enabled); - validator_options_.write().set_validator_mode(validator_mode_); return td::Status::OK(); } @@ -1502,6 +1501,31 @@ void ValidatorEngine::set_shard_check_function() { } } +void ValidatorEngine::load_collators_list() { + collators_list_ = {}; + auto data_R = td::read_file(collators_list_file()); + if (data_R.is_error()) { + return; + } + auto data = data_R.move_as_ok(); + auto json_R = td::json_decode(data.as_slice()); + if (json_R.is_error()) { + LOG(ERROR) << "Failed to parse collators list: " << json_R.move_as_error(); + return; + } + auto json = json_R.move_as_ok(); + collators_list_ = ton::create_tl_object(); + auto S = ton::ton_api::from_json(*collators_list_, json.get_object()); + if (S.is_error()) { + LOG(ERROR) << "Failed to parse collators list: " << S; + collators_list_ = {}; + return; + } + td::Ref list{true}; + list.write().unpack(*collators_list_); + validator_options_.write().set_collators_list(std::move(list)); +} + void ValidatorEngine::load_empty_local_config(td::Promise promise) { auto ret_promise = td::PromiseCreator::lambda( [SelfId = actor_id(this), promise = std::move(promise)](td::Result R) mutable { @@ -1794,6 +1818,7 @@ void ValidatorEngine::got_key(ton::PublicKey key) { void ValidatorEngine::start() { set_shard_check_function(); + load_collators_list(); read_config_ = true; start_adnl(); } @@ -3792,6 +3817,52 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_setStateS }); } +void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_setCollatorsList &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise) { + if (!(perm & ValidatorEnginePermissions::vep_modify)) { + promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized"))); + return; + } + if (!started_) { + promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "not started"))); + return; + } + + auto s = td::json_encode(td::ToJson(*query.list_), true); + auto S = td::write_file(collators_list_file(), s); + if (S.is_error()) { + promise.set_value(create_control_query_error(std::move(S))); + return; + } + + collators_list_ = std::move(query.list_); + td::Ref list{true}; + list.write().unpack(*collators_list_); + validator_options_.write().set_collators_list(std::move(list)); + td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManagerInterface::update_options, + validator_options_); + promise.set_value(ton::serialize_tl_object(ton::create_tl_object(), true)); +} + +void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_showCollatorsList &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise) { + if (!(perm & ValidatorEnginePermissions::vep_default)) { + promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized"))); + return; + } + if (!started_) { + promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "not started"))); + return; + } + if (collators_list_) { + promise.set_value(ton::serialize_tl_object(collators_list_, true)); + } else { + auto list = ton::create_tl_object(); + list->self_collate_ = true; + promise.set_value(ton::serialize_tl_object(list, true)); + } +} + void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_getValidatorSessionsInfo &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, td::Promise promise) { @@ -4260,20 +4331,6 @@ int main(int argc, char *argv[]) { p.add_option('M', "not-all-shards", "monitor only a necessary set of shards instead of all", [&]() { acts.push_back([&x]() { td::actor::send_closure(x, &ValidatorEngine::set_not_all_shards); }); }); - p.add_option('\0', "lite-validator-shards", - "lite-mode validator for shard blocks (don't collate blocks, use collator nodes instead)", [&]() { - acts.push_back([&x]() { - td::actor::send_closure(x, &ValidatorEngine::set_validator_mode, - ton::validator::ValidatorManagerOptions::validator_lite_shards); - }); - }); - p.add_option('\0', "lite-validator-all", - "lite-mode validator for all blocks (don't collate blocks, use collator nodes instead)", [&]() { - acts.push_back([&x]() { - td::actor::send_closure(x, &ValidatorEngine::set_validator_mode, - ton::validator::ValidatorManagerOptions::validator_lite_all); - }); - }); td::uint32 threads = 7; p.add_checked_option( 't', "threads", PSTRING() << "number of threads (default=" << threads << ")", [&](td::Slice fname) { diff --git a/validator-engine/validator-engine.hpp b/validator-engine/validator-engine.hpp index ebf8fb58..64154718 100644 --- a/validator-engine/validator-engine.hpp +++ b/validator-engine/validator-engine.hpp @@ -184,6 +184,7 @@ class ValidatorEngine : public td::actor::Actor { td::Ref validator_options_; Config config_; ton::tl_object_ptr custom_overlays_config_; + ton::tl_object_ptr collators_list_; std::set running_gc_; @@ -235,8 +236,6 @@ class ValidatorEngine : public td::actor::Actor { ton::BlockSeqno truncate_seqno_{0}; std::string session_logs_file_; bool not_all_shards_ = false; - ton::validator::ValidatorManagerOptions::ValidatorMode validator_mode_ = - ton::validator::ValidatorManagerOptions::validator_normal; std::set unsafe_catchains_; std::map> unsafe_catchain_rotations_; @@ -319,9 +318,6 @@ class ValidatorEngine : public td::actor::Actor { void set_not_all_shards() { not_all_shards_ = true; } - void set_validator_mode(ton::validator::ValidatorManagerOptions::ValidatorMode mode) { - validator_mode_ = mode; - } void start_up() override; ValidatorEngine() { @@ -333,6 +329,7 @@ class ValidatorEngine : public td::actor::Actor { void load_local_config(td::Promise promise); void load_config(td::Promise promise); void set_shard_check_function(); + void load_collators_list(); void start(); @@ -411,6 +408,9 @@ class ValidatorEngine : public td::actor::Actor { std::string custom_overlays_config_file() const { return db_root_ + "/custom-overlays.json"; } + std::string collators_list_file() const { + return db_root_ + "/collators-list.json"; + } void load_custom_overlays_config(); td::Status write_custom_overlays_config(); @@ -514,6 +514,10 @@ class ValidatorEngine : public td::actor::Actor { ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); void run_control_query(ton::ton_api::engine_validator_setStateSerializerEnabled &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); + void run_control_query(ton::ton_api::engine_validator_setCollatorsList &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); + void run_control_query(ton::ton_api::engine_validator_showCollatorsList &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); template void run_control_query(T &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, td::Promise promise) { diff --git a/validator/fabric.h b/validator/fabric.h index e809be43..a38b4056 100644 --- a/validator/fabric.h +++ b/validator/fabric.h @@ -26,7 +26,7 @@ namespace ton { namespace validator { -enum ValidateMode { fake = 1, full_collated_data = 2 }; +enum ValidateMode { fake = 1 }; enum CollateMode { skip_store_candidate = 1 }; td::actor::ActorOwn create_db_actor(td::actor::ActorId manager, std::string db_root_, diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index c0c4a2e8..85ced27d 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -82,7 +82,6 @@ ValidateQuery::ValidateQuery(ShardIdFull shard, BlockIdExt min_masterchain_block , timeout(timeout) , main_promise(std::move(promise)) , is_fake_(mode & ValidateMode::fake) - , full_collated_data_(mode & ValidateMode::full_collated_data) , shard_pfx_(shard_.shard) , shard_pfx_len_(ton::shard_prefix_length(shard_)) , perf_timer_("validateblock", 0.1, [manager](double duration) { @@ -258,7 +257,6 @@ void ValidateQuery::finish_query() { */ void ValidateQuery::start_up() { LOG(WARNING) << "validate query for " << block_candidate.id.to_str() << " started"; - LOG(DEBUG) << "full_collated_data is " << full_collated_data_; alarm_timestamp() = timeout; rand_seed_.set_zero(); created_by_ = block_candidate.pubkey; @@ -359,11 +357,16 @@ void ValidateQuery::start_up() { td::actor::send_closure_later( std::move(self), &ValidateQuery::after_get_latest_mc_state, std::move(res)); }); - // 3. load state(s) corresponding to previous block(s) (not full-collaoted-data or masterchain) + // 3. unpack block candidate (while necessary data is being loaded) + if (!unpack_block_candidate()) { + reject_query("error unpacking block candidate"); + return; + } + // 4. load state(s) corresponding to previous block(s) (not full-collated-data or masterchain) prev_states.resize(prev_blocks.size()); if (is_masterchain() || !full_collated_data_) { for (int i = 0; (unsigned)i < prev_blocks.size(); i++) { - // 3.1. load state + // 4.1. load state LOG(DEBUG) << "sending wait_block_state() query #" << i << " for " << prev_blocks[i].to_str() << " to Manager"; ++pending; td::actor::send_closure_later(manager, &ValidatorManager::wait_block_state_short, prev_blocks[i], priority(), @@ -374,11 +377,6 @@ void ValidateQuery::start_up() { }); } } - // 4. unpack block candidate (while necessary data is being loaded) - if (!unpack_block_candidate()) { - reject_query("error unpacking block candidate"); - return; - } // 5. request masterchain state referred to in the block if (!is_masterchain()) { ++pending; @@ -629,6 +627,7 @@ bool ValidateQuery::extract_collated_data_from(Ref croot, int idx) { if (!ins.second) { return reject_query("Merkle proof with duplicate virtual root hash "s + virt_hash.to_hex()); } + full_collated_data_ = true; return true; } if (block::gen::t_TopBlockDescrSet.has_valid_tag(cs)) { @@ -666,6 +665,9 @@ bool ValidateQuery::extract_collated_data() { return reject_query(PSTRING() << "virtualization error " << err.get_msg()); } } + if (full_collated_data_) { + LOG(INFO) << "full_collated_data = true"; + } return true; } diff --git a/validator/manager.cpp b/validator/manager.cpp index aa46e9e8..bde7a805 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -373,7 +373,8 @@ void ValidatorManagerImpl::get_key_block_proof_link(BlockIdExt block_id, td::Pro } void ValidatorManagerImpl::new_external_message(td::BufferSlice data, int priority) { - if (!is_collator()) { + if (!validating_masterchain() && collator_nodes_.empty() && + (!is_validator() || !opts_->get_collators_list()->self_collate)) { return; } if (last_masterchain_state_.is_null()) { @@ -453,7 +454,7 @@ void ValidatorManagerImpl::check_external_message(td::BufferSlice data, td::Prom } void ValidatorManagerImpl::new_ihr_message(td::BufferSlice data) { - if (!is_collator()) { + if (collator_nodes_.empty() && (!is_validator() || !opts_->get_collators_list()->self_collate)) { return; } auto R = create_ihr_message(std::move(data)); @@ -470,7 +471,7 @@ void ValidatorManagerImpl::new_ihr_message(td::BufferSlice data) { } void ValidatorManagerImpl::new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) { - if (!is_collator() && !is_validator()) { + if (!is_validator()) { return; } if (!last_masterchain_block_handle_) { @@ -533,7 +534,7 @@ void ValidatorManagerImpl::add_shard_block_description(td::Refblock_id(), 0, td::Timestamp::in(60.0), std::move(P)); } - if (collating_masterchain()) { + if (validating_masterchain()) { preload_msg_queue_to_masterchain(desc); } } @@ -542,7 +543,8 @@ void ValidatorManagerImpl::add_shard_block_description(td::Ref desc) { auto id = ShardTopBlockDescriptionId{desc->block_id().shard_full(), desc->catchain_seqno()}; auto it = shard_blocks_.find(id); - if (!collating_masterchain() || it == shard_blocks_.end() || it->second.latest_desc->block_id() != desc->block_id()) { + if (!validating_masterchain() || it == shard_blocks_.end() || + it->second.latest_desc->block_id() != desc->block_id()) { return; } wait_neighbor_msg_queue_proofs( @@ -2031,9 +2033,9 @@ void ValidatorManagerImpl::new_masterchain_block() { td::actor::send_closure(shard_client_, &ShardClient::new_masterchain_block_notification, last_masterchain_block_handle_, last_masterchain_state_); } - if (is_collator()) { + if (validating_masterchain() || !collator_nodes_.empty()) { std::set collating_shards; - if (collating_masterchain()) { + if (validating_masterchain()) { collating_shards.emplace(masterchainId); } for (const auto &collator : collator_nodes_) { @@ -2398,7 +2400,8 @@ td::actor::ActorOwn ValidatorManagerImpl::create_validator_group auto G = td::actor::create_actor( "validatorgroup", shard, validator_id, session_id, validator_set, last_masterchain_state_->get_collator_config(true), opts, keyring_, adnl_, rldp_, overlays_, db_root_, - actor_id(this), init_session, opts_->check_unsafe_resync_allowed(validator_set->get_catchain_seqno()), opts_); + actor_id(this), init_session, opts_->check_unsafe_resync_allowed(validator_set->get_catchain_seqno()), opts_, + opts_->need_monitor(shard, last_masterchain_state_)); return G; } } @@ -2845,27 +2848,12 @@ bool ValidatorManagerImpl::is_validator() { return temp_keys_.size() > 0 || permanent_keys_.size() > 0; } -bool ValidatorManagerImpl::is_collator() { - return !collator_nodes_.empty() || - (opts_->validator_mode() != ValidatorManagerOptions::validator_lite_all && is_validator()); -} - bool ValidatorManagerImpl::validating_masterchain() { return !get_validator(ShardIdFull(masterchainId), last_masterchain_state_->get_validator_set(ShardIdFull(masterchainId))) .is_zero(); } -bool ValidatorManagerImpl::collating_masterchain() { - if (masterchain_collators_) { - return true; - } - if (opts_->validator_mode() == ValidatorManagerOptions::validator_lite_all) { - return false; - } - return validating_masterchain(); -} - PublicKeyHash ValidatorManagerImpl::get_validator(ShardIdFull shard, td::Ref val_set) { for (auto &key : temp_keys_) { if (val_set->is_validator(key.bits256_value())) { @@ -3331,6 +3319,14 @@ void ValidatorManagerImpl::update_options(td::Ref opts) if (!queue_size_counter_.empty()) { td::actor::send_closure(queue_size_counter_, &QueueSizeCounter::update_options, opts); } + for (auto &group : validator_groups_) { + td::actor::send_closure(group.second.actor, &ValidatorGroup::update_options, opts, + opts->need_monitor(group.second.shard, last_masterchain_state_)); + } + for (auto &group : next_validator_groups_) { + td::actor::send_closure(group.second.actor, &ValidatorGroup::update_options, opts, + opts->need_monitor(group.second.shard, last_masterchain_state_)); + } opts_ = std::move(opts); } @@ -3376,9 +3372,6 @@ void ValidatorManagerImpl::add_collator(adnl::AdnlNodeIdShort id, ShardIdFull sh if (!it->second.shards.insert(shard).second) { return; } - if (shard.is_masterchain()) { - ++masterchain_collators_; - } td::actor::send_closure(it->second.actor, &CollatorNode::add_shard, shard); } @@ -3390,9 +3383,6 @@ void ValidatorManagerImpl::del_collator(adnl::AdnlNodeIdShort id, ShardIdFull sh if (!it->second.shards.erase(shard)) { return; } - if (shard.is_masterchain()) { - --masterchain_collators_; - } if (it->second.shards.empty()) { collator_nodes_.erase(it); } else { diff --git a/validator/manager.hpp b/validator/manager.hpp index dc18e627..4e5d1d3e 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -560,9 +560,7 @@ class ValidatorManagerImpl : public ValidatorManager { void read_gc_list(std::vector list); bool is_validator(); - bool is_collator(); bool validating_masterchain(); - bool collating_masterchain(); PublicKeyHash get_validator(ShardIdFull shard, td::Ref val_set); ValidatorManagerImpl(td::Ref opts, std::string db_root, @@ -767,7 +765,6 @@ class ValidatorManagerImpl : public ValidatorManager { std::set shards; }; std::map collator_nodes_; - size_t masterchain_collators_ = 0; std::set extra_active_shards_; std::map last_validated_blocks_; diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp index fc1fb009..e4ae88dd 100644 --- a/validator/validator-group.cpp +++ b/validator/validator-group.cpp @@ -57,14 +57,7 @@ void ValidatorGroup::generate_block_candidate( cache = cached_collated_block_](td::Result R) { td::actor::send_closure(SelfId, &ValidatorGroup::generated_block_candidate, std::move(cache), std::move(R)); }; - if (opts_->validator_mode() == ValidatorManagerOptions::validator_lite_all || - (opts_->validator_mode() == ValidatorManagerOptions::validator_lite_shards && !shard_.is_masterchain())) { - send_collate_query(round_id, td::Timestamp::in(10.0), std::move(P)); - return; - } - run_collate_query(shard_, min_masterchain_block_id_, prev_block_ids_, - Ed25519_PublicKey{local_id_full_.ed25519_value().raw()}, validator_set_, manager_, - td::Timestamp::in(10.0), std::move(P)); + collate_block(round_id, td::Timestamp::in(10.0), std::move(P)); } void ValidatorGroup::generated_block_candidate(std::shared_ptr cache, @@ -142,8 +135,7 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat } VLOG(VALIDATOR_DEBUG) << "validating block candidate " << next_block_id; run_validate_query(shard_, min_masterchain_block_id_, prev_block_ids_, std::move(block), validator_set_, manager_, - td::Timestamp::in(15.0), std::move(P), - collator_config_.full_collated_data ? ValidateMode::full_collated_data : 0); + td::Timestamp::in(15.0), std::move(P)); } void ValidatorGroup::update_approve_cache(CacheKey key, UnixTime value) { @@ -204,10 +196,8 @@ void ValidatorGroup::accept_block_query(BlockIdExt block_id, td::Ref } }); - run_accept_block_query( - block_id, std::move(block), std::move(prev), validator_set_, std::move(sig_set), std::move(approve_sig_set), - send_broadcast, shard_.is_masterchain() || opts_->validator_mode() == ValidatorManagerOptions::validator_normal, - manager_, std::move(P)); + run_accept_block_query(block_id, std::move(block), std::move(prev), validator_set_, std::move(sig_set), + std::move(approve_sig_set), send_broadcast, apply_blocks_, manager_, std::move(P)); } void ValidatorGroup::skip_round(td::uint32 round_id) { @@ -480,25 +470,55 @@ void ValidatorGroup::get_session_info( td::actor::send_closure(session_, &validatorsession::ValidatorSession::get_session_info, std::move(P)); } -void ValidatorGroup::send_collate_query(td::uint32 round_id, td::Timestamp timeout, td::Promise promise, - unsigned max_retries) { +void ValidatorGroup::collate_block(td::uint32 round_id, td::Timestamp timeout, td::Promise promise, + unsigned max_retries) { if (round_id < last_known_round_id_) { promise.set_error(td::Status::Error("too old")); return; } BlockId next_block_id = create_next_block_id_simple(); - adnl::AdnlNodeIdShort collator = adnl::AdnlNodeIdShort::zero(); - // TODO: some way to choose node (similar to "unreliability" in full-node) - int cnt = 0; - for (const block::CollatorNodeDescr &c : collator_config_.collator_nodes) { - if (shard_intersects(shard_, c.shard)) { - if (td::Random::fast(0, cnt) == 0) { - collator = adnl::AdnlNodeIdShort(c.adnl_id); + adnl::AdnlNodeIdShort collator_adnl_id = adnl::AdnlNodeIdShort::zero(); + bool self_collate = false; + bool trusted_collator = false; + + if (shard_.is_masterchain()) { + self_collate = true; + } else { + for (const auto &s : opts_->get_collators_list()->shards) { + if (!shard_intersects(s.shard_id, shard_)) { + continue; + } + if (!s.collators.empty()) { + const CollatorsList::Collator &col = s.collators[td::Random::fast(0, s.collators.size() - 1)]; + collator_adnl_id = col.adnl_id; + trusted_collator = col.trusted; + break; + } + } + if (collator_adnl_id.is_zero()) { + if (opts_->get_collators_list()->self_collate) { + self_collate = true; + } else if (opts_->get_collators_list()->use_config_41) { + // TODO: some way to choose node (similar to "unreliability" in full-node) + int cnt = 0; + for (const block::CollatorNodeDescr &c : collator_config_.collator_nodes) { + if (shard_intersects(shard_, c.shard)) { + if (td::Random::fast(0, cnt) == 0) { + collator_adnl_id = adnl::AdnlNodeIdShort(c.adnl_id); + } + ++cnt; + } + } } - ++cnt; } } - if (collator.is_zero()) { + if (self_collate) { + run_collate_query(shard_, min_masterchain_block_id_, prev_block_ids_, + Ed25519_PublicKey{local_id_full_.ed25519_value().raw()}, validator_set_, manager_, + td::Timestamp::in(10.0), std::move(promise)); + return; + } + if (collator_adnl_id.is_zero()) { promise.set_error(td::Status::Error(PSTRING() << "no collator for shard " << shard_.to_str())); return; } @@ -514,7 +534,7 @@ void ValidatorGroup::send_collate_query(td::uint32 round_id, td::Timestamp timeo LOG(WARNING) << "collate query for " << next_block_id.to_str() << ": " << R.error() << ", time=" << timer.elapsed() << "s, " << (retry ? "retrying" : "giving up"); if (retry) { - td::actor::send_closure(SelfId, &ValidatorGroup::send_collate_query, round_id, timeout, std::move(promise), + td::actor::send_closure(SelfId, &ValidatorGroup::collate_block, round_id, timeout, std::move(promise), max_retries - 1); } else { promise.set_result(td::Status::Error(ErrorCode::timeout, "timeout")); @@ -530,23 +550,23 @@ void ValidatorGroup::send_collate_query(td::uint32 round_id, td::Timestamp timeo local_id_full_.ed25519_value().raw()); auto P = td::PromiseCreator::lambda( - [SelfId = actor_id(this), round_id, promise = std::move(promise)](td::Result R) mutable { + [=, SelfId = actor_id(this), promise = std::move(promise)](td::Result R) mutable { if (R.is_error()) { promise.set_error(R.move_as_error_prefix("rldp query failed: ")); return; } td::actor::send_closure(SelfId, &ValidatorGroup::receive_collate_query_response, round_id, R.move_as_ok(), - std::move(promise)); + trusted_collator, std::move(promise)); }); - LOG(INFO) << "sending collate query for " << next_block_id.to_str() << ": send to " << collator; + LOG(INFO) << "sending collate query for " << next_block_id.to_str() << ": send to " << collator_adnl_id; size_t max_answer_size = config_.max_block_size + config_.max_collated_data_size + 1024; td::Timestamp query_timeout = td::Timestamp::in(10.0); query_timeout.relax(timeout); - td::actor::send_closure(rldp_, &rldp::Rldp::send_query_ex, local_adnl_id_, collator, "collatequery", std::move(P), - timeout, std::move(query), max_answer_size); + td::actor::send_closure(rldp_, &rldp::Rldp::send_query_ex, local_adnl_id_, collator_adnl_id, "collatequery", + std::move(P), timeout, std::move(query), max_answer_size); } -void ValidatorGroup::receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, +void ValidatorGroup::receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, bool trusted_collator, td::Promise promise) { if (round_id < last_known_round_id_) { promise.set_error(td::Status::Error("too old")); @@ -574,6 +594,10 @@ void ValidatorGroup::receive_collate_query_response(td::uint32 round_id, td::Buf return; } + if (trusted_collator) { + promise.set_result(std::move(candidate)); + return; + } auto P = td::PromiseCreator::lambda( [candidate = candidate.clone(), promise = std::move(promise)](td::Result> R) mutable { if (R.is_error()) { diff --git a/validator/validator-group.hpp b/validator/validator-group.hpp index d4080f6a..62757342 100644 --- a/validator/validator-group.hpp +++ b/validator/validator-group.hpp @@ -66,13 +66,18 @@ class ValidatorGroup : public td::actor::Actor { void get_session_info(td::Promise> promise); + void update_options(td::Ref opts, bool apply_blocks) { + opts_ = std::move(opts); + apply_blocks_ = apply_blocks; + } + ValidatorGroup(ShardIdFull shard, PublicKeyHash local_id, ValidatorSessionId session_id, td::Ref validator_set, block::CollatorConfig collator_config, validatorsession::ValidatorSessionOptions config, td::actor::ActorId keyring, td::actor::ActorId adnl, td::actor::ActorId rldp, td::actor::ActorId overlays, std::string db_root, td::actor::ActorId validator_manager, bool create_session, - bool allow_unsafe_self_blocks_resync, td::Ref opts) + bool allow_unsafe_self_blocks_resync, td::Ref opts, bool apply_blocks) : shard_(shard) , local_id_(std::move(local_id)) , session_id_(session_id) @@ -87,14 +92,16 @@ class ValidatorGroup : public td::actor::Actor { , manager_(validator_manager) , init_(create_session) , allow_unsafe_self_blocks_resync_(allow_unsafe_self_blocks_resync) - , opts_(std::move(opts)) { + , opts_(std::move(opts)) + , apply_blocks_(apply_blocks) { } private: std::unique_ptr make_validator_session_callback(); - void send_collate_query(td::uint32 round_id, td::Timestamp timeout, td::Promise promise, + void collate_block(td::uint32 round_id, td::Timestamp timeout, td::Promise promise, unsigned max_retries = 4); - void receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, td::Promise promise); + void receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, bool trusted_collator, + td::Promise promise); struct PostponedAccept { RootHash root_hash; @@ -134,6 +141,7 @@ class ValidatorGroup : public td::actor::Actor { bool allow_unsafe_self_blocks_resync_; td::Ref opts_; td::uint32 last_known_round_id_ = 0; + bool apply_blocks_ = true; struct CachedCollatedBlock { td::optional result; diff --git a/validator/validator-options.cpp b/validator/validator-options.cpp index cb26fe44..4f9b8c53 100644 --- a/validator/validator-options.cpp +++ b/validator/validator-options.cpp @@ -20,10 +20,26 @@ #include "ton/ton-shard.h" +#include + namespace ton { namespace validator { +void CollatorsList::unpack(const ton_api::engine_validator_collatorsList& obj) { + shards.clear(); + self_collate = obj.self_collate_; + use_config_41 = obj.use_config_41_; + for (const auto& shard_obj : obj.shards_) { + shards.emplace_back(); + Shard& shard = shards.back(); + shard.shard_id = create_shard_id(shard_obj->shard_id_); + for (const auto& collator : shard_obj->collators_) { + shard.collators.push_back({adnl::AdnlNodeIdShort{collator->adnl_id_}, collator->trusted_}); + } + } +} + td::Ref ValidatorManagerOptions::create( BlockIdExt zero_block_id, BlockIdExt init_block_id, std::function check_shard, bool allow_blockchain_init, diff --git a/validator/validator-options.hpp b/validator/validator-options.hpp index 55b40a33..e67c4e2d 100644 --- a/validator/validator-options.hpp +++ b/validator/validator-options.hpp @@ -142,8 +142,8 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { bool get_state_serializer_enabled() const override { return state_serializer_enabled_; } - ValidatorMode validator_mode() const override { - return validator_mode_; + td::Ref get_collators_list() const override { + return collators_list_; } void set_zero_block_id(BlockIdExt block_id) override { @@ -228,8 +228,8 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { void set_state_serializer_enabled(bool value) override { state_serializer_enabled_ = value; } - void set_validator_mode(ValidatorMode value) override { - validator_mode_ = value; + void set_collators_list(td::Ref list) override { + collators_list_ = std::move(list); } ValidatorManagerOptionsImpl *make_copy() const override { @@ -281,7 +281,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { bool celldb_preload_all_ = false; td::optional catchain_max_block_delay_; bool state_serializer_enabled_ = true; - ValidatorMode validator_mode_ = validator_normal; + td::Ref collators_list_{true, CollatorsList{}}; }; } // namespace validator diff --git a/validator/validator.h b/validator/validator.h index c7ef2ce8..77b39607 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -52,10 +52,24 @@ struct PerfTimerStats { std::deque> stats; // }; +struct CollatorsList : public td::CntObject { + struct Collator { + adnl::AdnlNodeIdShort adnl_id; + bool trusted; + }; + struct Shard { + ShardIdFull shard_id; + std::vector collators; + }; + bool self_collate = true; + bool use_config_41 = false; + std::vector shards; + + void unpack(const ton_api::engine_validator_collatorsList& obj); +}; + struct ValidatorManagerOptions : public td::CntObject { public: - enum ValidatorMode { validator_normal, validator_lite_shards, validator_lite_all }; - virtual BlockIdExt zero_block_id() const = 0; virtual BlockIdExt init_block_id() const = 0; virtual bool need_monitor(ShardIdFull shard, const td::Ref& state) const = 0; @@ -91,7 +105,7 @@ struct ValidatorManagerOptions : public td::CntObject { virtual bool get_celldb_preload_all() const = 0; virtual td::optional get_catchain_max_block_delay() const = 0; virtual bool get_state_serializer_enabled() const = 0; - virtual ValidatorMode validator_mode() const = 0; + virtual td::Ref get_collators_list() const = 0; virtual void set_zero_block_id(BlockIdExt block_id) = 0; virtual void set_init_block_id(BlockIdExt block_id) = 0; @@ -120,7 +134,7 @@ struct ValidatorManagerOptions : public td::CntObject { virtual void set_celldb_preload_all(bool value) = 0; virtual void set_catchain_max_block_delay(double value) = 0; virtual void set_state_serializer_enabled(bool value) = 0; - virtual void set_validator_mode(ValidatorMode value) = 0; + virtual void set_collators_list(td::Ref list) = 0; static td::Ref create( BlockIdExt zero_block_id, BlockIdExt init_block_id,