mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated tonlib, fixed bugs
updated tonlib fixed bugs in func validator: partial support for hardforks liteserver: support for waitMasterchainBlock prefix transactions: support for gas flat rate
This commit is contained in:
parent
841d5ebac2
commit
7ea00ebfcf
89 changed files with 1922 additions and 608 deletions
|
@ -473,6 +473,21 @@ struct BlockHandleImpl : public BlockHandleInterface {
|
|||
}
|
||||
}
|
||||
|
||||
void unsafe_clear_applied() override {
|
||||
if (is_applied()) {
|
||||
lock();
|
||||
flags_ &= ~Flags::dbf_applied;
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
void unsafe_clear_next() override {
|
||||
if (inited_next_left() || inited_next_right()) {
|
||||
lock();
|
||||
flags_ &= ~(Flags::dbf_inited_next_left | Flags::dbf_inited_next_right);
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
td::BufferSlice serialize() const override;
|
||||
BlockHandleImpl(BlockIdExt id)
|
||||
: id_(id), flags_(id_.is_masterchain() ? static_cast<td::uint32>(dbf_masterchain) : 0) {
|
||||
|
|
|
@ -229,6 +229,73 @@ tl_object_ptr<ton_api::db_blockdb_lru> BlockDb::DbEntry::release() {
|
|||
return create_tl_object<ton_api::db_blockdb_lru>(create_tl_block_id(block_id), prev, next);
|
||||
}
|
||||
|
||||
void BlockDb::truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) {
|
||||
std::map<ShardIdFull, BlockSeqno> max_seqno;
|
||||
max_seqno.emplace(ShardIdFull{masterchainId}, state->get_seqno() + 1);
|
||||
|
||||
auto shards = state->get_shards();
|
||||
auto it = KeyHash::zero();
|
||||
kv_->begin_transaction().ensure();
|
||||
while (true) {
|
||||
auto R = get_block_lru(it);
|
||||
R.ensure();
|
||||
auto v = R.move_as_ok();
|
||||
it = v.next;
|
||||
R = get_block_lru(it);
|
||||
R.ensure();
|
||||
v = R.move_as_ok();
|
||||
if (v.is_empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto s = v.block_id.shard_full();
|
||||
if (!max_seqno.count(s)) {
|
||||
bool found = false;
|
||||
for (auto &shard : shards) {
|
||||
if (shard_intersects(shard->shard(), s)) {
|
||||
found = true;
|
||||
max_seqno.emplace(s, shard->top_block_id().seqno() + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
max_seqno.emplace(s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool to_delete = v.block_id.seqno() >= max_seqno[s];
|
||||
if (to_delete) {
|
||||
auto key_hash = get_block_value_key(v.block_id);
|
||||
auto B = get_block_value(key_hash);
|
||||
B.ensure();
|
||||
auto handleR = create_block_handle(B.move_as_ok());
|
||||
handleR.ensure();
|
||||
auto handle = handleR.move_as_ok();
|
||||
|
||||
handle->unsafe_clear_applied();
|
||||
handle->unsafe_clear_next();
|
||||
|
||||
if (handle->need_flush()) {
|
||||
set_block_value(key_hash, handle->serialize());
|
||||
}
|
||||
} else if (v.block_id.seqno() + 1 == max_seqno[s]) {
|
||||
auto key_hash = get_block_value_key(v.block_id);
|
||||
auto B = get_block_value(key_hash);
|
||||
B.ensure();
|
||||
auto handleR = create_block_handle(B.move_as_ok());
|
||||
handleR.ensure();
|
||||
auto handle = handleR.move_as_ok();
|
||||
|
||||
handle->unsafe_clear_next();
|
||||
|
||||
if (handle->need_flush()) {
|
||||
set_block_value(key_hash, handle->serialize());
|
||||
}
|
||||
}
|
||||
}
|
||||
kv_->commit_transaction().ensure();
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -41,6 +41,8 @@ class BlockDb : public td::actor::Actor {
|
|||
void gc();
|
||||
void skip_gc();
|
||||
|
||||
void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise);
|
||||
|
||||
BlockDb(td::actor::ActorId<RootDb> root_db, std::string db_path);
|
||||
|
||||
private:
|
||||
|
|
|
@ -138,7 +138,7 @@ void FileDb::load_file(RefId ref_id, td::Promise<td::BufferSlice> promise) {
|
|||
}
|
||||
});
|
||||
|
||||
td::actor::create_actor<db::ReadFile>("readfile", get_file_name(ref_id, false), 0, -1, std::move(P)).release();
|
||||
td::actor::create_actor<db::ReadFile>("readfile", get_file_name(ref_id, false), 0, -1, 0, std::move(P)).release();
|
||||
}
|
||||
|
||||
void FileDb::load_file_slice(RefId ref_id, td::int64 offset, td::int64 max_size, td::Promise<td::BufferSlice> promise) {
|
||||
|
@ -159,7 +159,7 @@ void FileDb::load_file_slice(RefId ref_id, td::int64 offset, td::int64 max_size,
|
|||
}
|
||||
});
|
||||
|
||||
td::actor::create_actor<db::ReadFile>("readfile", get_file_name(ref_id, false), offset, max_size, std::move(P))
|
||||
td::actor::create_actor<db::ReadFile>("readfile", get_file_name(ref_id, false), offset, max_size, 0, std::move(P))
|
||||
.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -81,25 +81,32 @@ class WriteFile : public td::actor::Actor {
|
|||
|
||||
class ReadFile : public td::actor::Actor {
|
||||
public:
|
||||
enum Flags : td::uint32 { f_disable_log = 1 };
|
||||
void start_up() override {
|
||||
auto S = td::read_file(file_name_, max_length_, offset_);
|
||||
if (S.is_ok()) {
|
||||
promise_.set_result(S.move_as_ok());
|
||||
} else {
|
||||
// TODO check error code
|
||||
LOG(ERROR) << "missing file " << file_name_;
|
||||
if (flags_ & Flags::f_disable_log) {
|
||||
LOG(DEBUG) << "missing file " << file_name_;
|
||||
} else {
|
||||
LOG(ERROR) << "missing file " << file_name_;
|
||||
}
|
||||
promise_.set_error(td::Status::Error(ErrorCode::notready, "file does not exist"));
|
||||
}
|
||||
stop();
|
||||
}
|
||||
ReadFile(std::string file_name, td::int64 offset, td::int64 max_length, td::Promise<td::BufferSlice> promise)
|
||||
: file_name_(file_name), offset_(offset), max_length_(max_length), promise_(std::move(promise)) {
|
||||
ReadFile(std::string file_name, td::int64 offset, td::int64 max_length, td::uint32 flags,
|
||||
td::Promise<td::BufferSlice> promise)
|
||||
: file_name_(file_name), offset_(offset), max_length_(max_length), flags_(flags), promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
private:
|
||||
std::string file_name_;
|
||||
td::int64 offset_;
|
||||
td::int64 max_length_;
|
||||
td::uint32 flags_;
|
||||
td::Promise<td::BufferSlice> promise_;
|
||||
};
|
||||
|
||||
|
|
|
@ -216,6 +216,95 @@ void LtDb::start_up() {
|
|||
kv_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_path_).move_as_ok());
|
||||
}
|
||||
|
||||
void LtDb::truncate_workchain(ShardIdFull shard, td::Ref<MasterchainState> state) {
|
||||
auto key = get_desc_key(shard);
|
||||
std::string value;
|
||||
auto R = kv_->get(key, value);
|
||||
R.ensure();
|
||||
CHECK(R.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
auto F = fetch_tl_object<ton_api::db_lt_desc_value>(td::BufferSlice{value}, true);
|
||||
F.ensure();
|
||||
auto f = F.move_as_ok();
|
||||
|
||||
auto shards = state->get_shards();
|
||||
BlockSeqno seqno = 0;
|
||||
if (shard.is_masterchain()) {
|
||||
seqno = state->get_seqno();
|
||||
} else {
|
||||
for (auto s : shards) {
|
||||
if (shard_intersects(s->shard(), shard)) {
|
||||
seqno = s->top_block_id().seqno();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (f->last_idx_ > f->first_idx_) {
|
||||
auto db_key = get_el_key(shard, f->last_idx_ - 1);
|
||||
R = kv_->get(db_key, value);
|
||||
R.ensure();
|
||||
CHECK(R.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
auto E = fetch_tl_object<ton_api::db_lt_el_value>(td::BufferSlice{value}, true);
|
||||
E.ensure();
|
||||
auto e = E.move_as_ok();
|
||||
|
||||
bool to_delete = static_cast<td::uint32>(e->id_->seqno_) > seqno;
|
||||
|
||||
if (!to_delete) {
|
||||
break;
|
||||
} else {
|
||||
f->last_idx_--;
|
||||
kv_->erase(db_key).ensure();
|
||||
}
|
||||
}
|
||||
|
||||
if (f->first_idx_ == f->last_idx_) {
|
||||
f->last_ts_ = 0;
|
||||
f->last_lt_ = 0;
|
||||
f->last_seqno_ = 0;
|
||||
}
|
||||
|
||||
kv_->set(key, serialize_tl_object(f, true)).ensure();
|
||||
}
|
||||
|
||||
void LtDb::truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) {
|
||||
auto status_key = create_serialize_tl_object<ton_api::db_lt_status_key>();
|
||||
td::Result<td::KeyValue::GetStatus> R;
|
||||
td::uint32 total_shards = 0;
|
||||
{
|
||||
std::string value;
|
||||
R = kv_->get(status_key.as_slice(), value);
|
||||
R.ensure();
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
auto F = fetch_tl_object<ton_api::db_lt_status_value>(value, true);
|
||||
F.ensure();
|
||||
auto f = F.move_as_ok();
|
||||
total_shards = f->total_shards_;
|
||||
if (total_shards == 0) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
}
|
||||
kv_->begin_transaction().ensure();
|
||||
for (td::uint32 idx = 0; idx < total_shards; idx++) {
|
||||
auto shard_key = create_serialize_tl_object<ton_api::db_lt_shard_key>(idx);
|
||||
std::string value;
|
||||
R = kv_->get(shard_key.as_slice(), value);
|
||||
R.ensure();
|
||||
CHECK(R.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
auto F = fetch_tl_object<ton_api::db_lt_shard_value>(value, true);
|
||||
F.ensure();
|
||||
auto f = F.move_as_ok();
|
||||
|
||||
truncate_workchain(ShardIdFull{f->workchain_, static_cast<td::uint64>(f->shard_)}, state);
|
||||
}
|
||||
kv_->commit_transaction().ensure();
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/db/KeyValueAsync.h"
|
||||
#include "validator/interfaces/db.h"
|
||||
|
||||
#include "ton/ton-types.h"
|
||||
|
||||
|
@ -42,6 +43,9 @@ class LtDb : public td::actor::Actor {
|
|||
void get_block_by_unix_time(AccountIdPrefixFull account_id, UnixTime ts, td::Promise<BlockIdExt> promise);
|
||||
void get_block_by_seqno(AccountIdPrefixFull account_id, BlockSeqno seqno, td::Promise<BlockIdExt> promise);
|
||||
|
||||
void truncate_workchain(ShardIdFull shard, td::Ref<MasterchainState> state);
|
||||
void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise);
|
||||
|
||||
void start_up() override;
|
||||
|
||||
LtDb(td::actor::ActorId<RootDb> root_db, std::string db_path) : root_db_(root_db), db_path_(std::move(db_path)) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "td/utils/overloaded.h"
|
||||
#include "common/checksum.h"
|
||||
#include "validator/stats-merger.h"
|
||||
#include "td/actor/MultiPromise.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -413,6 +414,14 @@ void RootDb::get_async_serializer_state(td::Promise<AsyncSerializerState> promis
|
|||
td::actor::send_closure(state_db_, &StateDb::get_async_serializer_state, std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::update_hardforks(std::vector<BlockIdExt> blocks, td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(state_db_, &StateDb::update_hardforks, std::move(blocks), std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::get_hardforks(td::Promise<std::vector<BlockIdExt>> promise) {
|
||||
td::actor::send_closure(state_db_, &StateDb::get_hardforks, std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::start_up() {
|
||||
cell_db_ = td::actor::create_actor<CellDb>("celldb", actor_id(this), root_path_ + "/celldb/");
|
||||
block_db_ = td::actor::create_actor<BlockDb>("blockdb", actor_id(this), root_path_ + "/blockdb/");
|
||||
|
@ -481,6 +490,15 @@ void RootDb::prepare_stats(td::Promise<std::vector<std::pair<std::string, std::s
|
|||
td::actor::send_closure(archive_db_, &FileDb::prepare_stats, merger.make_promise("archivedb."));
|
||||
}
|
||||
|
||||
void RootDb::truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) {
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
ig.add_promise(std::move(promise));
|
||||
|
||||
td::actor::send_closure(lt_db_, &LtDb::truncate, state, ig.get_promise());
|
||||
td::actor::send_closure(block_db_, &BlockDb::truncate, state, ig.get_promise());
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -104,6 +104,9 @@ class RootDb : public Db {
|
|||
void update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) override;
|
||||
void get_async_serializer_state(td::Promise<AsyncSerializerState> promise) override;
|
||||
|
||||
void update_hardforks(std::vector<BlockIdExt> blocks, td::Promise<td::Unit> promise) override;
|
||||
void get_hardforks(td::Promise<std::vector<BlockIdExt>> promise) override;
|
||||
|
||||
void archive(BlockIdExt block_id, td::Promise<td::Unit> promise) override;
|
||||
|
||||
void allow_state_gc(BlockIdExt block_id, td::Promise<bool> promise);
|
||||
|
@ -112,6 +115,8 @@ class RootDb : public Db {
|
|||
|
||||
void prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) override;
|
||||
|
||||
void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) override;
|
||||
|
||||
private:
|
||||
td::actor::ActorId<ValidatorManager> validator_manager_;
|
||||
|
||||
|
|
|
@ -179,6 +179,44 @@ void StateDb::get_async_serializer_state(td::Promise<AsyncSerializerState> promi
|
|||
static_cast<UnixTime>(obj->last_ts_)});
|
||||
}
|
||||
|
||||
void StateDb::update_hardforks(std::vector<BlockIdExt> blocks, td::Promise<td::Unit> promise) {
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_hardforks>();
|
||||
|
||||
std::vector<tl_object_ptr<ton_api::tonNode_blockIdExt>> vec;
|
||||
|
||||
for (auto &e : blocks) {
|
||||
vec.push_back(create_tl_block_id(e));
|
||||
}
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->set(key.as_slice(), create_serialize_tl_object<ton_api::db_state_hardforks>(std::move(vec))).ensure();
|
||||
kv_->commit_transaction();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
void StateDb::get_hardforks(td::Promise<std::vector<BlockIdExt>> promise) {
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_hardforks>();
|
||||
|
||||
std::string value;
|
||||
auto R = kv_->get(key.as_slice(), value);
|
||||
R.ensure();
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
promise.set_value(std::vector<BlockIdExt>{});
|
||||
return;
|
||||
}
|
||||
auto F = fetch_tl_object<ton_api::db_state_hardforks>(value, true);
|
||||
F.ensure();
|
||||
auto f = F.move_as_ok();
|
||||
|
||||
std::vector<BlockIdExt> vec;
|
||||
for (auto &e : f->blocks_) {
|
||||
vec.push_back(create_block_id(e));
|
||||
}
|
||||
|
||||
promise.set_value(std::move(vec));
|
||||
}
|
||||
|
||||
StateDb::StateDb(td::actor::ActorId<RootDb> root_db, std::string db_path) : root_db_(root_db), db_path_(db_path) {
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ class StateDb : public td::actor::Actor {
|
|||
void update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise);
|
||||
void get_async_serializer_state(td::Promise<AsyncSerializerState> promise);
|
||||
|
||||
void update_hardforks(std::vector<BlockIdExt> blocks, td::Promise<td::Unit> promise);
|
||||
void get_hardforks(td::Promise<std::vector<BlockIdExt>> promise);
|
||||
|
||||
StateDb(td::actor::ActorId<RootDb> root_db, std::string path);
|
||||
|
||||
void start_up() override;
|
||||
|
|
|
@ -25,7 +25,9 @@ namespace validator {
|
|||
|
||||
void StaticFilesDb::load_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) {
|
||||
auto path = path_ + "/" + file_hash.to_hex();
|
||||
td::actor::create_actor<db::ReadFile>("read file", path, 0, -1, std::move(promise)).release();
|
||||
td::actor::create_actor<db::ReadFile>("read file", path, 0, -1, db::ReadFile::Flags::f_disable_log,
|
||||
std::move(promise))
|
||||
.release();
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -56,6 +56,20 @@ void WaitBlockData::start_up() {
|
|||
alarm_timestamp() = timeout_;
|
||||
|
||||
CHECK(handle_);
|
||||
if (!handle_->id().is_masterchain()) {
|
||||
start();
|
||||
} else {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<bool> R) {
|
||||
R.ensure();
|
||||
auto value = R.move_as_ok();
|
||||
td::actor::send_closure(SelfId, &WaitBlockData::set_is_hardfork, value);
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::check_is_hardfork, handle_->id(), std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void WaitBlockData::set_is_hardfork(bool value) {
|
||||
is_hardfork_ = value;
|
||||
start();
|
||||
}
|
||||
|
||||
|
@ -76,6 +90,18 @@ void WaitBlockData::start() {
|
|||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_data_from_db, handle_, std::move(P));
|
||||
} else if (try_read_static_file_.is_in_past() && (is_hardfork_ || !handle_->id().is_masterchain())) {
|
||||
try_read_static_file_ = td::Timestamp::in(30.0);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockData::start);
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &WaitBlockData::got_static_file, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::try_get_static_file, handle_->id().file_hash, std::move(P));
|
||||
} else {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<ReceivedBlock> R) {
|
||||
if (R.is_error()) {
|
||||
|
@ -149,6 +175,29 @@ void WaitBlockData::force_read_from_db() {
|
|||
td::actor::send_closure(manager_, &ValidatorManager::get_block_data_from_db, handle_, std::move(P));
|
||||
}
|
||||
|
||||
void WaitBlockData::got_static_file(td::BufferSlice data) {
|
||||
CHECK(td::sha256_bits256(data.as_slice()) == handle_->id().file_hash);
|
||||
|
||||
auto R = create_block(handle_->id(), std::move(data));
|
||||
if (R.is_error()) {
|
||||
LOG(ERROR) << "bad static file block: " << R.move_as_error();
|
||||
start();
|
||||
return;
|
||||
}
|
||||
data_ = R.move_as_ok();
|
||||
|
||||
CHECK(is_hardfork_ || !handle_->id().is_masterchain());
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockData::abort_query, R.move_as_error_prefix("bad static file block: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &WaitBlockData::finish_query);
|
||||
}
|
||||
});
|
||||
run_hardfork_accept_block_query(handle_->id(), data_, manager_, std::move(P));
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -51,12 +51,14 @@ class WaitBlockData : public td::actor::Actor {
|
|||
void force_read_from_db();
|
||||
|
||||
void start_up() override;
|
||||
void got_block_handle(BlockHandle handle);
|
||||
void set_is_hardfork(bool value);
|
||||
void start();
|
||||
void got_block_data_from_db(td::Ref<BlockData> data);
|
||||
void got_block_data_from_net(ReceivedBlock data);
|
||||
void failed_to_get_block_data_from_net(td::Status reason);
|
||||
|
||||
void got_static_file(td::BufferSlice data);
|
||||
|
||||
private:
|
||||
BlockHandle handle_;
|
||||
|
||||
|
@ -69,6 +71,8 @@ class WaitBlockData : public td::actor::Actor {
|
|||
td::Ref<BlockData> data_;
|
||||
|
||||
bool reading_from_db_ = false;
|
||||
bool is_hardfork_ = false;
|
||||
td::Timestamp try_read_static_file_ = td::Timestamp::now();
|
||||
|
||||
//td::PerfWarningTimer perf_timer_{"waitdata", 1.0};
|
||||
};
|
||||
|
|
|
@ -52,6 +52,8 @@ void run_accept_block_query(BlockIdExt id, td::Ref<BlockData> data, std::vector<
|
|||
void run_fake_accept_block_query(BlockIdExt id, td::Ref<BlockData> data, std::vector<BlockIdExt> prev,
|
||||
td::Ref<ValidatorSet> validator_set, td::actor::ActorId<ValidatorManager> manager,
|
||||
td::Promise<td::Unit> promise);
|
||||
void run_hardfork_accept_block_query(BlockIdExt id, td::Ref<BlockData> data,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Promise<td::Unit> promise);
|
||||
void run_apply_block_query(BlockIdExt id, td::Ref<BlockData> block, td::actor::ActorId<ValidatorManager> manager,
|
||||
td::Timestamp timeout, td::Promise<td::Unit> promise);
|
||||
void run_check_proof_query(BlockIdExt id, td::Ref<Proof> proof, td::actor::ActorId<ValidatorManager> manager,
|
||||
|
|
|
@ -1466,26 +1466,10 @@ bool Collator::fetch_config_params() {
|
|||
if (cell.is_null()) {
|
||||
return fatal_error("cannot fetch current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
auto f = [self = this](const auto& r, td::uint64 spec_limit) {
|
||||
self->compute_phase_cfg_.gas_limit = r.gas_limit;
|
||||
self->compute_phase_cfg_.special_gas_limit = spec_limit;
|
||||
self->compute_phase_cfg_.gas_credit = r.gas_credit;
|
||||
self->compute_phase_cfg_.gas_price = r.gas_price;
|
||||
self->storage_phase_cfg_.freeze_due_limit = td::RefInt256{true, r.freeze_due_limit};
|
||||
self->storage_phase_cfg_.delete_due_limit = td::RefInt256{true, r.delete_due_limit};
|
||||
};
|
||||
block::gen::GasLimitsPrices::Record_gas_prices_ext rec;
|
||||
if (tlb::unpack_cell(cell, rec)) {
|
||||
f(rec, rec.special_gas_limit);
|
||||
} else {
|
||||
block::gen::GasLimitsPrices::Record_gas_prices rec0;
|
||||
if (tlb::unpack_cell(std::move(cell), rec0)) {
|
||||
f(rec0, rec0.gas_limit);
|
||||
} else {
|
||||
return fatal_error("cannot unpack current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
if (!compute_phase_cfg_.parse_GasLimitsPrices(std::move(cell), storage_phase_cfg_.freeze_due_limit,
|
||||
storage_phase_cfg_.delete_due_limit)) {
|
||||
return fatal_error("cannot unpack current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
compute_phase_cfg_.compute_threshold();
|
||||
compute_phase_cfg_.block_rand_seed = rand_seed_;
|
||||
compute_phase_cfg_.libraries = std::make_unique<vm::Dictionary>(config_->get_libraries_root(), 256);
|
||||
compute_phase_cfg_.global_config = config_->get_root_cell();
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "top-shard-descr.hpp"
|
||||
#include "ton/ton-io.hpp"
|
||||
#include "liteserver.hpp"
|
||||
#include "validator/fabric.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -131,6 +132,11 @@ void run_fake_accept_block_query(BlockIdExt id, td::Ref<BlockData> data, std::ve
|
|||
.release();
|
||||
}
|
||||
|
||||
void run_hardfork_accept_block_query(BlockIdExt id, td::Ref<BlockData> data,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Promise<td::Unit> promise) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::error, "not implemented"));
|
||||
}
|
||||
|
||||
void run_apply_block_query(BlockIdExt id, td::Ref<BlockData> block, td::actor::ActorId<ValidatorManager> manager,
|
||||
td::Timestamp timeout, td::Promise<td::Unit> promise) {
|
||||
td::actor::create_actor<ApplyBlock>(PSTRING() << "apply " << id, id, std::move(block), manager, timeout,
|
||||
|
|
|
@ -192,7 +192,7 @@ void LiteQuery::perform_getMasterchainInfo(int mode) {
|
|||
}
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[ Self = actor_id(this), mode ](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) {
|
||||
[Self = actor_id(this), mode](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -230,7 +230,7 @@ void LiteQuery::perform_getBlock(BlockIdExt blkid) {
|
|||
return;
|
||||
}
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -256,7 +256,7 @@ void LiteQuery::perform_getBlockHeader(BlockIdExt blkid, int mode) {
|
|||
return;
|
||||
}
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid, mode ](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
[Self = actor_id(this), blkid, mode](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -371,7 +371,7 @@ void LiteQuery::perform_getState(BlockIdExt blkid) {
|
|||
}
|
||||
if (blkid.id.seqno) {
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ton::validator::ShardState>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ton::validator::ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -381,7 +381,7 @@ void LiteQuery::perform_getState(BlockIdExt blkid) {
|
|||
});
|
||||
} else {
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_zero_state, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<td::BufferSlice> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -440,7 +440,7 @@ bool LiteQuery::request_mc_block_data(BlockIdExt blkid) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<BlockData>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
||||
|
@ -466,7 +466,7 @@ bool LiteQuery::request_mc_proof(BlockIdExt blkid, int mode) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_proof_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid, mode ](td::Result<Ref<Proof>> res) {
|
||||
[Self = actor_id(this), blkid, mode](td::Result<Ref<Proof>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load proof for "s + blkid.to_str() + " : "));
|
||||
|
@ -488,7 +488,7 @@ bool LiteQuery::request_mc_block_state(BlockIdExt blkid) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ShardState>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load state for "s + blkid.to_str() + " : "));
|
||||
|
@ -519,7 +519,7 @@ bool LiteQuery::request_block_state(BlockIdExt blkid) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ShardState>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load state for "s + blkid.to_str() + " : "));
|
||||
|
@ -541,7 +541,7 @@ bool LiteQuery::request_block_data(BlockIdExt blkid) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<BlockData>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
||||
|
@ -563,7 +563,7 @@ bool LiteQuery::request_proof_link(BlockIdExt blkid) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_proof_link_from_db_short, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ProofLink>> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ProofLink>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load proof link for "s + blkid.to_str() + " : "));
|
||||
|
@ -588,7 +588,7 @@ bool LiteQuery::request_zero_state(BlockIdExt blkid) {
|
|||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_zero_state, blkid,
|
||||
[ Self = actor_id(this), blkid ](td::Result<td::BufferSlice> res) {
|
||||
[Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load zerostate of "s + blkid.to_str() + " : "));
|
||||
|
@ -632,7 +632,7 @@ void LiteQuery::perform_getAccountState(BlockIdExt blkid, WorkchainId workchain,
|
|||
LOG(INFO) << "sending a get_top_masterchain_state_block query to manager";
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[Self = actor_id(this)](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res)->void {
|
||||
[Self = actor_id(this)](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) -> void {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -1067,7 +1067,7 @@ void LiteQuery::continue_getTransactions(unsigned remaining, bool exact) {
|
|||
<< " " << trans_lt_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_by_lt_from_db, ton::extract_addr_prefix(acc_workchain_, acc_addr_),
|
||||
trans_lt_, [ Self = actor_id(this), remaining, manager = manager_ ](td::Result<BlockIdExt> res) {
|
||||
trans_lt_, [Self = actor_id(this), remaining, manager = manager_](td::Result<BlockIdExt> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, res.move_as_error(), ton::BlockIdExt{});
|
||||
} else {
|
||||
|
@ -1141,7 +1141,7 @@ void LiteQuery::perform_getShardInfo(BlockIdExt blkid, ShardIdFull shard, bool e
|
|||
void LiteQuery::perform_getConfigParams(BlockIdExt blkid, int mode, std::vector<int> param_list) {
|
||||
LOG(INFO) << "started a getConfigParams(" << blkid.to_str() << ", " << mode << ", <list of " << param_list.size()
|
||||
<< " parameters>) liteserver query";
|
||||
set_continuation([ this, mode, param_list = std::move(param_list) ]() mutable {
|
||||
set_continuation([this, mode, param_list = std::move(param_list)]() mutable {
|
||||
continue_getConfigParams(mode, std::move(param_list));
|
||||
});
|
||||
request_mc_block_data_state(blkid);
|
||||
|
@ -1294,7 +1294,7 @@ void LiteQuery::perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, Uni
|
|||
LOG(INFO) << "performing a lookupBlock(" << blkid.to_str() << ", " << mode << ", " << lt << ", " << utime
|
||||
<< ") query";
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[ Self = actor_id(this), manager = manager_, mode = (mode >> 4) ](td::Result<BlockIdExt> res) {
|
||||
[Self = actor_id(this), manager = manager_, mode = (mode >> 4)](td::Result<BlockIdExt> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -1445,10 +1445,21 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||
fatal_error("destination block "s + to.to_str() + " is not a valid masterchain block id");
|
||||
return;
|
||||
}
|
||||
if (!(mode & 1)) {
|
||||
if (mode & 1) {
|
||||
base_blk_id_ = (from.seqno() > to.seqno()) ? from : to;
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, base_blk_id_,
|
||||
[Self = actor_id(this), from, to, mode](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, to,
|
||||
mode, Ref<MasterchainStateQ>(res.move_as_ok()));
|
||||
}
|
||||
});
|
||||
} else if (mode & 2) {
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[ Self = actor_id(this), from, mode ](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res)->void {
|
||||
[Self = actor_id(this), from, mode](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -1458,14 +1469,13 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||
}
|
||||
});
|
||||
} else {
|
||||
base_blk_id_ = (from.seqno() > to.seqno()) ? from : to;
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, base_blk_id_,
|
||||
[ Self = actor_id(this), from, to, mode ](td::Result<Ref<ShardState>> res) {
|
||||
td::actor::send_closure_later(manager_, &ton::validator::ValidatorManager::get_shard_client_state, false,
|
||||
[Self = actor_id(this), from, mode](td::Result<BlockIdExt> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, to,
|
||||
mode, Ref<MasterchainStateQ>(res.move_as_ok()));
|
||||
td::actor::send_closure_later(Self, &LiteQuery::perform_getBlockProof, from,
|
||||
res.move_as_ok(), mode | 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -734,26 +734,10 @@ bool ValidateQuery::fetch_config_params() {
|
|||
if (cell.is_null()) {
|
||||
return fatal_error("cannot fetch current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
auto f = [self = this](const auto& r, td::uint64 spec_limit) {
|
||||
self->compute_phase_cfg_.gas_limit = r.gas_limit;
|
||||
self->compute_phase_cfg_.special_gas_limit = spec_limit;
|
||||
self->compute_phase_cfg_.gas_credit = r.gas_credit;
|
||||
self->compute_phase_cfg_.gas_price = r.gas_price;
|
||||
self->storage_phase_cfg_.freeze_due_limit = td::RefInt256{true, r.freeze_due_limit};
|
||||
self->storage_phase_cfg_.delete_due_limit = td::RefInt256{true, r.delete_due_limit};
|
||||
};
|
||||
block::gen::GasLimitsPrices::Record_gas_prices_ext rec;
|
||||
if (tlb::unpack_cell(cell, rec)) {
|
||||
f(rec, rec.special_gas_limit);
|
||||
} else {
|
||||
block::gen::GasLimitsPrices::Record_gas_prices rec0;
|
||||
if (tlb::unpack_cell(std::move(cell), rec0)) {
|
||||
f(rec0, rec0.gas_limit);
|
||||
} else {
|
||||
return fatal_error("cannot unpack current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
if (!compute_phase_cfg_.parse_GasLimitsPrices(std::move(cell), storage_phase_cfg_.freeze_due_limit,
|
||||
storage_phase_cfg_.delete_due_limit)) {
|
||||
return fatal_error("cannot unpack current gas prices and limits from masterchain configuration");
|
||||
}
|
||||
compute_phase_cfg_.compute_threshold();
|
||||
compute_phase_cfg_.block_rand_seed = rand_seed_;
|
||||
compute_phase_cfg_.libraries = std::make_unique<vm::Dictionary>(config_->get_libraries_root(), 256);
|
||||
compute_phase_cfg_.global_config = config_->get_root_cell();
|
||||
|
@ -5227,7 +5211,7 @@ bool ValidateQuery::check_block_create_stats() {
|
|||
auto key = td::Bits256::zero();
|
||||
auto old_val = ps_.block_create_stats_->lookup(key);
|
||||
auto new_val = ns_.block_create_stats_->lookup(key);
|
||||
if (new_val.is_null()) {
|
||||
if (new_val.is_null() && (!created_by_.is_zero() || block_create_total_)) {
|
||||
return reject_query(
|
||||
"new masterchain state does not contain a BlockCreator entry with zero key with total statistics");
|
||||
}
|
||||
|
|
|
@ -93,6 +93,9 @@ struct BlockHandleInterface {
|
|||
virtual void set_archived() = 0;
|
||||
virtual void set_applied() = 0;
|
||||
|
||||
virtual void unsafe_clear_applied() = 0;
|
||||
virtual void unsafe_clear_next() = 0;
|
||||
|
||||
virtual td::BufferSlice serialize() const = 0;
|
||||
|
||||
virtual ~BlockHandleInterface() = default;
|
||||
|
|
|
@ -92,9 +92,14 @@ class Db : public td::actor::Actor {
|
|||
virtual void update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) = 0;
|
||||
virtual void get_async_serializer_state(td::Promise<AsyncSerializerState> promise) = 0;
|
||||
|
||||
virtual void update_hardforks(std::vector<BlockIdExt> blocks, td::Promise<td::Unit> promise) = 0;
|
||||
virtual void get_hardforks(td::Promise<std::vector<BlockIdExt>> promise) = 0;
|
||||
|
||||
virtual void archive(BlockIdExt block_id, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) = 0;
|
||||
|
||||
virtual void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) = 0;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -128,7 +128,7 @@ class ValidatorManager : public ValidatorManagerInterface {
|
|||
virtual void send_block_broadcast(BlockBroadcast broadcast) = 0;
|
||||
|
||||
virtual void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise) = 0;
|
||||
virtual void get_shard_client_state(td::Promise<BlockIdExt> promise) = 0;
|
||||
virtual void get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) = 0;
|
||||
virtual void subscribe_to_shard(ShardIdFull shard) = 0;
|
||||
|
||||
virtual void update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) = 0;
|
||||
|
@ -153,6 +153,12 @@ class ValidatorManager : public ValidatorManagerInterface {
|
|||
virtual void update_last_known_key_block(BlockHandle handle, bool send_request) = 0;
|
||||
virtual void update_gc_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void update_shard_client_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
static bool is_persistent_state(UnixTime ts, UnixTime prev_ts) {
|
||||
return ts / 1024 != prev_ts / 1024;
|
||||
}
|
||||
|
|
|
@ -897,7 +897,7 @@ void ValidatorManagerImpl::update_shard_client_state(BlockIdExt masterchain_bloc
|
|||
td::actor::send_closure(db_, &Db::update_shard_client_state, masterchain_block_id, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_shard_client_state(td::Promise<BlockIdExt> promise) {
|
||||
void ValidatorManagerImpl::get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_shard_client_state, std::move(promise));
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
}
|
||||
|
||||
void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise) override;
|
||||
void get_shard_client_state(td::Promise<BlockIdExt> promise) override;
|
||||
void get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) override;
|
||||
void subscribe_to_shard(ShardIdFull shard) override {
|
||||
}
|
||||
|
||||
|
@ -329,11 +329,20 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
}
|
||||
void update_last_known_key_block(BlockHandle handle, bool send_request) override {
|
||||
}
|
||||
void update_shard_client_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override {
|
||||
}
|
||||
|
||||
void prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
private:
|
||||
PublicKeyHash local_id_;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "adnl/utils.hpp"
|
||||
#include "validator/downloaders/download-state.hpp"
|
||||
#include "common/delay.h"
|
||||
#include "td/actor/MultiPromise.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -33,7 +34,16 @@ namespace validator {
|
|||
void ValidatorManagerMasterchainReiniter::start_up() {
|
||||
CHECK(block_id_.is_masterchain());
|
||||
CHECK(block_id_.id.shard == shardIdAll);
|
||||
CHECK(block_id_.seqno() >= opts_->get_last_fork_masterchain_seqno());
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainReiniter::written_hardforks);
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::update_hardforks, opts_->get_hardforks(), std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainReiniter::written_hardforks() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainReiniter::got_masterchain_handle, R.move_as_ok());
|
||||
|
@ -268,7 +278,7 @@ void ValidatorManagerMasterchainStarter::start_up() {
|
|||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::failed_to_get_init_block_id() {
|
||||
td::actor::create_actor<ValidatorManagerMasterchainReiniter>("reiniter", opts_, manager_, std::move(promise_))
|
||||
td::actor::create_actor<ValidatorManagerMasterchainReiniter>("reiniter", opts_, manager_, db_, std::move(promise_))
|
||||
.release();
|
||||
stop();
|
||||
}
|
||||
|
@ -351,7 +361,7 @@ void ValidatorManagerMasterchainStarter::got_gc_block_state(td::Ref<MasterchainS
|
|||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_shard_block_id, R.move_as_ok());
|
||||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_client_state, std::move(P));
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_client_state, true, std::move(P));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -375,15 +385,169 @@ void ValidatorManagerMasterchainStarter::got_key_block_handle(BlockHandle handle
|
|||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_shard_block_id, R.move_as_ok());
|
||||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_client_state, std::move(P));
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_client_state, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_shard_block_id(BlockIdExt block_id) {
|
||||
client_ = td::actor::create_actor<ShardClient>("shardclient", opts_, manager_);
|
||||
client_block_id_ = block_id;
|
||||
finish();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<BlockIdExt>> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_hardforks, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::get_hardforks, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_hardforks(std::vector<BlockIdExt> vec) {
|
||||
auto h = opts_->get_hardforks();
|
||||
if (h.size() < vec.size()) {
|
||||
LOG(FATAL) << "cannot start: number of hardforks decreased";
|
||||
return;
|
||||
}
|
||||
if (h.size() == vec.size()) {
|
||||
if (h.size() > 0) {
|
||||
if (*h.rbegin() != *vec.rbegin()) {
|
||||
LOG(FATAL) << "cannot start: hardforks list changed";
|
||||
return;
|
||||
}
|
||||
}
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (h.size() > vec.size() + 1) {
|
||||
LOG(FATAL) << "cannot start: number of hardforks increase is too big";
|
||||
return;
|
||||
}
|
||||
|
||||
auto b = *h.rbegin();
|
||||
if (b.seqno() > handle_->id().seqno()) {
|
||||
truncated();
|
||||
return;
|
||||
}
|
||||
if (b.seqno() <= gc_handle_->id().seqno()) {
|
||||
LOG(FATAL) << "cannot start: new hardfork is on too old block (already gc'd)";
|
||||
return;
|
||||
}
|
||||
|
||||
BlockIdExt id;
|
||||
if (state_->get_old_mc_block_id(b.seqno() - 1, id)) {
|
||||
got_truncate_block_id(id);
|
||||
return;
|
||||
}
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockIdExt> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_truncate_block_id, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::get_block_by_seqno, AccountIdPrefixFull{masterchainId, 0}, b.seqno() - 1,
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_truncate_block_id(BlockIdExt block_id) {
|
||||
block_id_ = block_id;
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_truncate_block_handle, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, block_id_, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_truncate_block_handle(BlockHandle handle) {
|
||||
handle_ = std::move(handle);
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_truncate_state,
|
||||
td::Ref<MasterchainState>{R.move_as_ok()});
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::get_block_state, handle_, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_truncate_state(td::Ref<MasterchainState> state) {
|
||||
state_ = std::move(state);
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::truncated_db);
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::truncate, state_, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::truncated_db() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::truncated);
|
||||
});
|
||||
|
||||
auto key = state_->last_key_block_id();
|
||||
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
ig.add_promise(std::move(P));
|
||||
|
||||
td::actor::send_closure(db_, &Db::update_init_masterchain_block, block_id_, ig.get_promise());
|
||||
|
||||
if (client_block_id_.seqno() > block_id_.seqno()) {
|
||||
client_block_id_ = block_id_;
|
||||
td::actor::send_closure(db_, &Db::update_shard_client_state, client_block_id_, ig.get_promise());
|
||||
}
|
||||
|
||||
if (last_key_block_handle_->id().seqno() > key.seqno()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this),
|
||||
promise = ig.get_promise()](td::Result<BlockHandle> R) mutable {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_prev_key_block_handle, R.move_as_ok());
|
||||
promise.set_value(td::Unit());
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, key, false, std::move(P));
|
||||
}
|
||||
|
||||
{
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[b = block_id_, key, db = db_, promise = ig.get_promise()](td::Result<AsyncSerializerState> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
auto s = R.move_as_ok();
|
||||
if (s.last_block_id.seqno() <= b.seqno()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
s.last_block_id = b;
|
||||
if (s.last_written_block_id.seqno() > b.seqno()) {
|
||||
s.last_written_block_id = key;
|
||||
s.last_written_block_ts = 0; // may lead to extra state snapshot on disk. Does not seem like a problem
|
||||
}
|
||||
td::actor::send_closure(db, &Db::update_async_serializer_state, s, std::move(promise));
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::get_async_serializer_state, std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_prev_key_block_handle(BlockHandle handle) {
|
||||
last_key_block_handle_ = std::move(handle);
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::truncated() {
|
||||
handle_->set_next(*opts_->get_hardforks().rbegin());
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::written_next);
|
||||
});
|
||||
handle_->flush(manager_, handle_, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::written_next() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::finish);
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::update_hardforks, opts_->get_hardforks(), std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::finish() {
|
||||
client_ = td::actor::create_actor<ShardClient>("shardclient", opts_, manager_);
|
||||
promise_.set_value(
|
||||
ValidatorManagerInitResult{handle_, state_, std::move(client_), gc_handle_, gc_state_, last_key_block_handle_});
|
||||
stop();
|
||||
|
|
|
@ -34,12 +34,13 @@ namespace validator {
|
|||
class ValidatorManagerMasterchainReiniter : public td::actor::Actor {
|
||||
public:
|
||||
ValidatorManagerMasterchainReiniter(td::Ref<ValidatorManagerOptions> opts,
|
||||
td::actor::ActorId<ValidatorManager> manager,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::actor::ActorId<Db> db,
|
||||
td::Promise<ValidatorManagerInitResult> promise)
|
||||
: opts_(std::move(opts)), manager_(manager), promise_(std::move(promise)) {
|
||||
: opts_(std::move(opts)), manager_(manager), db_(db), promise_(std::move(promise)) {
|
||||
block_id_ = opts_->init_block_id();
|
||||
}
|
||||
void start_up() override;
|
||||
void written_hardforks();
|
||||
void got_masterchain_handle(BlockHandle handle);
|
||||
void download_proof_link();
|
||||
void downloaded_proof_link(td::BufferSlice data);
|
||||
|
@ -70,6 +71,7 @@ class ValidatorManagerMasterchainReiniter : public td::actor::Actor {
|
|||
std::vector<ShardIdFull> shards_;
|
||||
|
||||
td::actor::ActorId<ValidatorManager> manager_;
|
||||
td::actor::ActorId<Db> db_;
|
||||
|
||||
td::Promise<ValidatorManagerInitResult> promise_;
|
||||
|
||||
|
@ -95,6 +97,14 @@ class ValidatorManagerMasterchainStarter : public td::actor::Actor {
|
|||
void got_gc_block_state(td::Ref<MasterchainState> state);
|
||||
void got_key_block_handle(BlockHandle handle);
|
||||
void got_shard_block_id(BlockIdExt block_id);
|
||||
void got_hardforks(std::vector<BlockIdExt> hardforks);
|
||||
void got_truncate_block_id(BlockIdExt block_id);
|
||||
void got_truncate_block_handle(BlockHandle handle);
|
||||
void got_truncate_state(td::Ref<MasterchainState> state);
|
||||
void truncated_db();
|
||||
void got_prev_key_block_handle(BlockHandle handle);
|
||||
void truncated();
|
||||
void written_next();
|
||||
void finish();
|
||||
|
||||
private:
|
||||
|
@ -112,6 +122,7 @@ class ValidatorManagerMasterchainStarter : public td::actor::Actor {
|
|||
|
||||
td::Promise<ValidatorManagerInitResult> promise_;
|
||||
|
||||
BlockIdExt client_block_id_;
|
||||
td::actor::ActorOwn<ShardClient> client_;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,29 +52,52 @@ void ValidatorManagerImpl::validate_block_is_next_proof(BlockIdExt prev_block_id
|
|||
td::Status::Error(ErrorCode::protoviolation, "validate_block_is_next_proof() can only work for masterchain"));
|
||||
return;
|
||||
}
|
||||
if (prev_block_id.seqno() + 1 != next_block_id.seqno()) {
|
||||
VLOG(VALIDATOR_NOTICE) << "prev=" << prev_block_id << " next=" << next_block_id;
|
||||
promise.set_error(td::Status::Error(ErrorCode::protoviolation, "validate_block_is_next_proof(): bad seqno"));
|
||||
return;
|
||||
}
|
||||
CHECK(last_masterchain_state_.not_null());
|
||||
auto pp = create_proof(next_block_id, std::move(proof));
|
||||
if (pp.is_error()) {
|
||||
promise.set_error(pp.move_as_error_prefix("failed to create proof: "));
|
||||
return;
|
||||
}
|
||||
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([promise = std::move(promise), id = prev_block_id](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
auto handle = R.move_as_ok();
|
||||
CHECK(!handle->merge_before());
|
||||
if (handle->one_prev(true) != id) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::protoviolation, "prev block mismatch"));
|
||||
return;
|
||||
}
|
||||
promise.set_value(td::Unit());
|
||||
});
|
||||
if (last_masterchain_seqno_ == prev_block_id.seqno()) {
|
||||
CHECK(last_masterchain_block_id_ == prev_block_id);
|
||||
|
||||
run_check_proof_query(next_block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P),
|
||||
opts_->is_hardfork(next_block_id));
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise), id = prev_block_id](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
auto handle = R.move_as_ok();
|
||||
CHECK(!handle->merge_before());
|
||||
if (handle->one_prev(true) != id) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::protoviolation, "prev block mismatch"));
|
||||
return;
|
||||
}
|
||||
promise.set_value(td::Unit());
|
||||
});
|
||||
|
||||
run_check_proof_query(next_block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P),
|
||||
last_masterchain_state_, opts_->is_hardfork(next_block_id));
|
||||
} else {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([promise = std::move(promise), next_block_id](td::Result<BlockHandle> R) mutable {
|
||||
R.ensure();
|
||||
auto handle = R.move_as_ok();
|
||||
CHECK(handle->inited_next_left());
|
||||
if (handle->one_next(true) == next_block_id) {
|
||||
promise.set_value(td::Unit());
|
||||
} else {
|
||||
promise.set_error(td::Status::Error("next block id mismatch"));
|
||||
}
|
||||
});
|
||||
get_block_handle(prev_block_id, false, std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::validate_block_proof(BlockIdExt block_id, td::BufferSlice proof,
|
||||
|
@ -468,7 +491,27 @@ void ValidatorManagerImpl::run_ext_query(td::BufferSlice data, td::Promise<td::B
|
|||
promise.set_value(std::move(data));
|
||||
});
|
||||
|
||||
run_liteserver_query(std::move(data), actor_id(this), lite_server_cache_.get(), std::move(P));
|
||||
auto E = fetch_tl_prefix<lite_api::liteServer_waitMasterchainSeqno>(data, true);
|
||||
if (E.is_error()) {
|
||||
run_liteserver_query(std::move(data), actor_id(this), lite_server_cache_.get(), std::move(P));
|
||||
} else {
|
||||
auto e = E.move_as_ok();
|
||||
if (static_cast<BlockSeqno>(e->seqno_) <= min_confirmed_masterchain_seqno_) {
|
||||
run_liteserver_query(std::move(data), actor_id(this), lite_server_cache_.get(), std::move(P));
|
||||
} else {
|
||||
auto t = e->timeout_ms_ < 10000 ? e->timeout_ms_ * 0.001 : 10.0;
|
||||
auto Q =
|
||||
td::PromiseCreator::lambda([data = std::move(data), SelfId = actor_id(this), cache = lite_server_cache_.get(),
|
||||
promise = std::move(P)](td::Result<td::Unit> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
run_liteserver_query(std::move(data), SelfId, cache, std::move(promise));
|
||||
});
|
||||
wait_shard_client_state(e->seqno_, td::Timestamp::in(t), std::move(Q));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
|
@ -1387,7 +1430,8 @@ void ValidatorManagerImpl::new_masterchain_block() {
|
|||
}
|
||||
|
||||
void ValidatorManagerImpl::update_shards() {
|
||||
if (last_masterchain_state_->rotated_all_shards() || last_masterchain_seqno_ == 0) {
|
||||
if ((last_masterchain_state_->rotated_all_shards() || last_masterchain_seqno_ == 0) &&
|
||||
opts_->get_last_fork_masterchain_seqno() <= last_masterchain_seqno_) {
|
||||
allow_validate_ = true;
|
||||
}
|
||||
auto exp_vec = last_masterchain_state_->get_shards();
|
||||
|
@ -1468,7 +1512,7 @@ void ValidatorManagerImpl::update_shards() {
|
|||
auto val_set = last_masterchain_state_->get_validator_set(shard);
|
||||
auto x = val_set->export_vector();
|
||||
|
||||
auto validator_id = get_validator(val_set);
|
||||
auto validator_id = get_validator(shard, val_set);
|
||||
|
||||
if (!validator_id.is_zero()) {
|
||||
auto val_group_id = get_validator_set_id(shard, val_set, opts_hash);
|
||||
|
@ -1499,7 +1543,7 @@ void ValidatorManagerImpl::update_shards() {
|
|||
for (auto &shard : future_shards) {
|
||||
auto val_set = last_masterchain_state_->get_next_validator_set(shard);
|
||||
|
||||
auto validator_id = get_validator(val_set);
|
||||
auto validator_id = get_validator(shard, val_set);
|
||||
if (!validator_id.is_zero()) {
|
||||
auto val_group_id = get_validator_set_id(shard, val_set, opts_hash);
|
||||
auto it = next_validator_groups_.find(val_group_id);
|
||||
|
@ -1548,7 +1592,7 @@ void ValidatorManagerImpl::update_shards() {
|
|||
});
|
||||
td::actor::send_closure(db_, &Db::update_destroyed_validator_sessions, gc_list_, std::move(P));
|
||||
}
|
||||
}
|
||||
} // namespace validator
|
||||
|
||||
void ValidatorManagerImpl::written_destroyed_validator_sessions(std::vector<td::actor::ActorId<ValidatorGroup>> list) {
|
||||
for (auto &v : list) {
|
||||
|
@ -1609,7 +1653,7 @@ td::actor::ActorOwn<ValidatorGroup> ValidatorManagerImpl::create_validator_group
|
|||
if (check_gc_list_.count(session_id) == 1) {
|
||||
return td::actor::ActorOwn<ValidatorGroup>{};
|
||||
} else {
|
||||
auto validator_id = get_validator(validator_set);
|
||||
auto validator_id = get_validator(shard, validator_set);
|
||||
CHECK(!validator_id.is_zero());
|
||||
auto G = td::actor::create_actor<ValidatorGroup>("validatorgroup", shard, validator_id, session_id, validator_set,
|
||||
opts, keyring_, adnl_, rldp_, overlays_, db_root_, actor_id(this),
|
||||
|
@ -1827,10 +1871,26 @@ void ValidatorManagerImpl::advance_gc(BlockHandle handle, td::Ref<MasterchainSta
|
|||
try_advance_gc_masterchain_block();
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::update_shard_client_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
auto seqno = handle->id().seqno();
|
||||
shard_client_update(seqno);
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::shard_client_update(BlockSeqno seqno) {
|
||||
if (min_confirmed_masterchain_seqno_ < seqno) {
|
||||
min_confirmed_masterchain_seqno_ = seqno;
|
||||
}
|
||||
while (shard_client_waiters_.size() > 0) {
|
||||
auto it = shard_client_waiters_.begin();
|
||||
if (it->first > seqno) {
|
||||
break;
|
||||
}
|
||||
for (auto &y : it->second.waiting_) {
|
||||
y.promise.set_value(td::Unit());
|
||||
}
|
||||
shard_client_waiters_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::state_serializer_update(BlockSeqno seqno) {
|
||||
|
@ -1870,6 +1930,9 @@ void ValidatorManagerImpl::alarm() {
|
|||
for (auto &w : wait_state_) {
|
||||
w.second.check_timers();
|
||||
}
|
||||
for (auto &w : shard_client_waiters_) {
|
||||
w.second.check_timers();
|
||||
}
|
||||
}
|
||||
alarm_timestamp().relax(check_waiters_at_);
|
||||
if (check_shard_clients_.is_in_past()) {
|
||||
|
@ -1904,8 +1967,12 @@ void ValidatorManagerImpl::update_shard_client_state(BlockIdExt masterchain_bloc
|
|||
td::actor::send_closure(db_, &Db::update_shard_client_state, masterchain_block_id, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_shard_client_state(td::Promise<BlockIdExt> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_shard_client_state, std::move(promise));
|
||||
void ValidatorManagerImpl::get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) {
|
||||
if (!shard_client_.empty() && !from_db) {
|
||||
td::actor::send_closure(shard_client_, &ShardClient::get_processed_masterchain_block_id, std::move(promise));
|
||||
} else {
|
||||
td::actor::send_closure(db_, &Db::get_shard_client_state, std::move(promise));
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::subscribe_to_shard(ShardIdFull shard) {
|
||||
|
@ -1928,7 +1995,10 @@ bool ValidatorManagerImpl::is_validator() {
|
|||
return temp_keys_.size() > 0 || permanent_keys_.size() > 0;
|
||||
}
|
||||
|
||||
PublicKeyHash ValidatorManagerImpl::get_validator(td::Ref<ValidatorSet> val_set) {
|
||||
PublicKeyHash ValidatorManagerImpl::get_validator(ShardIdFull shard, td::Ref<ValidatorSet> val_set) {
|
||||
if (!opts_->need_validate(shard)) {
|
||||
return PublicKeyHash::zero();
|
||||
}
|
||||
for (auto &key : temp_keys_) {
|
||||
if (val_set->is_validator(key.bits256_value())) {
|
||||
return key;
|
||||
|
@ -2017,6 +2087,28 @@ void ValidatorManagerImpl::prepare_stats(td::Promise<std::vector<std::pair<std::
|
|||
td::actor::send_closure(db_, &Db::prepare_stats, merger.make_promise("db."));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(db_, &Db::truncate, std::move(state), std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout,
|
||||
td::Promise<td::Unit> promise) {
|
||||
if (seqno <= min_confirmed_masterchain_seqno_) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
if (timeout.is_in_past()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::timeout, "timeout"));
|
||||
return;
|
||||
}
|
||||
if (seqno > min_confirmed_masterchain_seqno_ + 100) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "too big masterchain block seqno"));
|
||||
return;
|
||||
}
|
||||
|
||||
shard_client_waiters_[seqno].waiting_.emplace_back(timeout, 0, std::move(promise));
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<ValidatorManagerInterface> ValidatorManagerFactory::create(
|
||||
td::Ref<ValidatorManagerOptions> opts, std::string db_root, td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<rldp::Rldp> rldp,
|
||||
|
|
|
@ -143,6 +143,8 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
std::vector<Waiter<ResType>> waiting_;
|
||||
td::actor::ActorId<ActorT> actor_;
|
||||
|
||||
WaitList() = default;
|
||||
|
||||
std::pair<td::Timestamp, td::uint32> get_timeout() const {
|
||||
td::Timestamp t = td::Timestamp::now();
|
||||
td::uint32 prio = 0;
|
||||
|
@ -256,6 +258,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void advance_gc(BlockHandle handle, td::Ref<MasterchainState> state);
|
||||
void try_advance_gc_masterchain_block();
|
||||
void update_gc_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
void update_shard_client_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
|
||||
public:
|
||||
void install_callback(std::unique_ptr<Callback> new_callback, td::Promise<td::Unit> promise) override {
|
||||
|
@ -414,7 +417,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void send_block_broadcast(BlockBroadcast broadcast) override;
|
||||
|
||||
void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise) override;
|
||||
void get_shard_client_state(td::Promise<BlockIdExt> promise) override;
|
||||
void get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) override;
|
||||
void subscribe_to_shard(ShardIdFull shard) override;
|
||||
|
||||
void update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) override;
|
||||
|
@ -448,7 +451,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void read_gc_list(std::vector<ValidatorSessionId> list);
|
||||
|
||||
bool is_validator();
|
||||
PublicKeyHash get_validator(td::Ref<ValidatorSet> val_set);
|
||||
PublicKeyHash get_validator(ShardIdFull shard, td::Ref<ValidatorSet> val_set);
|
||||
|
||||
ValidatorManagerImpl(td::Ref<ValidatorManagerOptions> opts, std::string db_root,
|
||||
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl,
|
||||
|
@ -502,6 +505,10 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
|
||||
void prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) override;
|
||||
|
||||
void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) override;
|
||||
|
||||
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override;
|
||||
|
||||
private:
|
||||
td::Timestamp resend_shard_blocks_at_;
|
||||
td::Timestamp check_waiters_at_;
|
||||
|
@ -558,6 +565,9 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
double block_ttl() const {
|
||||
return opts_->block_ttl();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<BlockSeqno, WaitList<td::actor::Actor, td::Unit>> shard_client_waiters_;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -36,7 +36,7 @@ void ShardClient::start_up() {
|
|||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ShardClient::got_state_from_db, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_client_state, std::move(P));
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_client_state, true, std::move(P));
|
||||
}
|
||||
|
||||
void ShardClient::got_state_from_db(BlockIdExt state) {
|
||||
|
@ -94,6 +94,8 @@ void ShardClient::saved_to_db() {
|
|||
}
|
||||
|
||||
CHECK(masterchain_block_handle_);
|
||||
td::actor::send_closure(manager_, &ValidatorManager::update_shard_client_block_handle, masterchain_block_handle_,
|
||||
[](td::Unit) {});
|
||||
if (masterchain_block_handle_->inited_next_left()) {
|
||||
new_masterchain_block_id(masterchain_block_handle_->one_next(true));
|
||||
} else {
|
||||
|
@ -198,6 +200,14 @@ void ShardClient::get_processed_masterchain_block(td::Promise<BlockSeqno> promis
|
|||
promise.set_result(seqno);
|
||||
}
|
||||
|
||||
void ShardClient::get_processed_masterchain_block_id(td::Promise<BlockIdExt> promise) {
|
||||
if (masterchain_block_handle_) {
|
||||
promise.set_result(masterchain_block_handle_->id());
|
||||
} else {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "shard client not started"));
|
||||
}
|
||||
}
|
||||
|
||||
void ShardClient::build_shard_overlays() {
|
||||
auto v = masterchain_state_->get_shards();
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ class ShardClient : public td::actor::Actor {
|
|||
void new_masterchain_block_notification(BlockHandle handle, td::Ref<MasterchainState> state);
|
||||
|
||||
void get_processed_masterchain_block(td::Promise<BlockSeqno> promise);
|
||||
void get_processed_masterchain_block_id(td::Promise<BlockIdExt> promise);
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace ton {
|
|||
namespace validator {
|
||||
|
||||
td::Ref<ValidatorManagerOptions> ValidatorManagerOptions::create(
|
||||
BlockIdExt zero_block_id, BlockIdExt init_block_id, std::function<bool(ShardIdFull)> check_shard,
|
||||
BlockIdExt zero_block_id, BlockIdExt init_block_id, std::function<bool(ShardIdFull, ShardCheckMode)> check_shard,
|
||||
bool allow_blockchain_init, td::ClocksBase::Duration sync_blocks_before, td::ClocksBase::Duration block_ttl,
|
||||
td::ClocksBase::Duration state_ttl, td::ClocksBase::Duration archive_ttl, td::ClocksBase::Duration key_proof_ttl,
|
||||
bool initial_sync_disabled) {
|
||||
|
|
|
@ -33,7 +33,10 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
return init_block_id_;
|
||||
}
|
||||
bool need_monitor(ShardIdFull shard) const override {
|
||||
return check_shard_(shard);
|
||||
return check_shard_(shard, ShardCheckMode::m_monitor);
|
||||
}
|
||||
bool need_validate(ShardIdFull shard) const override {
|
||||
return check_shard_(shard, ShardCheckMode::m_validate);
|
||||
}
|
||||
bool allow_blockchain_init() const override {
|
||||
return allow_blockchain_init_;
|
||||
|
@ -82,6 +85,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
td::uint32 get_last_fork_masterchain_seqno() const override {
|
||||
return hardforks_.size() ? hardforks_.rbegin()->seqno() : 0;
|
||||
}
|
||||
std::vector<BlockIdExt> get_hardforks() const override {
|
||||
return hardforks_;
|
||||
}
|
||||
td::uint32 get_filedb_depth() const override {
|
||||
return db_depth_;
|
||||
}
|
||||
|
@ -92,7 +98,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
void set_init_block_id(BlockIdExt block_id) override {
|
||||
init_block_id_ = block_id;
|
||||
}
|
||||
void set_shard_check_function(std::function<bool(ShardIdFull)> check_shard) override {
|
||||
void set_shard_check_function(std::function<bool(ShardIdFull, ShardCheckMode)> check_shard) override {
|
||||
check_shard_ = std::move(check_shard);
|
||||
}
|
||||
void set_allow_blockchain_init(bool value) override {
|
||||
|
@ -129,7 +135,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
}
|
||||
|
||||
ValidatorManagerOptionsImpl(BlockIdExt zero_block_id, BlockIdExt init_block_id,
|
||||
std::function<bool(ShardIdFull)> check_shard, bool allow_blockchain_init,
|
||||
std::function<bool(ShardIdFull, ShardCheckMode)> check_shard, bool allow_blockchain_init,
|
||||
td::ClocksBase::Duration sync_blocks_before, td::ClocksBase::Duration block_ttl,
|
||||
td::ClocksBase::Duration state_ttl, td::ClocksBase::Duration archive_ttl,
|
||||
td::ClocksBase::Duration key_proof_ttl, bool initial_sync_disabled)
|
||||
|
@ -148,7 +154,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
private:
|
||||
BlockIdExt zero_block_id_;
|
||||
BlockIdExt init_block_id_;
|
||||
std::function<bool(ShardIdFull)> check_shard_;
|
||||
std::function<bool(ShardIdFull, ShardCheckMode)> check_shard_;
|
||||
bool allow_blockchain_init_;
|
||||
td::ClocksBase::Duration sync_blocks_before_;
|
||||
td::ClocksBase::Duration block_ttl_;
|
||||
|
|
|
@ -46,9 +46,12 @@ class DownloadToken {
|
|||
|
||||
struct ValidatorManagerOptions : public td::CntObject {
|
||||
public:
|
||||
enum class ShardCheckMode { m_monitor, m_validate };
|
||||
|
||||
virtual BlockIdExt zero_block_id() const = 0;
|
||||
virtual BlockIdExt init_block_id() const = 0;
|
||||
virtual bool need_monitor(ShardIdFull shard) const = 0;
|
||||
virtual bool need_validate(ShardIdFull shard) const = 0;
|
||||
virtual bool allow_blockchain_init() const = 0;
|
||||
virtual td::ClocksBase::Duration sync_blocks_before() const = 0;
|
||||
virtual td::ClocksBase::Duration block_ttl() const = 0;
|
||||
|
@ -60,6 +63,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
|||
virtual td::uint32 get_vertical_seqno(BlockSeqno seqno) const = 0;
|
||||
virtual td::uint32 get_maximal_vertical_seqno() const = 0;
|
||||
virtual td::uint32 get_last_fork_masterchain_seqno() const = 0;
|
||||
virtual std::vector<BlockIdExt> get_hardforks() const = 0;
|
||||
virtual td::uint32 get_filedb_depth() const = 0;
|
||||
virtual td::uint32 key_block_utime_step() const {
|
||||
return 86400;
|
||||
|
@ -67,7 +71,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
|||
|
||||
virtual void set_zero_block_id(BlockIdExt block_id) = 0;
|
||||
virtual void set_init_block_id(BlockIdExt block_id) = 0;
|
||||
virtual void set_shard_check_function(std::function<bool(ShardIdFull)> check_shard) = 0;
|
||||
virtual void set_shard_check_function(std::function<bool(ShardIdFull, ShardCheckMode)> check_shard) = 0;
|
||||
virtual void set_allow_blockchain_init(bool value) = 0;
|
||||
virtual void set_sync_blocks_before(td::ClocksBase::Duration value) = 0;
|
||||
virtual void set_block_ttl(td::ClocksBase::Duration value) = 0;
|
||||
|
@ -80,7 +84,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
|||
|
||||
static td::Ref<ValidatorManagerOptions> create(
|
||||
BlockIdExt zero_block_id, BlockIdExt init_block_id,
|
||||
std::function<bool(ShardIdFull)> check_shard = [](ShardIdFull) { return true; },
|
||||
std::function<bool(ShardIdFull, ShardCheckMode)> check_shard = [](ShardIdFull, ShardCheckMode) { return true; },
|
||||
bool allow_blockchain_init = false, td::ClocksBase::Duration sync_blocks_before = 300,
|
||||
td::ClocksBase::Duration block_ttl = 86400 * 7, td::ClocksBase::Duration state_ttl = 3600,
|
||||
td::ClocksBase::Duration archive_ttl = 86400 * 365, td::ClocksBase::Duration key_proof_ttl = 86400 * 3650,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue