From 6038147afe999be5eadae332593cf97a0ce3ee47 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Tue, 27 Aug 2024 18:10:17 +0300 Subject: [PATCH 1/2] Disable state serializer on masterchain validators (#1129) --- validator/manager.cpp | 12 ++++++ validator/state-serializer.cpp | 72 ++++++++++++++++++++-------------- validator/state-serializer.hpp | 13 ++++-- 3 files changed, 64 insertions(+), 33 deletions(-) diff --git a/validator/manager.cpp b/validator/manager.cpp index 79661a293..f127b1fd4 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -2065,6 +2065,7 @@ void ValidatorManagerImpl::update_shards() { } } + bool validating_masterchain = false; if (allow_validate_) { for (auto &desc : new_shards) { auto shard = desc.first; @@ -2081,6 +2082,9 @@ void ValidatorManagerImpl::update_shards() { auto validator_id = get_validator(shard, val_set); if (!validator_id.is_zero()) { + if (shard.is_masterchain()) { + validating_masterchain = true; + } auto val_group_id = get_validator_set_id(shard, val_set, opts_hash, key_seqno, opts); if (force_recover) { @@ -2173,6 +2177,14 @@ void ValidatorManagerImpl::update_shards() { td::actor::send_closure(SelfId, &ValidatorManagerImpl::written_destroyed_validator_sessions, std::move(gc)); }); td::actor::send_closure(db_, &Db::update_destroyed_validator_sessions, gc_list_, std::move(P)); + + if (!serializer_.empty()) { + td::actor::send_closure( + serializer_, &AsyncStateSerializer::auto_disable_serializer, + validating_masterchain && + last_masterchain_state_->get_validator_set(ShardIdFull{masterchainId})->export_vector().size() * 2 <= + last_masterchain_state_->get_total_validator_set(0)->export_vector().size()); + } } } // namespace validator diff --git a/validator/state-serializer.cpp b/validator/state-serializer.cpp index f7ea7efe9..ef79d33cb 100644 --- a/validator/state-serializer.cpp +++ b/validator/state-serializer.cpp @@ -95,7 +95,8 @@ void AsyncStateSerializer::request_previous_state_files() { } void AsyncStateSerializer::got_previous_state_files(std::vector> files) { - previous_state_files_ = std::move(files); + previous_state_cache_ = std::make_shared(); + previous_state_cache_->state_files = std::move(files); request_masterchain_state(); } @@ -151,7 +152,10 @@ void AsyncStateSerializer::next_iteration() { need_serialize(masterchain_handle_)) { if (!have_masterchain_state_ && !opts_->get_state_serializer_enabled()) { LOG(ERROR) << "skipping serializing persistent state for " << masterchain_handle_->id().id.to_str() - << ": serializer is disabled"; + << ": serializer is disabled (by user)"; + } else if (!have_masterchain_state_ && auto_disabled_) { + LOG(ERROR) << "skipping serializing persistent state for " << masterchain_handle_->id().id.to_str() + << ": serializer is disabled (automatically)"; } else if (!have_masterchain_state_ && have_newer_persistent_state(masterchain_handle_->unix_time())) { LOG(ERROR) << "skipping serializing persistent state for " << masterchain_handle_->id().id.to_str() << ": newer key block with ts=" << last_known_key_block_ts_ << " exists"; @@ -182,9 +186,7 @@ void AsyncStateSerializer::next_iteration() { } last_key_block_ts_ = masterchain_handle_->unix_time(); last_key_block_id_ = masterchain_handle_->id(); - previous_state_files_ = {}; previous_state_cache_ = {}; - previous_state_cur_shards_ = {}; } if (!saved_to_db_) { running_ = true; @@ -252,27 +254,24 @@ class CachedCellDbReader : public vm::CellDbReader { td::uint64 cached_reqs_ = 0; }; -void AsyncStateSerializer::prepare_previous_state_cache(ShardIdFull shard) { - if (!opts_->get_fast_state_serializer_enabled()) { - return; - } +void AsyncStateSerializer::PreviousStateCache::prepare_cache(ShardIdFull shard) { std::vector prev_shards; - for (const auto& [_, prev_shard] : previous_state_files_) { + for (const auto& [_, prev_shard] : state_files) { if (shard_intersects(shard, prev_shard)) { prev_shards.push_back(prev_shard); } } - if (prev_shards == previous_state_cur_shards_) { + if (prev_shards == cur_shards) { return; } - previous_state_cur_shards_ = std::move(prev_shards); - previous_state_cache_ = {}; - if (previous_state_cur_shards_.empty()) { + cur_shards = std::move(prev_shards); + cache = {}; + if (cur_shards.empty()) { return; } td::Timer timer; LOG(WARNING) << "Preloading previous persistent state for shard " << shard.to_str() << " (" - << previous_state_cur_shards_.size() << " files)"; + << cur_shards.size() << " files)"; std::map> cells; std::function)> dfs = [&](td::Ref cell) { td::Bits256 hash = cell->get_hash().bits(); @@ -285,7 +284,7 @@ void AsyncStateSerializer::prepare_previous_state_cache(ShardIdFull shard) { dfs(cs.prefetch_ref(i)); } }; - for (const auto& [file, prev_shard] : previous_state_files_) { + for (const auto& [file, prev_shard] : state_files) { if (!shard_intersects(shard, prev_shard)) { continue; } @@ -300,22 +299,20 @@ void AsyncStateSerializer::prepare_previous_state_cache(ShardIdFull shard) { LOG(WARNING) << "Deserialize error : " << r_root.move_as_error(); continue; } - r_data = {}; + r_data.clear(); dfs(r_root.move_as_ok()); } LOG(WARNING) << "Preloaded previous state: " << cells.size() << " cells in " << timer.elapsed() << "s"; - previous_state_cache_ = std::make_shared>>(std::move(cells)); + cache = std::make_shared>>(std::move(cells)); } void AsyncStateSerializer::got_masterchain_state(td::Ref state, std::shared_ptr cell_db_reader) { - if (!opts_->get_state_serializer_enabled()) { + if (!opts_->get_state_serializer_enabled() || auto_disabled_) { stored_masterchain_state(); return; } LOG(ERROR) << "serializing masterchain state " << masterchain_handle_->id().id.to_str(); - prepare_previous_state_cache(state->get_shard()); - auto new_cell_db_reader = std::make_shared(cell_db_reader, previous_state_cache_); have_masterchain_state_ = true; CHECK(next_idx_ == 0); CHECK(shards_.size() == 0); @@ -325,10 +322,16 @@ void AsyncStateSerializer::got_masterchain_state(td::Ref state shards_.push_back(v->top_block_id()); } - auto write_data = [hash = state->root_cell()->get_hash(), cell_db_reader = new_cell_db_reader, + auto write_data = [shard = state->get_shard(), hash = state->root_cell()->get_hash(), cell_db_reader, + previous_state_cache = previous_state_cache_, + fast_serializer_enabled = opts_->get_fast_state_serializer_enabled(), cancellation_token = cancellation_token_source_.get_cancellation_token()](td::FileFd& fd) mutable { - auto res = vm::std_boc_serialize_to_file_large(cell_db_reader, hash, fd, 31, std::move(cancellation_token)); - cell_db_reader->print_stats(); + if (fast_serializer_enabled) { + previous_state_cache->prepare_cache(shard); + } + auto new_cell_db_reader = std::make_shared(cell_db_reader, previous_state_cache->cache); + auto res = vm::std_boc_serialize_to_file_large(new_cell_db_reader, hash, fd, 31, std::move(cancellation_token)); + new_cell_db_reader->print_stats(); return res; }; auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) { @@ -375,17 +378,21 @@ void AsyncStateSerializer::got_shard_handle(BlockHandle handle) { void AsyncStateSerializer::got_shard_state(BlockHandle handle, td::Ref state, std::shared_ptr cell_db_reader) { - if (!opts_->get_state_serializer_enabled()) { + if (!opts_->get_state_serializer_enabled() || auto_disabled_) { success_handler(); return; } LOG(ERROR) << "serializing shard state " << handle->id().id.to_str(); - prepare_previous_state_cache(state->get_shard()); - auto new_cell_db_reader = std::make_shared(cell_db_reader, previous_state_cache_); - auto write_data = [hash = state->root_cell()->get_hash(), cell_db_reader = new_cell_db_reader, + auto write_data = [shard = state->get_shard(), hash = state->root_cell()->get_hash(), cell_db_reader, + previous_state_cache = previous_state_cache_, + fast_serializer_enabled = opts_->get_fast_state_serializer_enabled(), cancellation_token = cancellation_token_source_.get_cancellation_token()](td::FileFd& fd) mutable { - auto res = vm::std_boc_serialize_to_file_large(cell_db_reader, hash, fd, 31, std::move(cancellation_token)); - cell_db_reader->print_stats(); + if (fast_serializer_enabled) { + previous_state_cache->prepare_cache(shard); + } + auto new_cell_db_reader = std::make_shared(cell_db_reader, previous_state_cache->cache); + auto res = vm::std_boc_serialize_to_file_large(new_cell_db_reader, hash, fd, 31, std::move(cancellation_token)); + new_cell_db_reader->print_stats(); return res; }; auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result R) { @@ -427,6 +434,13 @@ void AsyncStateSerializer::update_options(td::Ref opts) } } +void AsyncStateSerializer::auto_disable_serializer(bool disabled) { + auto_disabled_ = disabled; + if (auto_disabled_) { + cancellation_token_source_.cancel(); + } +} + bool AsyncStateSerializer::need_monitor(ShardIdFull shard) { return opts_->need_monitor(shard); diff --git a/validator/state-serializer.hpp b/validator/state-serializer.hpp index 6d966f930..68606d1ea 100644 --- a/validator/state-serializer.hpp +++ b/validator/state-serializer.hpp @@ -37,6 +37,7 @@ class AsyncStateSerializer : public td::actor::Actor { bool saved_to_db_ = true; td::Ref opts_; + bool auto_disabled_ = false; td::CancellationTokenSource cancellation_token_source_; UnixTime last_known_key_block_ts_ = 0; @@ -48,11 +49,14 @@ class AsyncStateSerializer : public td::actor::Actor { bool have_masterchain_state_ = false; std::vector shards_; - std::vector> previous_state_files_; - std::shared_ptr>> previous_state_cache_; - std::vector previous_state_cur_shards_; + struct PreviousStateCache { + std::vector> state_files; + std::shared_ptr>> cache; + std::vector cur_shards; - void prepare_previous_state_cache(ShardIdFull shard); + void prepare_cache(ShardIdFull shard); + }; + std::shared_ptr previous_state_cache_; public: AsyncStateSerializer(BlockIdExt block_id, td::Ref opts, @@ -105,6 +109,7 @@ class AsyncStateSerializer : public td::actor::Actor { void success_handler(); void update_options(td::Ref opts); + void auto_disable_serializer(bool disabled); }; } // namespace validator From be55da5fdef7340ee4e7f91015d53e38e4d6fbb0 Mon Sep 17 00:00:00 2001 From: EmelyanenkoK Date: Tue, 27 Aug 2024 18:17:43 +0300 Subject: [PATCH 2/2] Increase moderate misbehavior threshold --- lite-client/lite-client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp index 02a5fab67..da2fd6ff9 100644 --- a/lite-client/lite-client.cpp +++ b/lite-client/lite-client.cpp @@ -3737,10 +3737,10 @@ void TestNode::continue_check_validator_load3(std::unique_ptr