diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 1909c71a..eca15235 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -633,6 +633,8 @@ engine.validator.overlaysStats overlays:(vector engine.validator.overlayStats) = engine.validator.validatorSessionInfo current_block:tonNode.blockId self:int256 current_round:int next_producers:(vector int256) = engine.validator.ValidatorSessionInfo; engine.validator.validatorSessionsInfo sessions:(vector engine.validator.validatorSessionInfo) = engine.validator.ValidatorSessionsInfo; +engine.validator.requiredBlockCandidates block_ids:(vector tonNode.blockId) = engine.validator.RequiredBlockCandidates; + ---functions--- engine.validator.getTime = engine.validator.Time; @@ -684,6 +686,10 @@ engine.validator.importShardOverlayCertificate workchain:int shard:long signed_k engine.validator.getValidatorSessionsInfo = engine.validator.ValidatorSessionsInfo; +engine.validator.generateBlockCandidate block_id:tonNode.BlockId = db.Candidate; +engine.validator.getRequiredBlockCandidates = engine.validator.RequiredBlockCandidates; +engine.validator.importBlockCandidate block:db.candidate = engine.validator.Success; + ---types--- storage.pong = storage.Pong; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 9af19e27..252c6d05 100644 Binary files a/tl/generate/scheme/ton_api.tlo and b/tl/generate/scheme/ton_api.tlo differ diff --git a/validator-engine-console/validator-engine-console-query.cpp b/validator-engine-console/validator-engine-console-query.cpp index 9f48b6b5..028c5b1a 100644 --- a/validator-engine-console/validator-engine-console-query.cpp +++ b/validator-engine-console/validator-engine-console-query.cpp @@ -1028,3 +1028,66 @@ td::Status GetValidatorSessionsInfoQuery::receive(td::BufferSlice data) { td::TerminalIO::out() << "---------\n" << s << "--------\n"; return td::Status::OK(); } + +td::Status GenerateBlockCandidateQuery::run() { + TRY_RESULT_ASSIGN(wc_, tokenizer_.get_token()); + TRY_RESULT_ASSIGN(shard_, tokenizer_.get_token() ); + TRY_RESULT_ASSIGN(seqno_, tokenizer_.get_token()); + TRY_RESULT_ASSIGN(file_, tokenizer_.get_token()); + return td::Status::OK(); +} + +td::Status GenerateBlockCandidateQuery::send() { + auto b = ton::create_serialize_tl_object( + ton::create_tl_block_id_simple(ton::BlockId(wc_, shard_, seqno_))); + td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); + return td::Status::OK(); +} + +td::Status GenerateBlockCandidateQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX(f, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + TRY_STATUS_PREFIX(td::write_file(file_, data.as_slice()), "failed to write block to file"); + td::TerminalIO::out() << "successfully written candidate to file\n"; + return td::Status::OK(); +} + +td::Status GetRequiredBlockCandidatesQuery::run() { + TRY_STATUS(tokenizer_.check_endl()); + return td::Status::OK(); +} + +td::Status GetRequiredBlockCandidatesQuery::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 GetRequiredBlockCandidatesQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX( + f, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + td::TerminalIO::out() << td::json_encode(td::ToJson(*f), true); + return td::Status::OK(); +} + +td::Status ImportBlockCandidateQuery::run() { + TRY_RESULT_ASSIGN(file_, tokenizer_.get_token()); + return td::Status::OK(); +} + +td::Status ImportBlockCandidateQuery::send() { + TRY_RESULT(data, td::read_file(file_)); + TRY_RESULT_PREFIX(candidate, ton::fetch_tl_object(data.as_slice(), true), + "invalid file: "); + auto b = ton::create_serialize_tl_object(std::move(candidate)); + td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); + return td::Status::OK(); +} + +td::Status ImportBlockCandidateQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX(f, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + td::TerminalIO::out() << "successfully imported a block candidate\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 dea2273d..e4236f6d 100644 --- a/validator-engine-console/validator-engine-console-query.h +++ b/validator-engine-console/validator-engine-console-query.h @@ -1092,6 +1092,74 @@ class GetValidatorSessionsInfoQuery : public Query { std::string name() const override { return get_name(); } +}; + +class GenerateBlockCandidateQuery : public Query { + public: + GenerateBlockCandidateQuery(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 "genblock"; + } + static std::string get_help() { + return "genblock \t" + "generate a block candidate for a given shard (seqno mush match the next seqno for the shard), " + "candidate is saved to "; + } + std::string name() const override { + return get_name(); + } private: + td::int32 wc_; + td::int64 shard_; + td::int32 seqno_; + std::string file_; +}; + +class GetRequiredBlockCandidatesQuery : public Query { + public: + GetRequiredBlockCandidatesQuery(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 "getrequiredblockcandidates"; + } + static std::string get_help() { + return "getrequiredblockcandidates\t" + "get a list of block candidates that the validator is currently waiting for"; + } + std::string name() const override { + return get_name(); + } +}; + +class ImportBlockCandidateQuery : public Query { + public: + ImportBlockCandidateQuery(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 "importblockcandidate"; + } + static std::string get_help() { + return "importblockcandidate \t" + "load a block candidate from a given file"; + } + std::string name() const override { + return get_name(); + } + + private: + std::string file_; }; diff --git a/validator-engine-console/validator-engine-console.cpp b/validator-engine-console/validator-engine-console.cpp index 2c04971b..b4dcad22 100644 --- a/validator-engine-console/validator-engine-console.cpp +++ b/validator-engine-console/validator-engine-console.cpp @@ -141,6 +141,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 7783dc38..2e158e07 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -3307,6 +3307,94 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_getValida std::move(P)); } +void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_generateBlockCandidate &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 (validator_manager_.empty()) { + promise.set_value( + create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "validator manager not started"))); + return; + } + ton::BlockId block_id = ton::create_block_id_simple(query.block_id_); + td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManagerInterface::generate_block_candidate, + block_id, [promise = std::move(promise)](td::Result R) mutable { + if (R.is_ok()) { + auto block = R.move_as_ok(); + auto result = ton::create_serialize_tl_object( + ton::PublicKey{ton::pubkeys::Ed25519{block.pubkey.as_bits256()}}.tl(), + ton::create_tl_block_id(block.id), std::move(block.data), + std::move(block.collated_data)); + promise.set_result(std::move(result)); + } else { + promise.set_value(create_control_query_error(R.move_as_error())); + } + }); +} + +void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_getRequiredBlockCandidates &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 (validator_manager_.empty()) { + promise.set_value( + create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "validator manager not started"))); + return; + } + td::actor::send_closure( + validator_manager_, &ton::validator::ValidatorManagerInterface::get_required_block_candidates, + [promise = std::move(promise)](td::Result> R) mutable { + if (R.is_ok()) { + std::vector> block_ids; + for (const ton::BlockId &block_id : R.move_as_ok()) { + block_ids.push_back(ton::create_tl_block_id_simple(block_id)); + } + auto result = ton::create_serialize_tl_object( + std::move(block_ids)); + promise.set_result(std::move(result)); + } else { + promise.set_value(create_control_query_error(R.move_as_error())); + } + }); +} + +void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_importBlockCandidate &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 (validator_manager_.empty()) { + promise.set_value( + create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "validator manager not started"))); + return; + } + + auto collated_data_hash = td::sha256_bits256(query.block_->collated_data_); + auto key = ton::PublicKey{query.block_->source_}; + auto e_key = ton::Ed25519_PublicKey{key.ed25519_value().raw()}; + ton::BlockCandidate candidate{e_key, ton::create_block_id(query.block_->id_), collated_data_hash, + std::move(query.block_->data_), std::move(query.block_->collated_data_)}; + + td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManagerInterface::import_block_candidate, + std::move(candidate), + [promise = std::move(promise)](td::Result R) mutable { + if (R.is_ok()) { + promise.set_result(ton::serialize_tl_object( + ton::create_tl_object(), true)); + } else { + promise.set_value(create_control_query_error(R.move_as_error())); + } + }); +} + void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data, td::Promise promise) { diff --git a/validator-engine/validator-engine.hpp b/validator-engine/validator-engine.hpp index e0364bab..beb24237 100644 --- a/validator-engine/validator-engine.hpp +++ b/validator-engine/validator-engine.hpp @@ -409,6 +409,12 @@ class ValidatorEngine : public td::actor::Actor { ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); void run_control_query(ton::ton_api::engine_validator_getValidatorSessionsInfo &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); + void run_control_query(ton::ton_api::engine_validator_generateBlockCandidate &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); + void run_control_query(ton::ton_api::engine_validator_getRequiredBlockCandidates &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); + void run_control_query(ton::ton_api::engine_validator_importBlockCandidate &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/impl/validate-query.cpp b/validator/impl/validate-query.cpp index b9347fcf..bd0d3b2a 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -449,6 +449,7 @@ bool ValidateQuery::init_parse() { return reject_query("after_merge value mismatch in block header"); } rand_seed_ = extra.rand_seed; + created_by_ = extra.created_by; if (created_by_ != extra.created_by) { return reject_query("block candidate "s + id_.to_str() + " has creator " + created_by_.to_hex() + " but the block header contains different value " + extra.created_by.to_hex()); diff --git a/validator/interfaces/validator-manager.h b/validator/interfaces/validator-manager.h index 4ee276d3..c72ec307 100644 --- a/validator/interfaces/validator-manager.h +++ b/validator/interfaces/validator-manager.h @@ -169,6 +169,8 @@ class ValidatorManager : public ValidatorManagerInterface { virtual void log_validator_session_stats(BlockIdExt block_id, validatorsession::ValidatorSessionStats stats) = 0; + virtual void wait_block_candidate(BlockId block_id, td::Timestamp timeout, td::Promise promise) = 0; + static bool is_persistent_state(UnixTime ts, UnixTime prev_ts) { return ts / (1 << 17) != prev_ts / (1 << 17); } diff --git a/validator/manager-disk.hpp b/validator/manager-disk.hpp index 3f98273e..6bad1171 100644 --- a/validator/manager-disk.hpp +++ b/validator/manager-disk.hpp @@ -371,6 +371,18 @@ class ValidatorManagerImpl : public ValidatorManager { td::Promise> promise) override { UNREACHABLE(); } + void generate_block_candidate(BlockId block_id, td::Promise promise) override { + UNREACHABLE(); + } + void get_required_block_candidates(td::Promise> promise) override { + UNREACHABLE(); + } + void import_block_candidate(BlockCandidate candidate, td::Promise promise) override { + UNREACHABLE(); + } + void wait_block_candidate(BlockId block_id, td::Timestamp timeout, td::Promise promise) override { + UNREACHABLE(); + } private: PublicKeyHash local_id_; diff --git a/validator/manager-hardfork.hpp b/validator/manager-hardfork.hpp index 17042dbf..a8aaecfc 100644 --- a/validator/manager-hardfork.hpp +++ b/validator/manager-hardfork.hpp @@ -430,6 +430,19 @@ class ValidatorManagerImpl : public ValidatorManager { td::Promise> promise) override { UNREACHABLE(); } + void generate_block_candidate(BlockId block_id, td::Promise promise) override { + UNREACHABLE(); + } + void get_required_block_candidates(td::Promise> promise) override { + UNREACHABLE(); + } + void import_block_candidate(BlockCandidate candidate, td::Promise promise) override { + UNREACHABLE(); + } + void wait_block_candidate(BlockId block_id, td::Timestamp timeout, td::Promise promise) override { + UNREACHABLE(); + } + private: td::Ref opts_; diff --git a/validator/manager.cpp b/validator/manager.cpp index 81cd2e0e..0d8929ac 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -2031,7 +2031,7 @@ td::actor::ActorOwn ValidatorManagerImpl::create_validator_group auto G = td::actor::create_actor( "validatorgroup", shard, validator_id, session_id, validator_set, opts, keyring_, adnl_, rldp_, overlays_, db_root_, actor_id(this), init_session, - opts_->check_unsafe_resync_allowed(validator_set->get_catchain_seqno())); + opts_->check_unsafe_resync_allowed(validator_set->get_catchain_seqno()), true); return G; } } @@ -2583,6 +2583,119 @@ void ValidatorManagerImpl::get_validator_sessions_info( IntermediateData::step({std::move(groups), {}, std::move(promise)}); } +void ValidatorManagerImpl::generate_block_candidate(BlockId block_id, td::Promise promise) { + if (!block_id.is_valid_full()) { + promise.set_error(td::Status::Error("invalid block id")); + return; + } + if (last_masterchain_state_.is_null()) { + promise.set_error(td::Status::Error("not started")); + return; + } + ShardIdFull shard_id = block_id.shard_full(); + std::vector prev; + auto shard = last_masterchain_state_->get_shard_from_config(shard_id); + if (shard.not_null()) { + if (shard->before_split()) { + promise.set_error(td::Status::Error("shard is before_split")); + return; + } + if (shard->before_merge()) { + promise.set_error(td::Status::Error("shard is before_merge")); + return; + } + prev.push_back(shard->top_block_id()); + } else { + auto parent = shard_id.pfx_len() == 0 ? td::Ref() + : last_masterchain_state_->get_shard_from_config(shard_parent(shard_id)); + if (parent.not_null() && parent->before_split()) { + prev.push_back(parent->top_block_id()); + } else { + auto child_l = last_masterchain_state_->get_shard_from_config(shard_child(shard_id, true)); + auto child_r = last_masterchain_state_->get_shard_from_config(shard_child(shard_id, false)); + if (child_l.not_null() && child_r.not_null() && child_l->before_merge() && child_r->before_merge()) { + prev.push_back(child_l->top_block_id()); + prev.push_back(child_r->top_block_id()); + } + } + if (prev.empty()) { + promise.set_error(td::Status::Error("no such shard")); + return; + } + } + + BlockSeqno next_seqno = 0; + for (const BlockIdExt& prev_id : prev) { + next_seqno = std::max(next_seqno, prev_id.seqno() + 1); + } + if (next_seqno != block_id.seqno) { + promise.set_error(td::Status::Error(PSTRING() << "seqno mismatch: asked for seqno " << block_id.seqno + << ", but actual next seqno is " << next_seqno)); + return; + } + + Ed25519_PublicKey local_id{Bits256::zero()}; + td::Ref validator_set = last_masterchain_state_->get_validator_set(shard_id); + if (validator_set.is_null()) { + promise.set_error(td::Status::Error("cannot get validator set")); + return; + } + run_collate_query(shard_id, last_masterchain_state_->get_unix_time(), last_masterchain_block_id_, std::move(prev), + local_id, std::move(validator_set), actor_id(this), td::Timestamp::in(10.0), std::move(promise)); +} + +void ValidatorManagerImpl::get_required_block_candidates(td::Promise> promise) { + std::vector block_ids; + for (const auto& p : pending_block_candidates_) { + block_ids.push_back(p.first); + } + promise.set_result(std::move(block_ids)); +} + +void ValidatorManagerImpl::import_block_candidate(BlockCandidate candidate, td::Promise promise) { + auto it = pending_block_candidates_.find(candidate.id.id); + if (it != pending_block_candidates_.end()) { + while (!it->second.empty()) { + auto promise = std::move(it->second.back().first); + it->second.pop_back(); + if (it->second.empty()) { + promise.set_result(std::move(candidate)); + } else { + promise.set_result(candidate.clone()); + } + } + pending_block_candidates_.erase(it); + } + promise.set_result(td::Unit()); +} + +void ValidatorManagerImpl::wait_block_candidate(BlockId block_id, td::Timestamp timeout, + td::Promise promise) { + pending_block_candidates_[block_id].emplace_back(std::move(promise), timeout); + delay_action([SelfId = actor_id(this), block_id, timeout]() { + td::actor::send_closure(SelfId, &ValidatorManagerImpl::cleanup_old_pending_candidates, block_id, timeout); + }, timeout); +} + +void ValidatorManagerImpl::cleanup_old_pending_candidates(BlockId block_id, td::Timestamp now) { + auto it = pending_block_candidates_.find(block_id); + if (it == pending_block_candidates_.end()) { + return; + } + it->second.erase(std::remove_if(it->second.begin(), it->second.end(), + [&](std::pair, td::Timestamp> &p) { + if (p.second.is_in_past(now)) { + p.first.set_error(td::Status::Error(ErrorCode::timeout, "timeout")); + return true; + } + return false; + }), + it->second.end()); + if (it->second.empty()) { + pending_block_candidates_.erase(it); + } +} + td::actor::ActorOwn ValidatorManagerFactory::create( td::Ref opts, std::string db_root, td::actor::ActorId keyring, td::actor::ActorId adnl, td::actor::ActorId rldp, diff --git a/validator/manager.hpp b/validator/manager.hpp index c855e1cc..1fbf60a9 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -534,7 +534,12 @@ class ValidatorManagerImpl : public ValidatorManager { void get_validator_sessions_info( td::Promise> promise) override; - private: + void generate_block_candidate(BlockId block_id, td::Promise promise) override; + void get_required_block_candidates(td::Promise> promise) override; + void import_block_candidate(BlockCandidate candidate, td::Promise promise) override; + void wait_block_candidate(BlockId block_id, td::Timestamp timeout, td::Promise promise) override; + + private: td::Timestamp resend_shard_blocks_at_; td::Timestamp check_waiters_at_; td::Timestamp check_shard_clients_; @@ -598,6 +603,9 @@ class ValidatorManagerImpl : public ValidatorManager { private: std::map> shard_client_waiters_; + + std::map, td::Timestamp>>> pending_block_candidates_; + void cleanup_old_pending_candidates(BlockId block_id, td::Timestamp now); }; } // namespace validator diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp index 333259b4..f5c35798 100644 --- a/validator/validator-group.cpp +++ b/validator/validator-group.cpp @@ -35,6 +35,22 @@ void ValidatorGroup::generate_block_candidate(td::uint32 round_id, td::Promise R) mutable { + if (R.is_error()) { + promise.set_error(R.move_as_error()); + } else { + BlockCandidate candidate = R.move_as_ok(); + candidate.pubkey = pubkey; + promise.set_result(std::move(candidate)); + } + }); + td::actor::send_closure(manager_, &ValidatorManager::wait_block_candidate, create_next_block_id_simple(), + td::Timestamp::in(15.0), std::move(P)); + return; + } run_collate_query(shard_, min_ts_, 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)); @@ -79,7 +95,7 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat VLOG(VALIDATOR_DEBUG) << "validating block candidate " << next_block_id; block.id = next_block_id; run_validate_query(shard_, min_ts_, min_masterchain_block_id_, prev_block_ids_, std::move(block), validator_set_, - manager_, td::Timestamp::in(10.0), std::move(P)); + manager_, td::Timestamp::in(10.0), std::move(P), lite_mode_ ? ValidateMode::lite : 0); } void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block_data, diff --git a/validator/validator-group.hpp b/validator/validator-group.hpp index 3216f5fe..5d760899 100644 --- a/validator/validator-group.hpp +++ b/validator/validator-group.hpp @@ -64,7 +64,7 @@ class ValidatorGroup : public td::actor::Actor { 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) + bool allow_unsafe_self_blocks_resync, bool lite_mode = false) : shard_(shard) , local_id_(std::move(local_id)) , session_id_(session_id) @@ -77,7 +77,8 @@ class ValidatorGroup : public td::actor::Actor { , db_root_(std::move(db_root)) , manager_(validator_manager) , init_(create_session) - , allow_unsafe_self_blocks_resync_(allow_unsafe_self_blocks_resync) { + , allow_unsafe_self_blocks_resync_(allow_unsafe_self_blocks_resync) + , lite_mode_(lite_mode) { } private: @@ -118,6 +119,7 @@ class ValidatorGroup : public td::actor::Actor { bool init_ = false; bool started_ = false; bool allow_unsafe_self_blocks_resync_; + bool lite_mode_ = false; td::uint32 last_known_round_id_ = 0; }; diff --git a/validator/validator.h b/validator/validator.h index b3d32e30..09081f1e 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -216,6 +216,10 @@ class ValidatorManagerInterface : public td::actor::Actor { virtual void prepare_stats(td::Promise>> promise) = 0; virtual void get_validator_sessions_info( td::Promise> promise) = 0; + + virtual void generate_block_candidate(BlockId block_id, td::Promise promise) = 0; + virtual void get_required_block_candidates(td::Promise> promise) = 0; + virtual void import_block_candidate(BlockCandidate candidate, td::Promise promise) = 0; }; } // namespace validator