1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-14 20:22:19 +00:00

Changes in validation

* Configure collator list in validator-console
* Remove "lite-validator" flags
* Better compatibility in validate-query.cpp
This commit is contained in:
SpyCheese 2024-06-11 11:29:52 +03:00
parent f91ed6cc31
commit 38ab70c037
16 changed files with 368 additions and 107 deletions

View file

@ -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;

Binary file not shown.

View file

@ -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<std::string>());
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<ton::ton_api::engine_validator_collatorsList>();
TRY_STATUS(ton::ton_api::from_json(*list, json.get_object()));
auto b = ton::create_serialize_tl_object<ton::ton_api::engine_validator_setCollatorsList>(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<ton::ton_api::engine_validator_success>(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<ton::ton_api::engine_validator_collatorsList>();
list->self_collate_ = true;
auto b = ton::create_serialize_tl_object<ton::ton_api::engine_validator_setCollatorsList>(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<ton::ton_api::engine_validator_success>(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<ton::ton_api::engine_validator_showCollatorsList>();
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<ton::ton_api::engine_validator_collatorsList>(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();
}

View file

@ -1342,3 +1342,63 @@ class DelShardQuery : public Query {
td::int32 wc_;
td::int64 shard_;
};
class SetCollatorsListQuery : public Query {
public:
SetCollatorsListQuery(td::actor::ActorId<ValidatorEngineConsole> 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 <filename>\tset list of collators from file <filename>";
}
std::string name() const override {
return get_name();
}
private:
std::string file_name_;
};
class ClearCollatorsListQuery : public Query {
public:
ClearCollatorsListQuery(td::actor::ActorId<ValidatorEngineConsole> 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<ValidatorEngineConsole> 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();
}
};

View file

@ -152,6 +152,9 @@ void ValidatorEngineConsole::run() {
add_query_runner(std::make_unique<QueryRunnerImpl<AddShardQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<DelShardQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<DelCollatorQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<SetCollatorsListQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<ClearCollatorsListQuery>>());
add_query_runner(std::make_unique<QueryRunnerImpl<ShowCollatorsListQuery>>());
}
bool ValidatorEngineConsole::envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) {

View file

@ -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<ton::ton_api::engine_validator_collatorsList>();
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<ton::validator::CollatorsList> list{true};
list.write().unpack(*collators_list_);
validator_options_.write().set_collators_list(std::move(list));
}
void ValidatorEngine::load_empty_local_config(td::Promise<td::Unit> promise) {
auto ret_promise = td::PromiseCreator::lambda(
[SelfId = actor_id(this), promise = std::move(promise)](td::Result<td::Unit> 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<td::BufferSlice> 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<std::string>(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<ton::validator::CollatorsList> 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<ton::ton_api::engine_validator_success>(), true));
}
void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_showCollatorsList &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> 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<ton::ton_api::engine_validator_collatorsList>();
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<td::BufferSlice> 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) {

View file

@ -184,6 +184,7 @@ class ValidatorEngine : public td::actor::Actor {
td::Ref<ton::validator::ValidatorManagerOptions> validator_options_;
Config config_;
ton::tl_object_ptr<ton::ton_api::engine_validator_customOverlaysConfig> custom_overlays_config_;
ton::tl_object_ptr<ton::ton_api::engine_validator_collatorsList> collators_list_;
std::set<ton::PublicKeyHash> 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<ton::CatchainSeqno> unsafe_catchains_;
std::map<ton::BlockSeqno, std::pair<ton::CatchainSeqno, td::uint32>> 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<td::Unit> promise);
void load_config(td::Promise<td::Unit> 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<td::BufferSlice> promise);
void run_control_query(ton::ton_api::engine_validator_setStateSerializerEnabled &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
void run_control_query(ton::ton_api::engine_validator_setCollatorsList &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
void run_control_query(ton::ton_api::engine_validator_showCollatorsList &query, td::BufferSlice data,
ton::PublicKeyHash src, td::uint32 perm, td::Promise<td::BufferSlice> promise);
template <class T>
void run_control_query(T &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm,
td::Promise<td::BufferSlice> promise) {

View file

@ -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<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_,

View file

@ -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<vm::Cell> 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;
}

View file

@ -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::Ref<ShardTopBlockDesc
});
wait_block_state_short(desc->block_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<ShardTopBlockDesc
void ValidatorManagerImpl::preload_msg_queue_to_masterchain(td::Ref<ShardTopBlockDescription> 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<ShardIdFull> 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<ValidatorGroup> ValidatorManagerImpl::create_validator_group
auto G = td::actor::create_actor<ValidatorGroup>(
"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<ValidatorSet> 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<ValidatorManagerOptions> 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 {

View file

@ -560,9 +560,7 @@ class ValidatorManagerImpl : public ValidatorManager {
void read_gc_list(std::vector<ValidatorSessionId> list);
bool is_validator();
bool is_collator();
bool validating_masterchain();
bool collating_masterchain();
PublicKeyHash get_validator(ShardIdFull shard, td::Ref<ValidatorSet> val_set);
ValidatorManagerImpl(td::Ref<ValidatorManagerOptions> opts, std::string db_root,
@ -767,7 +765,6 @@ class ValidatorManagerImpl : public ValidatorManager {
std::set<ShardIdFull> shards;
};
std::map<adnl::AdnlNodeIdShort, Collator> collator_nodes_;
size_t masterchain_collators_ = 0;
std::set<ShardIdFull> extra_active_shards_;
std::map<ShardIdFull, BlockSeqno> last_validated_blocks_;

View file

@ -57,14 +57,7 @@ void ValidatorGroup::generate_block_candidate(
cache = cached_collated_block_](td::Result<BlockCandidate> 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<CachedCollatedBlock> 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<BlockData>
}
});
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<BlockCandidate> promise,
unsigned max_retries) {
void ValidatorGroup::collate_block(td::uint32 round_id, td::Timestamp timeout, td::Promise<BlockCandidate> 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<td::BufferSlice> R) mutable {
[=, SelfId = actor_id(this), promise = std::move(promise)](td::Result<td::BufferSlice> 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<BlockCandidate> 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<std::pair<UnixTime, bool>> R) mutable {
if (R.is_error()) {

View file

@ -66,13 +66,18 @@ class ValidatorGroup : public td::actor::Actor {
void get_session_info(td::Promise<tl_object_ptr<ton_api::engine_validator_validatorSessionInfo>> promise);
void update_options(td::Ref<ValidatorManagerOptions> opts, bool apply_blocks) {
opts_ = std::move(opts);
apply_blocks_ = apply_blocks;
}
ValidatorGroup(ShardIdFull shard, PublicKeyHash local_id, ValidatorSessionId session_id,
td::Ref<ValidatorSet> validator_set, block::CollatorConfig collator_config,
validatorsession::ValidatorSessionOptions config,
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl,
td::actor::ActorId<rldp::Rldp> rldp, td::actor::ActorId<overlay::Overlays> overlays,
std::string db_root, td::actor::ActorId<ValidatorManager> validator_manager, bool create_session,
bool allow_unsafe_self_blocks_resync, td::Ref<ValidatorManagerOptions> opts)
bool allow_unsafe_self_blocks_resync, td::Ref<ValidatorManagerOptions> 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<validatorsession::ValidatorSession::Callback> make_validator_session_callback();
void send_collate_query(td::uint32 round_id, td::Timestamp timeout, td::Promise<BlockCandidate> promise,
void collate_block(td::uint32 round_id, td::Timestamp timeout, td::Promise<BlockCandidate> promise,
unsigned max_retries = 4);
void receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, td::Promise<BlockCandidate> promise);
void receive_collate_query_response(td::uint32 round_id, td::BufferSlice data, bool trusted_collator,
td::Promise<BlockCandidate> promise);
struct PostponedAccept {
RootHash root_hash;
@ -134,6 +141,7 @@ class ValidatorGroup : public td::actor::Actor {
bool allow_unsafe_self_blocks_resync_;
td::Ref<ValidatorManagerOptions> opts_;
td::uint32 last_known_round_id_ = 0;
bool apply_blocks_ = true;
struct CachedCollatedBlock {
td::optional<BlockCandidate> result;

View file

@ -20,10 +20,26 @@
#include "ton/ton-shard.h"
#include <ton/ton-tl.hpp>
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> ValidatorManagerOptions::create(
BlockIdExt zero_block_id, BlockIdExt init_block_id,
std::function<bool(ShardIdFull)> check_shard, bool allow_blockchain_init,

View file

@ -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<CollatorsList> 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<CollatorsList> 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<double> catchain_max_block_delay_;
bool state_serializer_enabled_ = true;
ValidatorMode validator_mode_ = validator_normal;
td::Ref<CollatorsList> collators_list_{true, CollatorsList{}};
};
} // namespace validator

View file

@ -52,10 +52,24 @@ struct PerfTimerStats {
std::deque<std::pair<double, double>> stats; // <Time::now(), duration>
};
struct CollatorsList : public td::CntObject {
struct Collator {
adnl::AdnlNodeIdShort adnl_id;
bool trusted;
};
struct Shard {
ShardIdFull shard_id;
std::vector<Collator> collators;
};
bool self_collate = true;
bool use_config_41 = false;
std::vector<Shard> 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<MasterchainState>& state) const = 0;
@ -91,7 +105,7 @@ struct ValidatorManagerOptions : public td::CntObject {
virtual bool get_celldb_preload_all() const = 0;
virtual td::optional<double> get_catchain_max_block_delay() const = 0;
virtual bool get_state_serializer_enabled() const = 0;
virtual ValidatorMode validator_mode() const = 0;
virtual td::Ref<CollatorsList> 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<CollatorsList> list) = 0;
static td::Ref<ValidatorManagerOptions> create(
BlockIdExt zero_block_id, BlockIdExt init_block_id,