1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

changed validate broadcast logic, added new queries to

validator-engine-console
This commit is contained in:
ton 2019-09-11 16:50:29 +04:00
parent 47814dca3d
commit d8244eff53
24 changed files with 695 additions and 84 deletions

View file

@ -9,6 +9,7 @@ set(TON_VALIDATOR_SOURCE
block.cpp
check-proof.cpp
collator.cpp
config.cpp
external-message.cpp
fabric.cpp
ihr-message.cpp
@ -27,6 +28,7 @@ set(TON_VALIDATOR_SOURCE
collate-query-impl.h
collator-impl.h
collator.h
config.hpp
external-message.hpp
ihr-message.hpp
liteserver.hpp

58
validator/impl/config.cpp Normal file
View file

@ -0,0 +1,58 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "config.hpp"
#include "block/block-parse.h"
#include "block/block-auto.h"
#include "vm/boc.h"
#include "vm/cells/MerkleProof.h"
#include "validator-set.hpp"
namespace ton {
namespace validator {
td::Ref<ValidatorSet> ConfigHolderQ::get_total_validator_set(int next) const {
if (!config_) {
LOG(ERROR) << "MasterchainStateQ::get_total_validator_set() : no config";
return {};
}
auto nodes = config_->compute_total_validator_set(next);
if (nodes.empty()) {
return {};
}
return Ref<ValidatorSetQ>{true, 0, ton::ShardIdFull{}, std::move(nodes)};
}
td::Ref<ValidatorSet> ConfigHolderQ::get_validator_set(ShardIdFull shard, UnixTime utime,
CatchainSeqno cc_seqno) const {
if (!config_) {
LOG(ERROR) << "MasterchainStateQ::get_validator_set() : no config";
return {};
}
auto nodes = config_->compute_validator_set(shard, utime, cc_seqno);
if (nodes.empty()) {
return {};
}
return Ref<ValidatorSetQ>{true, cc_seqno, shard, std::move(nodes)};
}
} // namespace validator
} // namespace ton

50
validator/impl/config.hpp Normal file
View file

@ -0,0 +1,50 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "validator/interfaces/config.h"
namespace ton {
namespace validator {
using td::Ref;
class ConfigHolderQ : public ConfigHolder {
std::shared_ptr<block::Config> config_;
std::shared_ptr<vm::StaticBagOfCellsDb> boc_;
public:
ConfigHolderQ() = default;
ConfigHolderQ(std::shared_ptr<block::Config> config, std::shared_ptr<vm::StaticBagOfCellsDb> boc)
: config_(std::move(config)), boc_(std::move(boc)) {
}
ConfigHolderQ(std::shared_ptr<block::Config> config) : config_(std::move(config)) {
}
const block::Config *get_config() const {
return config_.get();
}
ConfigHolderQ *make_copy() const override {
return new ConfigHolderQ(*this);
}
// if necessary, add more public methods providing interface to config_->...()
td::Ref<ValidatorSet> get_total_validator_set(int next) const override; // next = -1 -> prev, next = 0 -> cur
td::Ref<ValidatorSet> get_validator_set(ShardIdFull shard, UnixTime utime, CatchainSeqno seqno) const override;
};
} // namespace validator
} // namespace ton

View file

@ -43,10 +43,10 @@ td::Result<Ref<ProofLink>> ProofQ::export_as_proof_link() const {
}
td::Result<BlockSeqno> ProofLinkQ::prev_key_mc_seqno() const {
if (!id_.is_masterchain()) {
return td::Status::Error(
-668, "cannot compute previous key masterchain block from ProofLink of non-masterchain block "s + id_.to_str());
}
//if (!id_.is_masterchain()) {
// return td::Status::Error(
// -668, "cannot compute previous key masterchain block from ProofLink of non-masterchain block "s + id_.to_str());
//}
TRY_RESULT(pair, get_virtual_root(true));
try {
block::gen::Block::Record blk;
@ -68,8 +68,7 @@ td::Result<td::Ref<ConfigHolder>> ProofLinkQ::get_key_block_config() const {
}
TRY_RESULT(pair, get_virtual_root(true));
try {
TRY_RESULT(cfg, block::Config::extract_from_key_block(
std::move(pair.first), block::Config::needValidatorSet | block::Config::needWorkchainInfo));
TRY_RESULT(cfg, block::Config::extract_from_key_block(std::move(pair.first), block::Config::needValidatorSet));
return td::make_ref<ConfigHolderQ>(std::move(cfg), std::move(pair.second));
} catch (vm::VmVirtError &) {
return td::Status::Error(-668,
@ -77,6 +76,26 @@ td::Result<td::Ref<ConfigHolder>> ProofLinkQ::get_key_block_config() const {
}
}
td::Result<ProofLink::BasicHeaderInfo> ProofLinkQ::get_basic_header_info() const {
BasicHeaderInfo res;
TRY_RESULT(pair, get_virtual_root(true));
try {
block::gen::Block::Record blk;
block::gen::BlockInfo::Record info;
if (!(tlb::unpack_cell(std::move(pair.first), blk) && tlb::unpack_cell(blk.info, info) && !info.version)) {
return td::Status::Error(-668,
"cannot unpack block header in the Merkle proof for masterchain block "s + id_.to_str());
}
res.cc_seqno = info.gen_catchain_seqno;
res.utime = info.gen_utime;
res.validator_set_hash = info.gen_validator_list_hash_short;
res.prev_key_mc_seqno = info.prev_key_block_seqno;
return res;
} catch (vm::VmVirtError &) {
return td::Status::Error(-668, "virtualization error in masterchain block proof for "s + id_.to_str());
}
}
td::Result<std::pair<Ref<vm::Cell>, std::shared_ptr<vm::StaticBagOfCellsDb>>> ProofLinkQ::get_virtual_root(
bool lazy) const {
if (data_.empty()) {
@ -127,17 +146,5 @@ td::Result<std::pair<Ref<vm::Cell>, std::shared_ptr<vm::StaticBagOfCellsDb>>> Pr
return std::make_pair(std::move(virt_root), std::move(boc));
}
td::Ref<ValidatorSet> ConfigHolderQ::get_total_validator_set(int next) const {
if (!config_) {
LOG(ERROR) << "MasterchainStateQ::get_total_validator_set() : no config";
return {};
}
auto nodes = config_->compute_total_validator_set(next);
if (nodes.empty()) {
return {};
}
return Ref<ValidatorSetQ>{true, 0, ton::ShardIdFull{}, std::move(nodes)};
}
} // namespace validator
} // namespace ton

View file

@ -22,32 +22,12 @@
#include "block/block-db.h"
#include "block/mc-config.h"
#include "vm/db/StaticBagOfCellsDb.h"
#include "config.hpp"
namespace ton {
namespace validator {
using td::Ref;
class ConfigHolderQ : public ConfigHolder {
std::shared_ptr<block::Config> config_;
std::shared_ptr<vm::StaticBagOfCellsDb> boc_;
public:
ConfigHolderQ() = default;
ConfigHolderQ(std::shared_ptr<block::Config> config, std::shared_ptr<vm::StaticBagOfCellsDb> boc)
: config_(std::move(config)), boc_(std::move(boc)) {
}
ConfigHolderQ(std::shared_ptr<block::Config> config) : config_(std::move(config)) {
}
const block::Config *get_config() const {
return config_.get();
}
ConfigHolderQ *make_copy() const override {
return new ConfigHolderQ(*this);
}
// if necessary, add more public methods providing interface to config_->...()
td::Ref<ValidatorSet> get_total_validator_set(int next) const override; // next = -1 -> prev, next = 0 -> cur
};
class ProofLinkQ : virtual public ProofLink {
protected:
BlockIdExt id_;
@ -67,6 +47,7 @@ class ProofLinkQ : virtual public ProofLink {
}
td::Result<BlockSeqno> prev_key_mc_seqno() const override;
td::Result<td::Ref<ConfigHolder>> get_key_block_config() const override;
td::Result<BasicHeaderInfo> get_basic_header_info() const override;
protected:
td::Result<std::pair<Ref<vm::Cell>, std::shared_ptr<vm::StaticBagOfCellsDb>>> get_virtual_root(

View file

@ -20,6 +20,7 @@
#include "interfaces/shard.h"
#include "vm/db/StaticBagOfCellsDb.h"
#include "block/mc-config.h"
#include "config.hpp"
namespace ton {
@ -138,6 +139,13 @@ class MasterchainStateQ : public MasterchainState, public ShardStateQ {
std::shared_ptr<block::ConfigInfo> get_config() const {
return config_;
}
td::Result<td::Ref<ConfigHolder>> get_key_block_config() const override {
if (!config_) {
return td::Status::Error(ErrorCode::notready, "config not found");
} else {
return td::make_ref<ConfigHolderQ>(config_);
}
}
private:
ZeroStateIdExt zerostate_id_;

View file

@ -665,9 +665,7 @@ bool ValidateQuery::try_unpack_mc_state() {
}
config_ = res.move_as_ok();
CHECK(config_);
if (mc_seqno_) {
config_->set_block_id_ext(mc_blkid_);
}
config_->set_block_id_ext(mc_blkid_);
old_shard_conf_ = std::make_unique<block::ShardConfig>(*config_);
if (!is_masterchain()) {
new_shard_conf_ = std::make_unique<block::ShardConfig>(*config_);
@ -684,6 +682,11 @@ bool ValidateQuery::try_unpack_mc_state() {
} else {
prev_key_block_seqno_ = 0;
}
if (prev_key_seqno_ != prev_key_block_seqno_) {
return reject_query(PSTRING() << "previous key block seqno value in candidate block header is " << prev_key_seqno_
<< " while the correct value corresponding to reference masterchain state "
<< mc_blkid_.to_str() << " is " << prev_key_block_seqno_);
}
auto limits = config_->get_block_limits(is_masterchain());
if (limits.is_error()) {
return fatal_error(limits.move_as_error());
@ -5002,7 +5005,7 @@ bool ValidateQuery::check_mc_state_extra() {
} else if (!new_extra.r1.last_key_block->prefetch_ulong(1)) {
return reject_query("last_key_block:(Maybe ExtBlkRef) changed in the new state, but it became a nothing$0");
} else {
auto& cs = new_extra.r1.last_key_block.write();
vm::CellSlice cs = *new_extra.r1.last_key_block;
BlockIdExt blkid;
LogicalTime lt;
CHECK(cs.fetch_ulong(1) == 1 && block::tlb::t_ExtBlkRef.unpack(cs, blkid, &lt));
@ -5017,6 +5020,20 @@ bool ValidateQuery::check_mc_state_extra() {
", but it is not a key block");
}
}
if (new_extra.r1.last_key_block->prefetch_ulong(1)) {
auto& cs = new_extra.r1.last_key_block.write();
BlockIdExt blkid;
LogicalTime lt;
CHECK(cs.fetch_ulong(1) == 1 && block::tlb::t_ExtBlkRef.unpack(cs, blkid, &lt));
if (blkid != prev_key_block_) {
return reject_query("new masterchain state declares previous key block to be "s + blkid.to_str() +
" but the value computed from previous masterchain state is " + prev_key_block_.to_str());
}
} else if (prev_key_block_seqno_ > 0) {
return reject_query(PSTRING() << "new masterchain state declares no previous key block, but the block header "
"announces previous key block seqno "
<< prev_key_block_seqno_);
}
// global_balance:CurrencyCollection
block::CurrencyCollection global_balance, old_global_balance;
if (!global_balance.validate_unpack(new_extra.global_balance)) {

View file

@ -34,6 +34,7 @@ class ConfigHolder : public td::CntObject {
virtual ~ConfigHolder() = default;
virtual td::Ref<ValidatorSet> get_total_validator_set(int next) const = 0; // next = -1 -> prev, next = 0 -> cur
virtual td::Ref<ValidatorSet> get_validator_set(ShardIdFull shard, UnixTime utime, CatchainSeqno seqno) const = 0;
};
} // namespace validator

View file

@ -27,11 +27,18 @@ namespace validator {
class ProofLink : public td::CntObject {
public:
struct BasicHeaderInfo {
UnixTime utime;
CatchainSeqno cc_seqno;
td::uint32 validator_set_hash;
BlockSeqno prev_key_mc_seqno;
};
virtual ~ProofLink() = default;
virtual BlockIdExt block_id() const = 0;
virtual td::BufferSlice data() const = 0;
virtual td::Result<BlockSeqno> prev_key_mc_seqno() const = 0;
virtual td::Result<td::Ref<ConfigHolder>> get_key_block_config() const = 0;
virtual td::Result<BasicHeaderInfo> get_basic_header_info() const = 0;
};
class Proof : virtual public ProofLink {

View file

@ -79,6 +79,7 @@ class MasterchainState : virtual public ShardState {
virtual bool get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid,
ton::LogicalTime* end_lt = nullptr) const = 0;
virtual bool check_old_mc_block_id(const ton::BlockIdExt& blkid, bool strict = false) const = 0;
virtual td::Result<td::Ref<ConfigHolder>> get_key_block_config() const = 0;
virtual td::Status prepare() {
return td::Status::OK();
}

View file

@ -1908,12 +1908,14 @@ void ValidatorManagerImpl::send_peek_key_block_request() {
}
void ValidatorManagerImpl::prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) {
std::vector<std::pair<std::string, std::string>> vec;
vec.emplace_back("unixtime", td::to_string(static_cast<UnixTime>(td::Clocks::system())));
if (!last_masterchain_block_handle_) {
promise.set_value(std::vector<std::pair<std::string, std::string>>());
promise.set_value(std::move(vec));
return;
}
std::vector<std::pair<std::string, std::string>> vec;
vec.emplace_back("masterchainblock", last_masterchain_block_id_.to_str());
vec.emplace_back("masterchainblocktime", td::to_string(last_masterchain_block_handle_->unix_time()));
vec.emplace_back("gcmasterchainblock", gc_masterchain_handle_->id().to_str());
vec.emplace_back("keymasterchainblock", last_key_block_handle_->id().to_str());
vec.emplace_back("knownkeymasterchainblock", last_known_key_block_handle_->id().to_str());

View file

@ -69,33 +69,150 @@ void ValidateBroadcast::start_up() {
return;
}
auto val_set = last_masterchain_state_->get_validator_set(broadcast_.block_id.shard_full());
if (val_set.not_null() && val_set->get_catchain_seqno() == broadcast_.catchain_seqno &&
val_set->get_validator_set_hash() == broadcast_.validator_set_hash) {
auto S = val_set->check_signatures(broadcast_.block_id.root_hash, broadcast_.block_id.file_hash, sig_set_);
if (S.is_ok()) {
checked_signatures();
if (broadcast_.block_id.is_masterchain()) {
auto R = create_proof(broadcast_.block_id, broadcast_.proof.clone());
if (R.is_error()) {
abort_query(R.move_as_error_prefix("bad proof: "));
return;
}
proof_ = R.move_as_ok();
auto hR = proof_->get_basic_header_info();
if (hR.is_error()) {
abort_query(hR.move_as_error_prefix("bad proof: "));
return;
}
header_info_ = hR.move_as_ok();
} else {
auto R = create_proof_link(broadcast_.block_id, broadcast_.proof.clone());
if (R.is_error()) {
abort_query(R.move_as_error_prefix("bad proof link: "));
return;
}
proof_link_ = R.move_as_ok();
auto hR = proof_link_->get_basic_header_info();
if (hR.is_error()) {
abort_query(hR.move_as_error_prefix("bad proof link: "));
return;
}
header_info_ = hR.move_as_ok();
}
BlockSeqno key_block_seqno = header_info_.prev_key_mc_seqno;
exact_key_block_handle_ = key_block_seqno <= last_known_masterchain_block_handle_->id().seqno();
if (key_block_seqno < last_known_masterchain_block_handle_->id().seqno()) {
if (key_block_seqno < last_masterchain_state_->get_seqno()) {
BlockIdExt block_id;
if (!last_masterchain_state_->get_old_mc_block_id(key_block_seqno, block_id)) {
abort_query(td::Status::Error(ErrorCode::error, "too old reference key block"));
return;
}
got_key_block_id(block_id);
} else if (key_block_seqno == last_masterchain_state_->get_seqno()) {
got_key_block_handle(last_masterchain_block_handle_);
} else {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockIdExt> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
R.move_as_error_prefix("cannot find reference key block id: "));
} else {
td::actor::send_closure(SelfId, &ValidateBroadcast::got_key_block_id, R.move_as_ok());
}
});
td::actor::send_closure(manager_, &ValidatorManager::get_block_by_seqno_from_db,
AccountIdPrefixFull{masterchainId, 0}, key_block_seqno, std::move(P));
}
} else {
got_key_block_handle(last_known_masterchain_block_handle_);
}
}
void ValidateBroadcast::got_key_block_id(BlockIdExt block_id) {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
R.move_as_error_prefix("cannot find reference key block handle: "));
} else {
td::actor::send_closure(SelfId, &ValidateBroadcast::got_key_block_handle, R.move_as_ok());
}
});
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, block_id, false, std::move(P));
}
void ValidateBroadcast::got_key_block_handle(BlockHandle handle) {
if (handle->id().seqno() == 0) {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
R.move_as_error_prefix("failed to get zero state: "));
} else {
td::actor::send_closure(SelfId, &ValidateBroadcast::got_zero_state, td::Ref<MasterchainState>{R.move_as_ok()});
}
});
td::actor::send_closure(manager_, &ValidatorManager::get_shard_state_from_db, handle, std::move(P));
} else {
if (!handle->inited_proof() && !handle->inited_proof_link()) {
abort_query(td::Status::Error(ErrorCode::notready, "reference key block proof not received"));
return;
}
if (!handle->is_key_block()) {
abort_query(td::Status::Error(ErrorCode::protoviolation, "reference key block is not key"));
return;
}
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ProofLink>> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query,
R.move_as_error_prefix("cannot get reference key block proof: "));
} else {
td::actor::send_closure(SelfId, &ValidateBroadcast::got_key_block_proof_link, R.move_as_ok());
}
});
td::actor::send_closure(manager_, &ValidatorManager::get_block_proof_link_from_db, handle, std::move(P));
}
}
void ValidateBroadcast::got_key_block_proof_link(td::Ref<ProofLink> key_proof_link) {
key_proof_link_ = key_proof_link;
auto confR = key_proof_link->get_key_block_config();
if (confR.is_error()) {
abort_query(confR.move_as_error_prefix("failed to extract config from key proof: "));
return;
}
check_signatures_common(confR.move_as_ok());
}
void ValidateBroadcast::got_zero_state(td::Ref<MasterchainState> state) {
zero_state_ = state;
auto confR = state->get_key_block_config();
if (confR.is_error()) {
abort_query(confR.move_as_error_prefix("failed to extract config from zero state: "));
return;
}
check_signatures_common(confR.move_as_ok());
}
void ValidateBroadcast::check_signatures_common(td::Ref<ConfigHolder> conf) {
auto val_set = conf->get_validator_set(broadcast_.block_id.shard_full(), header_info_.utime, header_info_.cc_seqno);
if (val_set.is_null()) {
abort_query(td::Status::Error(ErrorCode::notready, "failed to compute validator set"));
return;
}
if (val_set->get_validator_set_hash() != header_info_.validator_set_hash) {
if (!exact_key_block_handle_) {
abort_query(td::Status::Error(ErrorCode::notready, "too new block, don't know recent enough key block"));
return;
} else {
abort_query(S.move_as_error_prefix("failed signature check: "));
abort_query(td::Status::Error(ErrorCode::notready, "bad validator set hash"));
return;
}
}
val_set = last_masterchain_state_->get_next_validator_set(broadcast_.block_id.shard_full());
if (val_set.not_null() && val_set->get_catchain_seqno() == broadcast_.catchain_seqno &&
val_set->get_validator_set_hash() == broadcast_.validator_set_hash) {
auto S = val_set->check_signatures(broadcast_.block_id.root_hash, broadcast_.block_id.file_hash, sig_set_);
if (S.is_ok()) {
checked_signatures();
return;
} else {
abort_query(S.move_as_error_prefix("failed signature check: "));
return;
}
auto S = val_set->check_signatures(broadcast_.block_id.root_hash, broadcast_.block_id.file_hash, sig_set_);
if (S.is_ok()) {
checked_signatures();
} else {
abort_query(S.move_as_error_prefix("failed signature check: "));
}
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad signature set"));
}
void ValidateBroadcast::checked_signatures() {
@ -142,13 +259,7 @@ void ValidateBroadcast::written_block_data() {
checked_proof();
return;
}
auto proofR = create_proof(broadcast_.block_id, broadcast_.proof.clone());
if (proofR.is_error()) {
abort_query(proofR.move_as_error_prefix("bad proof: "));
return;
}
proof_ = proofR.move_as_ok();
if (handle_->id().id.seqno == last_masterchain_block_handle_->id().id.seqno + 1) {
if (exact_key_block_handle_) {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query, R.move_as_error_prefix("db error: "));
@ -156,7 +267,12 @@ void ValidateBroadcast::written_block_data() {
td::actor::send_closure(SelfId, &ValidateBroadcast::checked_proof);
}
});
run_check_proof_query(broadcast_.block_id, proof_, manager_, timeout_, std::move(P));
if (!key_proof_link_.is_null()) {
run_check_proof_query(broadcast_.block_id, proof_, manager_, timeout_, std::move(P), key_proof_link_);
} else {
CHECK(!zero_state_.not_null());
run_check_proof_query(broadcast_.block_id, proof_, manager_, timeout_, std::move(P), zero_state_);
}
} else {
checked_proof();
}
@ -165,12 +281,6 @@ void ValidateBroadcast::written_block_data() {
checked_proof();
return;
}
auto proofR = create_proof_link(broadcast_.block_id, broadcast_.proof.clone());
if (proofR.is_error()) {
abort_query(proofR.move_as_error());
return;
}
proof_link_ = proofR.move_as_ok();
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query, R.move_as_error_prefix("db error: "));
@ -183,7 +293,10 @@ void ValidateBroadcast::written_block_data() {
}
void ValidateBroadcast::checked_proof() {
if (handle_->inited_proof()) {
if (handle_->inited_proof() && handle_->is_key_block()) {
td::actor::send_closure(manager_, &ValidatorManager::update_last_known_key_block, handle_, false);
}
if (handle_->inited_proof() && handle_->id().seqno() - last_masterchain_block_handle_->id().seqno() <= 16) {
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
if (R.is_error()) {
td::actor::send_closure(SelfId, &ValidateBroadcast::abort_query, R.move_as_error());

View file

@ -31,7 +31,8 @@ class ValidateBroadcast : public td::actor::Actor {
BlockHandle last_masterchain_block_handle_;
td::Ref<MasterchainState> last_masterchain_state_;
BlockHandle last_known_masterchain_block_handle_;
td::Ref<Proof> last_known_masterchain_block_proof_;
ProofLink::BasicHeaderInfo header_info_;
td::actor::ActorId<ValidatorManager> manager_;
td::Timestamp timeout_;
@ -45,6 +46,10 @@ class ValidateBroadcast : public td::actor::Actor {
td::PerfWarningTimer perf_timer_{"validatebroadcast", 0.1};
bool exact_key_block_handle_;
td::Ref<ProofLink> key_proof_link_;
td::Ref<MasterchainState> zero_state_;
public:
ValidateBroadcast(BlockBroadcast broadcast, BlockHandle last_masterchain_block_handle,
td::Ref<MasterchainState> last_masterchain_state, BlockHandle last_known_masterchain_block_handle,
@ -59,6 +64,11 @@ class ValidateBroadcast : public td::actor::Actor {
}
void start_up() override;
void got_key_block_id(BlockIdExt block_id);
void got_key_block_handle(BlockHandle block_handle);
void got_key_block_proof_link(td::Ref<ProofLink> proof_link);
void got_zero_state(td::Ref<MasterchainState> state);
void check_signatures_common(td::Ref<ConfigHolder> conf);
void checked_signatures();
void got_block_handle(BlockHandle handle);
void written_block_data();