mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated submodules, bugfixes
- added new fift/func code for validator complaint creation - bugfixes in validator - updates in tonlib - new versions of rocksdb/abseil - hardfork support
This commit is contained in:
parent
16a4566091
commit
9f008b129f
129 changed files with 8438 additions and 879 deletions
|
@ -110,6 +110,25 @@ set(DISK_VALIDATOR_SOURCE
|
|||
${VALIDATOR_DB_SOURCE}
|
||||
)
|
||||
|
||||
set(HARDFORK_VALIDATOR_SOURCE
|
||||
apply-block.cpp
|
||||
block-handle.cpp
|
||||
shard-client.cpp
|
||||
validator-full-id.cpp
|
||||
validator-group.cpp
|
||||
validator-options.cpp
|
||||
|
||||
downloaders/wait-block-data-disk.cpp
|
||||
downloaders/wait-block-state.cpp
|
||||
downloaders/wait-block-state-merge.cpp
|
||||
downloaders/download-state.cpp
|
||||
|
||||
manager-init.cpp
|
||||
manager-hardfork.cpp
|
||||
|
||||
${VALIDATOR_DB_SOURCE}
|
||||
)
|
||||
|
||||
set(FULL_NODE_SOURCE
|
||||
full-node.h
|
||||
full-node.hpp
|
||||
|
@ -139,6 +158,7 @@ set(FULL_NODE_SOURCE
|
|||
|
||||
add_library(validator STATIC ${VALIDATOR_SOURCE})
|
||||
add_library(validator-disk STATIC ${DISK_VALIDATOR_SOURCE})
|
||||
add_library(validator-hardfork STATIC ${HARDFORK_VALIDATOR_SOURCE})
|
||||
add_library(full-node STATIC ${FULL_NODE_SOURCE})
|
||||
|
||||
target_include_directories(validator PUBLIC
|
||||
|
@ -155,6 +175,13 @@ target_include_directories(validator-disk PUBLIC
|
|||
${OPENSSL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_include_directories(validator-hardfork PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/..
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/../crypto
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_include_directories(full-node PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/..
|
||||
|
@ -168,5 +195,8 @@ target_link_libraries(validator PRIVATE tdutils tdactor adnl rldp tl_api dht tdf
|
|||
target_link_libraries(validator-disk PRIVATE tdutils tdactor adnl rldp tl_api dht tdfec
|
||||
overlay catchain validatorsession ton_crypto ton_block ton_db)
|
||||
|
||||
target_link_libraries(validator-hardfork PRIVATE tdutils tdactor adnl rldp tl_api dht tdfec
|
||||
overlay catchain validatorsession ton_crypto ton_block ton_db)
|
||||
|
||||
target_link_libraries(full-node PRIVATE tdutils tdactor adnl rldp tl_api dht tdfec
|
||||
overlay catchain validatorsession ton_crypto ton_block ton_db)
|
||||
|
|
|
@ -42,8 +42,8 @@ td::BufferSlice BlockHandleImpl::serialize() const {
|
|||
(flags & dbf_inited_masterchain_ref_block) ? masterchain_ref_seqno_ : 0);
|
||||
}
|
||||
|
||||
BlockHandleImpl::BlockHandleImpl(td::BufferSlice data) {
|
||||
auto obj = fetch_tl_object<ton_api::db_block_info>(std::move(data), true).move_as_ok();
|
||||
BlockHandleImpl::BlockHandleImpl(td::Slice data) {
|
||||
auto obj = fetch_tl_object<ton_api::db_block_info>(data, true).move_as_ok();
|
||||
flags_ = obj->flags_ & ~(Flags::dbf_processed | Flags::dbf_moved_handle);
|
||||
id_ = create_block_id(obj->id_);
|
||||
prev_[0] = (flags_ & dbf_inited_prev_left) ? create_block_id(obj->prev_left_) : BlockIdExt{};
|
||||
|
|
|
@ -517,7 +517,7 @@ struct BlockHandleImpl : public BlockHandleInterface {
|
|||
: id_(id), flags_(id_.is_masterchain() ? static_cast<td::uint32>(dbf_masterchain) : 0) {
|
||||
get_thread_safe_counter().add(1);
|
||||
}
|
||||
BlockHandleImpl(td::BufferSlice data);
|
||||
BlockHandleImpl(td::Slice data);
|
||||
~BlockHandleImpl() {
|
||||
LOG_CHECK(!need_flush()) << "flags=" << flags_;
|
||||
get_thread_safe_counter().add(-1);
|
||||
|
@ -532,7 +532,7 @@ struct BlockHandleImpl : public BlockHandleInterface {
|
|||
return std::make_shared<BlockHandleImpl>(id);
|
||||
}
|
||||
|
||||
static BlockHandle create(td::BufferSlice data) {
|
||||
static BlockHandle create(td::Slice data) {
|
||||
return std::make_shared<BlockHandleImpl>(std::move(data));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -77,10 +77,20 @@ void ArchiveManager::update_handle(BlockHandle handle, td::Promise<td::Unit> pro
|
|||
FileDescription *f;
|
||||
if (handle->handle_moved_to_archive()) {
|
||||
CHECK(handle->inited_unix_time());
|
||||
if (!handle->need_flush()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
f = get_file_desc(handle->id().shard_full(), get_package_id(handle->masterchain_ref_block()), handle->id().seqno(),
|
||||
handle->unix_time(), handle->logical_time(), true);
|
||||
if (!f) {
|
||||
handle->flushed_upto(handle->version());
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
f = get_file_desc(handle->id().shard_full(), get_temp_package_id(), 0, 0, 0, true);
|
||||
CHECK(f);
|
||||
}
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveSlice::update_handle, std::move(handle), std::move(promise));
|
||||
}
|
||||
|
@ -540,7 +550,7 @@ void ArchiveManager::load_package(PackageId id) {
|
|||
}
|
||||
}
|
||||
|
||||
desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, db_root_);
|
||||
desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_);
|
||||
|
||||
get_file_map(id).emplace(id, std::move(desc));
|
||||
}
|
||||
|
@ -551,7 +561,6 @@ ArchiveManager::FileDescription *ArchiveManager::get_file_desc(ShardIdFull shard
|
|||
auto it = f.find(id);
|
||||
if (it != f.end()) {
|
||||
if (it->second.deleted) {
|
||||
CHECK(!force);
|
||||
return nullptr;
|
||||
}
|
||||
if (force && !id.temp) {
|
||||
|
@ -574,7 +583,7 @@ ArchiveManager::FileDescription *ArchiveManager::add_file_desc(ShardIdFull shard
|
|||
FileDescription desc{id, false};
|
||||
td::mkdir(db_root_ + id.path()).ensure();
|
||||
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
||||
desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, db_root_);
|
||||
desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_);
|
||||
if (!id.temp) {
|
||||
update_desc(desc, shard, seqno, ts, lt);
|
||||
}
|
||||
|
@ -648,7 +657,11 @@ ArchiveManager::FileDescription *ArchiveManager::get_file_desc_by_seqno(ShardIdF
|
|||
for (auto it = f.rbegin(); it != f.rend(); it++) {
|
||||
auto i = it->second.first_blocks.find(shard);
|
||||
if (i != it->second.first_blocks.end() && i->second.seqno <= seqno) {
|
||||
return &it->second;
|
||||
if (it->second.deleted) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -660,7 +673,11 @@ ArchiveManager::FileDescription *ArchiveManager::get_file_desc_by_unix_time(Shar
|
|||
for (auto it = f.rbegin(); it != f.rend(); it++) {
|
||||
auto i = it->second.first_blocks.find(shard);
|
||||
if (i != it->second.first_blocks.end() && i->second.ts <= ts) {
|
||||
return &it->second;
|
||||
if (it->second.deleted) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -672,7 +689,11 @@ ArchiveManager::FileDescription *ArchiveManager::get_file_desc_by_lt(ShardIdFull
|
|||
for (auto it = f.rbegin(); it != f.rend(); it++) {
|
||||
auto i = it->second.first_blocks.find(shard);
|
||||
if (i != it->second.first_blocks.end() && i->second.lt <= lt) {
|
||||
return &it->second;
|
||||
if (it->second.deleted) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -823,6 +844,14 @@ void ArchiveManager::start_up() {
|
|||
}
|
||||
}
|
||||
|
||||
v = index_->get("finalizedupto", value);
|
||||
v.ensure();
|
||||
if (v.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto R = td::to_integer_safe<td::uint32>(value);
|
||||
R.ensure();
|
||||
finalized_up_to_ = R.move_as_ok();
|
||||
}
|
||||
|
||||
td::WalkPath::run(db_root_ + "/archive/states/", [&](td::CSlice fname, td::WalkPath::Type t) -> void {
|
||||
if (t == td::WalkPath::Type::NotDir) {
|
||||
LOG(ERROR) << "checking file " << fname;
|
||||
|
@ -853,7 +882,7 @@ void ArchiveManager::start_up() {
|
|||
persistent_state_gc(FileHash::zero());
|
||||
}
|
||||
|
||||
void ArchiveManager::run_gc(UnixTime ts) {
|
||||
void ArchiveManager::run_gc(UnixTime ts, UnixTime archive_ttl) {
|
||||
auto p = get_temp_package_id_by_unixtime(ts);
|
||||
std::vector<PackageId> vec;
|
||||
for (auto &x : temp_files_) {
|
||||
|
@ -863,13 +892,37 @@ void ArchiveManager::run_gc(UnixTime ts) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (vec.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
vec.resize(vec.size() - 1, PackageId::empty(false, true));
|
||||
if (vec.size() > 1) {
|
||||
vec.resize(vec.size() - 1, PackageId::empty(false, true));
|
||||
|
||||
for (auto &x : vec) {
|
||||
delete_package(x, [](td::Unit) {});
|
||||
for (auto &x : vec) {
|
||||
delete_package(x, [](td::Unit) {});
|
||||
}
|
||||
}
|
||||
vec.clear();
|
||||
|
||||
if (archive_ttl > 0) {
|
||||
for (auto &f : files_) {
|
||||
auto &desc = f.second;
|
||||
if (desc.deleted) {
|
||||
continue;
|
||||
}
|
||||
auto it = desc.first_blocks.find(ShardIdFull{masterchainId});
|
||||
if (it == desc.first_blocks.end()) {
|
||||
continue;
|
||||
}
|
||||
if (it->second.ts < ts - archive_ttl) {
|
||||
vec.push_back(f.first);
|
||||
}
|
||||
}
|
||||
if (vec.size() > 1) {
|
||||
vec.resize(vec.size() - 1, PackageId::empty(false, true));
|
||||
|
||||
for (auto &x : vec) {
|
||||
LOG(ERROR) << "WARNING: deleting package " << x.id;
|
||||
delete_package(x, [](td::Unit) {});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1049,6 +1102,102 @@ void ArchiveManager::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
|||
}
|
||||
}
|
||||
|
||||
void ArchiveManager::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
index_->begin_transaction().ensure();
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
ig.add_promise(std::move(promise));
|
||||
for (auto &x : temp_files_) {
|
||||
if (!x.second.deleted) {
|
||||
td::actor::send_closure(x.second.file_actor_id(), &ArchiveSlice::destroy, ig.get_promise());
|
||||
x.second.file.release();
|
||||
}
|
||||
}
|
||||
temp_files_.clear();
|
||||
|
||||
{
|
||||
auto it = key_files_.begin();
|
||||
while (it != key_files_.end()) {
|
||||
if (it->first.id <= masterchain_seqno) {
|
||||
td::actor::send_closure(it->second.file_actor_id(), &ArchiveSlice::truncate, masterchain_seqno, handle,
|
||||
ig.get_promise());
|
||||
it++;
|
||||
} else {
|
||||
auto it2 = it;
|
||||
it++;
|
||||
td::actor::send_closure(it2->second.file_actor_id(), &ArchiveSlice::destroy, ig.get_promise());
|
||||
it2->second.file.release();
|
||||
index_
|
||||
->erase(create_serialize_tl_object<ton_api::db_files_package_key>(it2->second.id.id, it2->second.id.key,
|
||||
it2->second.id.temp)
|
||||
.as_slice())
|
||||
.ensure();
|
||||
key_files_.erase(it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto it = files_.begin();
|
||||
while (it != files_.end()) {
|
||||
if (it->first.id <= masterchain_seqno) {
|
||||
td::actor::send_closure(it->second.file_actor_id(), &ArchiveSlice::truncate, masterchain_seqno, handle,
|
||||
ig.get_promise());
|
||||
it++;
|
||||
} else {
|
||||
auto it2 = it;
|
||||
it++;
|
||||
td::actor::send_closure(it2->second.file_actor_id(), &ArchiveSlice::destroy, ig.get_promise());
|
||||
it2->second.file.release();
|
||||
index_
|
||||
->erase(create_serialize_tl_object<ton_api::db_files_package_key>(it2->second.id.id, it2->second.id.key,
|
||||
it2->second.id.temp)
|
||||
.as_slice())
|
||||
.ensure();
|
||||
files_.erase(it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
std::vector<td::int32> t;
|
||||
std::vector<td::int32> tk;
|
||||
std::vector<td::int32> tt;
|
||||
for (auto &e : files_) {
|
||||
t.push_back(e.first.id);
|
||||
}
|
||||
for (auto &e : key_files_) {
|
||||
tk.push_back(e.first.id);
|
||||
}
|
||||
for (auto &e : temp_files_) {
|
||||
tt.push_back(e.first.id);
|
||||
}
|
||||
index_
|
||||
->set(create_serialize_tl_object<ton_api::db_files_index_key>().as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_files_index_value>(std::move(t), std::move(tk), std::move(tt))
|
||||
.as_slice())
|
||||
.ensure();
|
||||
}
|
||||
index_->commit_transaction().ensure();
|
||||
|
||||
{
|
||||
auto it = perm_states_.begin();
|
||||
while (it != perm_states_.end()) {
|
||||
int res = 0;
|
||||
it->second.ref().visit(td::overloaded(
|
||||
[&](const fileref::ZeroStateShort &x) { res = -1; },
|
||||
[&](const fileref::PersistentStateShort &x) { res = x.masterchain_seqno <= masterchain_seqno ? -1 : 1; },
|
||||
[&](const auto &obj) { res = 1; }));
|
||||
if (res <= 0) {
|
||||
it++;
|
||||
} else {
|
||||
auto it2 = it;
|
||||
it++;
|
||||
td::unlink(db_root_ + "/archive/states/" + it2->second.filename_short()).ignore();
|
||||
perm_states_.erase(it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -52,10 +52,10 @@ class ArchiveManager : public td::actor::Actor {
|
|||
void check_persistent_state(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::Promise<bool> promise);
|
||||
void check_zero_state(BlockIdExt block_id, td::Promise<bool> promise);
|
||||
|
||||
//void truncate(BlockSeqno masterchain_seqno, td::Promise<td::Unit> promise);
|
||||
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
||||
//void truncate_continue(BlockSeqno masterchain_seqno, td::Promise<td::Unit> promise);
|
||||
|
||||
void run_gc(UnixTime ts);
|
||||
void run_gc(UnixTime ts, UnixTime archive_ttl);
|
||||
|
||||
/* from LTDB */
|
||||
void get_block_by_unix_time(AccountIdPrefixFull account_id, UnixTime ts, td::Promise<ConstBlockHandle> promise);
|
||||
|
@ -104,6 +104,7 @@ class ArchiveManager : public td::actor::Actor {
|
|||
std::map<PackageId, FileDescription> files_;
|
||||
std::map<PackageId, FileDescription> key_files_;
|
||||
std::map<PackageId, FileDescription> temp_files_;
|
||||
BlockSeqno finalized_up_to_{0};
|
||||
bool async_mode_ = false;
|
||||
bool huge_transaction_started_ = false;
|
||||
td::uint32 huge_transaction_size_ = 0;
|
||||
|
|
|
@ -309,7 +309,7 @@ void ArchiveSlice::get_block_common(AccountIdPrefixFull account_id,
|
|||
}
|
||||
}
|
||||
f = true;
|
||||
auto G = fetch_tl_object<ton_api::db_lt_desc_value>(td::BufferSlice{value}, true);
|
||||
auto G = fetch_tl_object<ton_api::db_lt_desc_value>(value, true);
|
||||
G.ensure();
|
||||
auto g = G.move_as_ok();
|
||||
if (compare_desc(*g.get()) > 0) {
|
||||
|
@ -467,12 +467,18 @@ void ArchiveSlice::start_up() {
|
|||
R2 = kv_->get(PSTRING() << "status." << i, value);
|
||||
R2.ensure();
|
||||
auto len = td::to_integer<td::uint64>(value);
|
||||
R2 = kv_->get(PSTRING() << "version." << i, value);
|
||||
R2.ensure();
|
||||
td::uint32 ver = 0;
|
||||
if (R2.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
ver = td::to_integer<td::uint32>(value);
|
||||
}
|
||||
auto v = archive_id_ + slice_size_ * i;
|
||||
add_package(v, len);
|
||||
add_package(v, len, ver);
|
||||
}
|
||||
} else {
|
||||
auto len = td::to_integer<td::uint64>(value);
|
||||
add_package(archive_id_, len);
|
||||
add_package(archive_id_, len, 0);
|
||||
}
|
||||
} else {
|
||||
if (!temp_ && !key_blocks_only_) {
|
||||
|
@ -482,13 +488,15 @@ void ArchiveSlice::start_up() {
|
|||
kv_->set("slices", "1").ensure();
|
||||
kv_->set("slice_size", td::to_string(slice_size_)).ensure();
|
||||
kv_->set("status.0", "0").ensure();
|
||||
kv_->set("version.0", td::to_string(default_package_version())).ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
add_package(archive_id_, 0, default_package_version());
|
||||
} else {
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->set("status", "0").ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
add_package(archive_id_, 0, 0);
|
||||
}
|
||||
add_package(archive_id_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -528,8 +536,12 @@ void ArchiveSlice::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
|||
}
|
||||
}
|
||||
|
||||
ArchiveSlice::ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, std::string db_root)
|
||||
: archive_id_(archive_id), key_blocks_only_(key_blocks_only), temp_(temp), db_root_(std::move(db_root)) {
|
||||
ArchiveSlice::ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root)
|
||||
: archive_id_(archive_id)
|
||||
, key_blocks_only_(key_blocks_only)
|
||||
, temp_(temp)
|
||||
, finalized_(finalized)
|
||||
, db_root_(std::move(db_root)) {
|
||||
}
|
||||
|
||||
td::Result<ArchiveSlice::PackageInfo *> ArchiveSlice::choose_package(BlockSeqno masterchain_seqno, bool force) {
|
||||
|
@ -548,16 +560,17 @@ td::Result<ArchiveSlice::PackageInfo *> ArchiveSlice::choose_package(BlockSeqno
|
|||
begin_transaction();
|
||||
kv_->set("slices", td::to_string(v + 1)).ensure();
|
||||
kv_->set(PSTRING() << "status." << v, "0").ensure();
|
||||
kv_->set(PSTRING() << "version." << v, td::to_string(default_package_version())).ensure();
|
||||
commit_transaction();
|
||||
CHECK((masterchain_seqno - archive_id_) % slice_size_ == 0);
|
||||
add_package(masterchain_seqno, 0);
|
||||
add_package(masterchain_seqno, 0, default_package_version());
|
||||
return &packages_[v];
|
||||
} else {
|
||||
return &packages_[v];
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveSlice::add_package(td::uint32 seqno, td::uint64 size) {
|
||||
void ArchiveSlice::add_package(td::uint32 seqno, td::uint64 size, td::uint32 version) {
|
||||
PackageId p_id{seqno, key_blocks_only_, temp_};
|
||||
std::string path = PSTRING() << db_root_ << p_id.path() << p_id.name() << ".pack";
|
||||
auto R = Package::open(path, false, true);
|
||||
|
@ -565,9 +578,17 @@ void ArchiveSlice::add_package(td::uint32 seqno, td::uint64 size) {
|
|||
LOG(FATAL) << "failed to open/create archive '" << path << "': " << R.move_as_error();
|
||||
return;
|
||||
}
|
||||
auto idx = td::narrow_cast<td::uint32>(packages_.size());
|
||||
if (finalized_) {
|
||||
packages_.emplace_back(nullptr, td::actor::ActorOwn<PackageWriter>(), seqno, path, idx, version);
|
||||
return;
|
||||
}
|
||||
auto pack = std::make_shared<Package>(R.move_as_ok());
|
||||
if (version >= 1) {
|
||||
pack->truncate(size).ensure();
|
||||
}
|
||||
auto writer = td::actor::create_actor<PackageWriter>("writer", pack);
|
||||
packages_.emplace_back(std::move(pack), std::move(writer), seqno, path, 0);
|
||||
packages_.emplace_back(std::move(pack), std::move(writer), seqno, path, idx, version);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -609,6 +630,207 @@ void ArchiveSlice::destroy(td::Promise<td::Unit> promise) {
|
|||
td::Timestamp::in(0.0));
|
||||
}
|
||||
|
||||
BlockSeqno ArchiveSlice::max_masterchain_seqno() {
|
||||
auto key = get_db_key_lt_desc(ShardIdFull{masterchainId});
|
||||
std::string value;
|
||||
auto F = kv_->get(key, value);
|
||||
F.ensure();
|
||||
if (F.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
return 0;
|
||||
}
|
||||
auto G = fetch_tl_object<ton_api::db_lt_desc_value>(value, true);
|
||||
G.ensure();
|
||||
auto g = G.move_as_ok();
|
||||
if (g->first_idx_ == g->last_idx_) {
|
||||
return 0;
|
||||
}
|
||||
auto last_idx = g->last_idx_ - 1;
|
||||
auto db_key = get_db_key_lt_el(ShardIdFull{masterchainId}, last_idx);
|
||||
F = kv_->get(db_key, value);
|
||||
F.ensure();
|
||||
CHECK(F.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();
|
||||
return e->id_->seqno_;
|
||||
}
|
||||
|
||||
void ArchiveSlice::delete_file(FileReference ref_id) {
|
||||
std::string value;
|
||||
auto R = kv_->get(ref_id.hash().to_hex(), value);
|
||||
R.ensure();
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
return;
|
||||
}
|
||||
kv_->erase(ref_id.hash().to_hex());
|
||||
}
|
||||
|
||||
void ArchiveSlice::delete_handle(ConstBlockHandle handle) {
|
||||
delete_file(fileref::Proof{handle->id()});
|
||||
delete_file(fileref::ProofLink{handle->id()});
|
||||
delete_file(fileref::Block{handle->id()});
|
||||
kv_->erase(get_db_key_block_info(handle->id()));
|
||||
}
|
||||
|
||||
void ArchiveSlice::move_file(FileReference ref_id, Package *old_pack, Package *pack) {
|
||||
LOG(DEBUG) << "moving " << ref_id.filename_short();
|
||||
std::string value;
|
||||
auto R = kv_->get(ref_id.hash().to_hex(), value);
|
||||
R.ensure();
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
return;
|
||||
}
|
||||
auto offset = td::to_integer<td::uint64>(value);
|
||||
auto V = old_pack->read(offset);
|
||||
V.ensure();
|
||||
auto data = std::move(V.move_as_ok().second);
|
||||
auto r = pack->append(ref_id.filename(), std::move(data), false);
|
||||
kv_->set(ref_id.hash().to_hex(), td::to_string(r));
|
||||
}
|
||||
|
||||
void ArchiveSlice::move_handle(ConstBlockHandle handle, Package *old_pack, Package *pack) {
|
||||
move_file(fileref::Proof{handle->id()}, old_pack, pack);
|
||||
move_file(fileref::ProofLink{handle->id()}, old_pack, pack);
|
||||
move_file(fileref::Block{handle->id()}, old_pack, pack);
|
||||
}
|
||||
|
||||
bool ArchiveSlice::truncate_block(BlockSeqno masterchain_seqno, BlockIdExt block_id, td::uint32 cutoff_idx,
|
||||
Package *pack) {
|
||||
std::string value;
|
||||
auto R = kv_->get(get_db_key_block_info(block_id), value);
|
||||
R.ensure();
|
||||
CHECK(R.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
auto E = create_block_handle(value);
|
||||
E.ensure();
|
||||
auto handle = E.move_as_ok();
|
||||
auto seqno = handle->id().is_masterchain() ? handle->id().seqno() : handle->masterchain_ref_block();
|
||||
if (seqno > masterchain_seqno) {
|
||||
delete_handle(std::move(handle));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto S = choose_package(seqno, false);
|
||||
S.ensure();
|
||||
auto p = S.move_as_ok();
|
||||
CHECK(p->idx <= cutoff_idx);
|
||||
if (p->idx == cutoff_idx) {
|
||||
move_handle(std::move(handle), p->package.get(), pack);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArchiveSlice::truncate_shard(BlockSeqno masterchain_seqno, ShardIdFull shard, td::uint32 cutoff_idx,
|
||||
Package *pack) {
|
||||
auto key = get_db_key_lt_desc(shard);
|
||||
std::string value;
|
||||
auto F = kv_->get(key, value);
|
||||
F.ensure();
|
||||
if (F.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
return;
|
||||
}
|
||||
auto G = fetch_tl_object<ton_api::db_lt_desc_value>(value, true);
|
||||
G.ensure();
|
||||
auto g = G.move_as_ok();
|
||||
if (g->first_idx_ == g->last_idx_) {
|
||||
return;
|
||||
}
|
||||
|
||||
int new_last_idx = g->first_idx_;
|
||||
for (int i = g->first_idx_; i < g->last_idx_; i++) {
|
||||
auto db_key = get_db_key_lt_el(shard, i);
|
||||
F = kv_->get(db_key, value);
|
||||
F.ensure();
|
||||
CHECK(F.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
auto E = fetch_tl_object<ton_api::db_lt_el_value>(value, true);
|
||||
E.ensure();
|
||||
auto e = E.move_as_ok();
|
||||
|
||||
if (truncate_block(masterchain_seqno, create_block_id(e->id_), cutoff_idx, pack)) {
|
||||
CHECK(new_last_idx == i);
|
||||
new_last_idx = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (g->last_idx_ != new_last_idx) {
|
||||
g->last_idx_ = new_last_idx;
|
||||
kv_->set(key, serialize_tl_object(g, true)).ensure();
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveSlice::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
if (temp_ || archive_id_ > masterchain_seqno) {
|
||||
destroy(std::move(promise));
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "TRUNCATE: slice " << archive_id_ << " maxseqno= " << max_masterchain_seqno()
|
||||
<< " truncate_upto=" << masterchain_seqno;
|
||||
if (max_masterchain_seqno() <= masterchain_seqno) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
|
||||
auto cutoff = choose_package(masterchain_seqno, false);
|
||||
cutoff.ensure();
|
||||
auto pack = cutoff.move_as_ok();
|
||||
CHECK(pack);
|
||||
|
||||
auto pack_r = Package::open(pack->path + ".new", false, true);
|
||||
pack_r.ensure();
|
||||
auto new_package = std::make_shared<Package>(pack_r.move_as_ok());
|
||||
new_package->truncate(0).ensure();
|
||||
|
||||
std::string value;
|
||||
auto status_key = create_serialize_tl_object<ton_api::db_lt_status_key>();
|
||||
auto R = kv_->get(status_key, value);
|
||||
R.ensure();
|
||||
|
||||
auto F = fetch_tl_object<ton_api::db_lt_status_value>(value, true);
|
||||
F.ensure();
|
||||
auto f = F.move_as_ok();
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
for (int i = 0; i < f->total_shards_; i++) {
|
||||
auto shard_key = create_serialize_tl_object<ton_api::db_lt_shard_key>(i);
|
||||
R = kv_->get(shard_key, value);
|
||||
R.ensure();
|
||||
CHECK(R.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
|
||||
auto G = fetch_tl_object<ton_api::db_lt_shard_value>(value, true);
|
||||
G.ensure();
|
||||
auto g = G.move_as_ok();
|
||||
|
||||
truncate_shard(masterchain_seqno, ShardIdFull{g->workchain_, static_cast<td::uint64>(g->shard_)}, pack->idx,
|
||||
new_package.get());
|
||||
}
|
||||
|
||||
if (!sliced_mode_) {
|
||||
kv_->set("status", td::to_string(new_package->size())).ensure();
|
||||
} else {
|
||||
kv_->set(PSTRING() << "status." << pack->idx, td::to_string(new_package->size())).ensure();
|
||||
for (size_t i = pack->idx + 1; i < packages_.size(); i++) {
|
||||
kv_->erase(PSTRING() << "status." << i);
|
||||
kv_->erase(PSTRING() << "version." << i);
|
||||
}
|
||||
kv_->set("slices", td::to_string(pack->idx + 1));
|
||||
}
|
||||
|
||||
pack->package = new_package;
|
||||
pack->writer.reset();
|
||||
td::unlink(pack->path).ensure();
|
||||
td::rename(pack->path + ".new", pack->path).ensure();
|
||||
pack->writer = td::actor::create_actor<PackageWriter>("writer", new_package);
|
||||
|
||||
for (auto idx = pack->idx + 1; idx < packages_.size(); idx++) {
|
||||
td::unlink(packages_[idx].path).ensure();
|
||||
}
|
||||
packages_.erase(packages_.begin() + pack->idx + 1);
|
||||
|
||||
kv_->commit_transaction().ensure();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -73,7 +73,7 @@ class PackageWriter : public td::actor::Actor {
|
|||
|
||||
class ArchiveSlice : public td::actor::Actor {
|
||||
public:
|
||||
ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, std::string db_root);
|
||||
ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root);
|
||||
|
||||
void get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise);
|
||||
|
||||
|
@ -97,6 +97,7 @@ class ArchiveSlice : public td::actor::Actor {
|
|||
|
||||
void start_up() override;
|
||||
void destroy(td::Promise<td::Unit> promise);
|
||||
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
||||
|
||||
void begin_transaction();
|
||||
void commit_transaction();
|
||||
|
@ -117,6 +118,7 @@ class ArchiveSlice : public td::actor::Actor {
|
|||
|
||||
bool key_blocks_only_;
|
||||
bool temp_;
|
||||
bool finalized_;
|
||||
|
||||
bool destroyed_ = false;
|
||||
bool async_mode_ = false;
|
||||
|
@ -130,19 +132,38 @@ class ArchiveSlice : public td::actor::Actor {
|
|||
|
||||
struct PackageInfo {
|
||||
PackageInfo(std::shared_ptr<Package> package, td::actor::ActorOwn<PackageWriter> writer, BlockSeqno id,
|
||||
std::string path, td::uint32 idx)
|
||||
: package(std::move(package)), writer(std ::move(writer)), id(id), path(std::move(path)), idx(idx) {
|
||||
std::string path, td::uint32 idx, td::uint32 version)
|
||||
: package(std::move(package))
|
||||
, writer(std ::move(writer))
|
||||
, id(id)
|
||||
, path(std::move(path))
|
||||
, idx(idx)
|
||||
, version(version) {
|
||||
}
|
||||
std::shared_ptr<Package> package;
|
||||
td::actor::ActorOwn<PackageWriter> writer;
|
||||
BlockSeqno id;
|
||||
std::string path;
|
||||
td::uint32 idx;
|
||||
td::uint32 version;
|
||||
};
|
||||
std::vector<PackageInfo> packages_;
|
||||
|
||||
td::Result<PackageInfo *> choose_package(BlockSeqno masterchain_seqno, bool force);
|
||||
void add_package(BlockSeqno masterchain_seqno, td::uint64 size);
|
||||
void add_package(BlockSeqno masterchain_seqno, td::uint64 size, td::uint32 version);
|
||||
void truncate_shard(BlockSeqno masterchain_seqno, ShardIdFull shard, td::uint32 cutoff_idx, Package *pack);
|
||||
bool truncate_block(BlockSeqno masterchain_seqno, BlockIdExt block_id, td::uint32 cutoff_idx, Package *pack);
|
||||
|
||||
void delete_handle(ConstBlockHandle handle);
|
||||
void delete_file(FileReference ref_id);
|
||||
void move_handle(ConstBlockHandle handle, Package *old_pack, Package *pack);
|
||||
void move_file(FileReference ref_id, Package *old_pack, Package *pack);
|
||||
|
||||
BlockSeqno max_masterchain_seqno();
|
||||
|
||||
static constexpr td::uint32 default_package_version() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -44,9 +44,9 @@ void CellDbIn::start_up() {
|
|||
auto empty = get_empty_key_hash();
|
||||
if (get_block(empty).is_error()) {
|
||||
DbEntry e{get_empty_key(), empty, empty, RootHash::zero()};
|
||||
cell_db_->begin_transaction().ensure();
|
||||
cell_db_->begin_write_batch().ensure();
|
||||
set_block(empty, std::move(e));
|
||||
cell_db_->commit_transaction().ensure();
|
||||
cell_db_->commit_write_batch().ensure();
|
||||
}
|
||||
last_gc_ = empty;
|
||||
}
|
||||
|
@ -89,12 +89,12 @@ void CellDbIn::store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promi
|
|||
boc_->inc(cell);
|
||||
boc_->prepare_commit().ensure();
|
||||
vm::CellStorer stor{*cell_db_.get()};
|
||||
cell_db_->begin_transaction().ensure();
|
||||
cell_db_->begin_write_batch().ensure();
|
||||
boc_->commit(stor).ensure();
|
||||
set_block(empty, std::move(E));
|
||||
set_block(D.prev, std::move(P));
|
||||
set_block(key_hash, std::move(D));
|
||||
cell_db_->commit_transaction().ensure();
|
||||
cell_db_->commit_write_batch().ensure();
|
||||
|
||||
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot())).ensure();
|
||||
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
||||
|
@ -181,12 +181,12 @@ void CellDbIn::gc_cont2(BlockHandle handle) {
|
|||
boc_->dec(cell);
|
||||
boc_->prepare_commit().ensure();
|
||||
vm::CellStorer stor{*cell_db_.get()};
|
||||
cell_db_->begin_transaction().ensure();
|
||||
cell_db_->begin_write_batch().ensure();
|
||||
boc_->commit(stor).ensure();
|
||||
cell_db_->erase(get_key(last_gc_)).ensure();
|
||||
set_block(F.prev, std::move(P));
|
||||
set_block(F.next, std::move(N));
|
||||
cell_db_->commit_transaction().ensure();
|
||||
cell_db_->commit_write_batch().ensure();
|
||||
alarm_timestamp() = td::Timestamp::now();
|
||||
|
||||
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot())).ensure();
|
||||
|
|
|
@ -409,10 +409,13 @@ void RootDb::prepare_stats(td::Promise<std::vector<std::pair<std::string, std::s
|
|||
auto merger = StatsMerger::create(std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) {
|
||||
void RootDb::truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
ig.add_promise(std::move(promise));
|
||||
|
||||
td::actor::send_closure(archive_db_, &ArchiveManager::truncate, seqno, handle, ig.get_promise());
|
||||
td::actor::send_closure(state_db_, &StateDb::truncate, seqno, handle, ig.get_promise());
|
||||
}
|
||||
|
||||
void RootDb::add_key_block_proof(td::Ref<Proof> proof, td::Promise<td::Unit> promise) {
|
||||
|
@ -483,8 +486,8 @@ void RootDb::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
|||
td::actor::send_closure(archive_db_, &ArchiveManager::set_async_mode, mode, std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::run_gc(UnixTime ts) {
|
||||
td::actor::send_closure(archive_db_, &ArchiveManager::run_gc, ts);
|
||||
void RootDb::run_gc(UnixTime ts, UnixTime archive_ttl) {
|
||||
td::actor::send_closure(archive_db_, &ArchiveManager::run_gc, ts, archive_ttl);
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace validator {
|
|||
class RootDb : public Db {
|
||||
public:
|
||||
enum class Flags : td::uint32 { f_started = 1, f_ready = 2, f_switched = 4, f_archived = 8 };
|
||||
RootDb(td::actor::ActorId<ValidatorManager> validator_manager, std::string root_path, td::uint32 depth)
|
||||
: validator_manager_(validator_manager), root_path_(std::move(root_path)), depth_(depth) {
|
||||
RootDb(td::actor::ActorId<ValidatorManager> validator_manager, std::string root_path)
|
||||
: validator_manager_(validator_manager), root_path_(std::move(root_path)) {
|
||||
}
|
||||
|
||||
void start_up() override;
|
||||
|
@ -84,7 +84,8 @@ class RootDb : public Db {
|
|||
void apply_block(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
void get_block_by_lt(AccountIdPrefixFull account, LogicalTime lt, td::Promise<ConstBlockHandle> promise) override;
|
||||
void get_block_by_unix_time(AccountIdPrefixFull account, UnixTime ts, td::Promise<ConstBlockHandle> promise) override;
|
||||
void get_block_by_seqno(AccountIdPrefixFull account, BlockSeqno seqno, td::Promise<ConstBlockHandle> promise) override;
|
||||
void get_block_by_seqno(AccountIdPrefixFull account, BlockSeqno seqno,
|
||||
td::Promise<ConstBlockHandle> promise) override;
|
||||
|
||||
void update_init_masterchain_block(BlockIdExt block, td::Promise<td::Unit> promise) override;
|
||||
void get_init_masterchain_block(td::Promise<BlockIdExt> promise) override;
|
||||
|
@ -113,7 +114,7 @@ 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;
|
||||
void truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
|
||||
void add_key_block_proof(td::Ref<Proof> proof, td::Promise<td::Unit> promise) override;
|
||||
void add_key_block_proof_link(td::Ref<ProofLink> proof_link, td::Promise<td::Unit> promise) override;
|
||||
|
@ -127,13 +128,12 @@ class RootDb : public Db {
|
|||
td::Promise<td::BufferSlice> promise) override;
|
||||
void set_async_mode(bool mode, td::Promise<td::Unit> promise) override;
|
||||
|
||||
void run_gc(UnixTime ts) override;
|
||||
void run_gc(UnixTime ts, UnixTime archive_ttl) override;
|
||||
|
||||
private:
|
||||
td::actor::ActorId<ValidatorManager> validator_manager_;
|
||||
|
||||
std::string root_path_;
|
||||
td::uint32 depth_;
|
||||
|
||||
td::actor::ActorOwn<CellDb> cell_db_;
|
||||
td::actor::ActorOwn<StateDb> state_db_;
|
||||
|
|
|
@ -29,11 +29,11 @@ namespace validator {
|
|||
void StateDb::update_init_masterchain_block(BlockIdExt block, td::Promise<td::Unit> promise) {
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_initBlockId>();
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_state_initBlockId>(create_tl_block_id(block)).as_slice())
|
||||
.ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
@ -59,11 +59,11 @@ void StateDb::get_init_masterchain_block(td::Promise<BlockIdExt> promise) {
|
|||
void StateDb::update_gc_masterchain_block(BlockIdExt block, td::Promise<td::Unit> promise) {
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_gcBlockId>();
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_state_gcBlockId>(create_tl_block_id(block)).as_slice())
|
||||
.ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
@ -89,11 +89,11 @@ void StateDb::get_gc_masterchain_block(td::Promise<BlockIdExt> promise) {
|
|||
void StateDb::update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise) {
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_shardClient>();
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_state_shardClient>(create_tl_block_id(masterchain_block_id)))
|
||||
.ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
@ -120,10 +120,10 @@ void StateDb::update_destroyed_validator_sessions(std::vector<ValidatorSessionId
|
|||
td::Promise<td::Unit> promise) {
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_destroyedSessions>();
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(), create_serialize_tl_object<ton_api::db_state_destroyedSessions>(std::move(sessions)))
|
||||
.ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
@ -153,9 +153,9 @@ void StateDb::update_async_serializer_state(AsyncSerializerState state, td::Prom
|
|||
create_tl_block_id(state.last_block_id), create_tl_block_id(state.last_written_block_id),
|
||||
state.last_written_block_ts);
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(), value.as_slice()).ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
@ -188,9 +188,9 @@ void StateDb::update_hardforks(std::vector<BlockIdExt> blocks, td::Promise<td::U
|
|||
vec.push_back(create_tl_block_id(e));
|
||||
}
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(), create_serialize_tl_object<ton_api::db_state_hardforks>(std::move(vec))).ensure();
|
||||
kv_->commit_transaction();
|
||||
kv_->commit_write_batch();
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
@ -232,14 +232,95 @@ void StateDb::start_up() {
|
|||
auto f = F.move_as_ok();
|
||||
CHECK(f->version_ == 2);
|
||||
} else {
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(create_serialize_tl_object<ton_api::db_state_key_dbVersion>(),
|
||||
create_serialize_tl_object<ton_api::db_state_dbVersion>(2))
|
||||
.ensure();
|
||||
kv_->commit_transaction().ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
}
|
||||
}
|
||||
|
||||
void StateDb::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
{
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_asyncSerializer>();
|
||||
|
||||
std::string value;
|
||||
auto R = kv_->get(key.as_slice(), value);
|
||||
R.ensure();
|
||||
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto F = fetch_tl_object<ton_api::db_state_asyncSerializer>(value, true);
|
||||
F.ensure();
|
||||
auto obj = F.move_as_ok();
|
||||
if (static_cast<BlockSeqno>(obj->last_->seqno_) > masterchain_seqno) {
|
||||
CHECK(handle);
|
||||
CHECK(handle->inited_unix_time());
|
||||
obj->last_ = create_tl_block_id(handle->id());
|
||||
obj->last_ts_ = handle->unix_time();
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(), serialize_tl_object(obj, true)).ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_shardClient>();
|
||||
|
||||
std::string value;
|
||||
auto R = kv_->get(key.as_slice(), value);
|
||||
R.ensure();
|
||||
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto F = fetch_tl_object<ton_api::db_state_shardClient>(td::BufferSlice{value}, true);
|
||||
F.ensure();
|
||||
auto obj = F.move_as_ok();
|
||||
if (static_cast<BlockSeqno>(obj->block_->seqno_) > masterchain_seqno) {
|
||||
CHECK(handle);
|
||||
obj->block_ = create_tl_block_id(handle->id());
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(), serialize_tl_object(obj, true)).ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_gcBlockId>();
|
||||
|
||||
std::string value;
|
||||
auto R = kv_->get(key.as_slice(), value);
|
||||
R.ensure();
|
||||
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto F = fetch_tl_object<ton_api::db_state_gcBlockId>(td::BufferSlice{value}, true);
|
||||
F.ensure();
|
||||
auto obj = F.move_as_ok();
|
||||
CHECK(static_cast<BlockSeqno>(obj->block_->seqno_) <= masterchain_seqno);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto key = create_hash_tl_object<ton_api::db_state_key_initBlockId>();
|
||||
|
||||
std::string value;
|
||||
auto R = kv_->get(key.as_slice(), value);
|
||||
R.ensure();
|
||||
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto F = fetch_tl_object<ton_api::db_state_initBlockId>(td::BufferSlice{value}, true);
|
||||
F.ensure();
|
||||
auto obj = F.move_as_ok();
|
||||
if (static_cast<BlockSeqno>(obj->block_->seqno_) > masterchain_seqno) {
|
||||
CHECK(handle);
|
||||
obj->block_ = create_tl_block_id(handle->id());
|
||||
kv_->begin_write_batch().ensure();
|
||||
kv_->set(key.as_slice(), serialize_tl_object(obj, true)).ensure();
|
||||
kv_->commit_write_batch().ensure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -56,6 +56,7 @@ class StateDb : public td::actor::Actor {
|
|||
StateDb(td::actor::ActorId<RootDb> root_db, std::string path);
|
||||
|
||||
void start_up() override;
|
||||
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
||||
|
||||
private:
|
||||
using KeyType = td::Bits256;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "validator/fabric.h"
|
||||
#include "ton/ton-io.hpp"
|
||||
#include "common/checksum.h"
|
||||
#include "common/delay.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -95,8 +96,6 @@ void WaitBlockState::start() {
|
|||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::try_get_static_file, handle_->id().file_hash, std::move(P));
|
||||
} else if (handle_->id().id.seqno == 0) {
|
||||
// do not try to download full chain
|
||||
// download state + proof_link only
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::failed_to_get_state_from_net,
|
||||
|
@ -107,21 +106,19 @@ void WaitBlockState::start() {
|
|||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::send_get_zero_state_request, handle_->id(), priority_,
|
||||
std::move(P));
|
||||
} else if (block_.is_null()) {
|
||||
// download block and then prev state, not in reverse only
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<BlockData>> R) {
|
||||
} else if (!handle_->inited_prev() || (!handle_->inited_proof() && !handle_->inited_proof_link())) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle = handle_](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::failed_to_get_block_data,
|
||||
R.move_as_error_prefix("block wait error: "));
|
||||
delay_action([SelfId]() { td::actor::send_closure(SelfId, &WaitBlockState::start); }, td::Timestamp::in(0.1));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::got_block_data, R.move_as_ok());
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::got_proof_link, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::wait_block_data, handle_, priority_, timeout_, std::move(P));
|
||||
td::actor::send_closure(manager_, &ValidatorManager::send_get_block_proof_link_request, handle_->id(), priority_,
|
||||
std::move(P));
|
||||
} else if (prev_state_.is_null()) {
|
||||
CHECK(handle_->inited_proof() || handle_->inited_proof_link());
|
||||
CHECK(handle_->received());
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::failed_to_get_prev_state,
|
||||
|
@ -133,6 +130,28 @@ void WaitBlockState::start() {
|
|||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::wait_prev_block_state, handle_, priority_, timeout_,
|
||||
std::move(P));
|
||||
} else if (handle_->id().is_masterchain() && !handle_->inited_proof()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle = handle_](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
delay_action([SelfId]() { td::actor::send_closure(SelfId, &WaitBlockState::start); }, td::Timestamp::in(0.1));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::got_proof, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::send_get_block_proof_request, handle_->id(), priority_,
|
||||
std::move(P));
|
||||
} else if (block_.is_null()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<BlockData>> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::failed_to_get_block_data,
|
||||
R.move_as_error_prefix("block wait error: "));
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::got_block_data, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::wait_block_data, handle_, priority_, timeout_, std::move(P));
|
||||
} else {
|
||||
apply();
|
||||
}
|
||||
|
@ -152,6 +171,39 @@ void WaitBlockState::got_prev_state(td::Ref<ShardState> state) {
|
|||
start();
|
||||
}
|
||||
|
||||
void WaitBlockState::got_proof_link(td::BufferSlice data) {
|
||||
auto R = create_proof_link(handle_->id(), std::move(data));
|
||||
if (R.is_error()) {
|
||||
LOG(INFO) << "received bad proof link: " << R.move_as_error();
|
||||
start();
|
||||
return;
|
||||
}
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
if (R.is_ok()) {
|
||||
auto h = R.move_as_ok();
|
||||
CHECK(h->inited_prev());
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::start);
|
||||
} else {
|
||||
LOG(INFO) << "received bad proof link: " << R.move_as_error();
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::start);
|
||||
}
|
||||
});
|
||||
run_check_proof_link_query(handle_->id(), R.move_as_ok(), manager_, timeout_, std::move(P));
|
||||
}
|
||||
|
||||
void WaitBlockState::got_proof(td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
if (R.is_ok()) {
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::start);
|
||||
} else {
|
||||
LOG(INFO) << "received bad proof link: " << R.move_as_error();
|
||||
td::actor::send_closure(SelfId, &WaitBlockState::start);
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::validate_block_proof, handle_->id(), std::move(data),
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void WaitBlockState::failed_to_get_block_data(td::Status reason) {
|
||||
if (reason.code() == ErrorCode::notready) {
|
||||
start();
|
||||
|
|
|
@ -54,6 +54,8 @@ class WaitBlockState : public td::actor::Actor {
|
|||
void got_state_from_net(td::BufferSlice data);
|
||||
void failed_to_get_zero_state();
|
||||
void failed_to_get_state_from_net(td::Status reason);
|
||||
void got_proof_link(td::BufferSlice data);
|
||||
void got_proof(td::BufferSlice data);
|
||||
void apply();
|
||||
void written_state(td::Ref<ShardState> upd_state);
|
||||
void written_state_file();
|
||||
|
|
|
@ -25,8 +25,7 @@ namespace ton {
|
|||
|
||||
namespace validator {
|
||||
|
||||
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_,
|
||||
td::uint32 depth);
|
||||
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_);
|
||||
td::actor::ActorOwn<LiteServerCache> create_liteserver_cache_actor(td::actor::ActorId<ValidatorManager> manager,
|
||||
std::string db_root);
|
||||
|
||||
|
@ -38,6 +37,7 @@ td::Result<td::Ref<BlockSignatureSet>> create_signature_set(td::BufferSlice sig_
|
|||
td::Result<td::Ref<ShardState>> create_shard_state(BlockIdExt block_id, td::BufferSlice data);
|
||||
td::Result<td::Ref<ShardState>> create_shard_state(BlockIdExt block_id, td::Ref<vm::DataCell> root_cell);
|
||||
td::Result<BlockHandle> create_block_handle(td::BufferSlice data);
|
||||
td::Result<BlockHandle> create_block_handle(td::Slice data);
|
||||
td::Result<ConstBlockHandle> create_temp_block_handle(td::BufferSlice data);
|
||||
BlockHandle create_empty_block_handle(BlockIdExt id);
|
||||
td::Result<td::Ref<ExtMessage>> create_ext_message(td::BufferSlice data);
|
||||
|
@ -76,6 +76,9 @@ void run_collate_query(ShardIdFull shard, td::uint32 min_ts, const BlockIdExt& m
|
|||
std::vector<BlockIdExt> prev, Ed25519_PublicKey local_id, td::Ref<ValidatorSet> validator_set,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
|
||||
td::Promise<BlockCandidate> promise);
|
||||
void run_collate_hardfork(ShardIdFull shard, const BlockIdExt& min_masterchain_block_id, std::vector<BlockIdExt> prev,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
|
||||
td::Promise<BlockCandidate> promise);
|
||||
void run_liteserver_query(td::BufferSlice data, td::actor::ActorId<ValidatorManager> manager,
|
||||
td::actor::ActorId<LiteServerCache> cache, td::Promise<td::BufferSlice> promise);
|
||||
void run_validate_shard_block_description(td::BufferSlice data, BlockHandle masterchain_block,
|
||||
|
|
|
@ -262,9 +262,9 @@ bool AcceptBlockQuery::create_new_proof() {
|
|||
} else { // FAKE
|
||||
vm::CellBuilder cb2;
|
||||
if (!(cb2.store_long_bool(0x11, 8) // block_signatures#11
|
||||
&& cb2.store_long_bool(validator_set_->get_validator_set_hash(),
|
||||
&& cb2.store_long_bool(validator_set_.not_null() ? validator_set_->get_validator_set_hash() : 0,
|
||||
32) // validator_info$_ validator_set_hash_short:uint32
|
||||
&& cb2.store_long_bool(validator_set_->get_catchain_seqno(),
|
||||
&& cb2.store_long_bool(validator_set_.not_null() ? validator_set_->get_catchain_seqno() : 0,
|
||||
32) // validator_set_ts:uint32 = ValidatorInfo
|
||||
&& cb2.store_long_bool(0, 32) // sig_count:uint32
|
||||
&& cb2.store_long_bool(0, 64) // sig_weight:uint32
|
||||
|
@ -355,7 +355,7 @@ void AcceptBlockQuery::start_up() {
|
|||
VLOG(VALIDATOR_DEBUG) << "start_up()";
|
||||
alarm_timestamp() = timeout_;
|
||||
|
||||
if (validator_set_.is_null()) {
|
||||
if (!is_fork_ && validator_set_.is_null()) {
|
||||
fatal_error("no real ValidatorSet passed to AcceptBlockQuery");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -313,8 +313,8 @@ void CheckProof::start_up() {
|
|||
return;
|
||||
}
|
||||
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, id_,
|
||||
true, [SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, id_, true,
|
||||
[SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &CheckProof::abort_query, R.move_as_error());
|
||||
} else {
|
||||
|
@ -344,8 +344,8 @@ void CheckProof::got_block_handle(BlockHandle handle) {
|
|||
process_masterchain_state();
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(manager_, &ValidatorManager::wait_block_state_short, prev_[0], priority(),
|
||||
timeout_, [SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
td::actor::send_closure(manager_, &ValidatorManager::wait_block_state_short, prev_[0], priority(), timeout_,
|
||||
[SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
check_send_error(SelfId, R) ||
|
||||
td::actor::send_closure_bool(SelfId, &CheckProof::got_masterchain_state,
|
||||
td::Ref<MasterchainState>{R.move_as_ok()});
|
||||
|
@ -440,8 +440,8 @@ void CheckProof::check_signatures(Ref<ValidatorSet> s) {
|
|||
if (handle_) {
|
||||
got_block_handle_2(handle_);
|
||||
} else {
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, id_,
|
||||
true, [SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, id_, true,
|
||||
[SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
check_send_error(SelfId, R) ||
|
||||
td::actor::send_closure_bool(SelfId, &CheckProof::got_block_handle_2, R.move_as_ok());
|
||||
});
|
||||
|
@ -466,7 +466,10 @@ void CheckProof::got_block_handle_2(BlockHandle handle) {
|
|||
});
|
||||
if (skip_check_signatures_) {
|
||||
// do not save proof if we skipped signatures
|
||||
handle_->flush(manager_, handle_, std::move(P));
|
||||
auto proof = Ref<Proof>(proof_);
|
||||
CHECK(proof.not_null());
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::set_block_proof, handle_, std::move(proof),
|
||||
std::move(P));
|
||||
} else if (is_proof()) {
|
||||
auto proof = Ref<Proof>(proof_);
|
||||
CHECK(proof.not_null());
|
||||
|
|
|
@ -63,6 +63,7 @@ class Collator final : public td::actor::Actor {
|
|||
bool inbound_queues_empty_{false};
|
||||
bool libraries_changed_{false};
|
||||
bool prev_key_block_exists_{false};
|
||||
bool is_hardfork_{false};
|
||||
UnixTime min_ts;
|
||||
BlockIdExt min_mc_block_id;
|
||||
std::vector<BlockIdExt> prev_blocks;
|
||||
|
@ -85,9 +86,9 @@ class Collator final : public td::actor::Actor {
|
|||
static constexpr bool shard_splitting_enabled = true;
|
||||
|
||||
public:
|
||||
Collator(ShardIdFull shard, td::uint32 min_ts, BlockIdExt min_masterchain_block_id, std::vector<BlockIdExt> prev,
|
||||
Ref<ValidatorSet> validator_set, Ed25519_PublicKey collator_id, td::actor::ActorId<ValidatorManager> manager,
|
||||
td::Timestamp timeout, td::Promise<BlockCandidate> promise);
|
||||
Collator(ShardIdFull shard, bool is_hardfork, td::uint32 min_ts, BlockIdExt min_masterchain_block_id,
|
||||
std::vector<BlockIdExt> prev, Ref<ValidatorSet> validator_set, Ed25519_PublicKey collator_id,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout, td::Promise<BlockCandidate> promise);
|
||||
~Collator() override = default;
|
||||
bool is_busy() const {
|
||||
return busy_;
|
||||
|
|
|
@ -54,11 +54,12 @@ static inline bool dbg(int c) {
|
|||
return true;
|
||||
}
|
||||
|
||||
Collator::Collator(ShardIdFull shard, UnixTime min_ts, BlockIdExt min_masterchain_block_id,
|
||||
Collator::Collator(ShardIdFull shard, bool is_hardfork, UnixTime min_ts, BlockIdExt min_masterchain_block_id,
|
||||
std::vector<BlockIdExt> prev, td::Ref<ValidatorSet> validator_set, Ed25519_PublicKey collator_id,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
|
||||
td::Promise<BlockCandidate> promise)
|
||||
: shard_(shard)
|
||||
, is_hardfork_(is_hardfork)
|
||||
, min_ts(min_ts)
|
||||
, min_mc_block_id{min_masterchain_block_id}
|
||||
, prev_blocks(std::move(prev))
|
||||
|
@ -75,6 +76,9 @@ void Collator::start_up() {
|
|||
if (prev_blocks.size() > 1) {
|
||||
LOG(DEBUG) << "Previous block #2 is " << prev_blocks.at(1).to_str();
|
||||
}
|
||||
if (is_hardfork_ && workchain() == masterchainId) {
|
||||
is_key_block_ = true;
|
||||
}
|
||||
// 1. check validity of parameters, especially prev_blocks, shard and min_mc_block_id
|
||||
if (workchain() != ton::masterchainId && workchain() != ton::basechainId) {
|
||||
fatal_error(-667, "can create block candidates only for masterchain (-1) and base workchain (0)");
|
||||
|
@ -162,12 +166,26 @@ void Collator::start_up() {
|
|||
// 2. learn latest masterchain state and block id
|
||||
LOG(DEBUG) << "sending get_top_masterchain_state_block() to Manager";
|
||||
++pending;
|
||||
td::actor::send_closure_later(manager, &ValidatorManager::get_top_masterchain_state_block,
|
||||
[self = get_self()](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) {
|
||||
LOG(DEBUG) << "got answer to get_top_masterchain_state_block";
|
||||
td::actor::send_closure_later(std::move(self), &Collator::after_get_mc_state,
|
||||
std::move(res));
|
||||
});
|
||||
if (!is_hardfork_) {
|
||||
td::actor::send_closure_later(manager, &ValidatorManager::get_top_masterchain_state_block,
|
||||
[self = get_self()](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) {
|
||||
LOG(DEBUG) << "got answer to get_top_masterchain_state_block";
|
||||
td::actor::send_closure_later(std::move(self), &Collator::after_get_mc_state,
|
||||
std::move(res));
|
||||
});
|
||||
} else {
|
||||
td::actor::send_closure_later(
|
||||
manager, &ValidatorManager::get_shard_state_from_db_short, min_mc_block_id,
|
||||
[self = get_self(), block_id = min_mc_block_id](td::Result<Ref<ShardState>> res) {
|
||||
LOG(DEBUG) << "got answer to get_top_masterchain_state_block";
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure_later(std::move(self), &Collator::after_get_mc_state, res.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(std::move(self), &Collator::after_get_mc_state,
|
||||
std::make_pair(Ref<MasterchainState>(res.move_as_ok()), block_id));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// 3. load previous block(s) and corresponding state(s)
|
||||
prev_states.resize(prev_blocks.size());
|
||||
|
@ -195,16 +213,21 @@ void Collator::start_up() {
|
|||
});
|
||||
}
|
||||
}
|
||||
if (is_hardfork_) {
|
||||
LOG(WARNING) << "generating a hardfork block";
|
||||
}
|
||||
// 4. load external messages
|
||||
LOG(DEBUG) << "sending get_external_messages() query to Manager";
|
||||
++pending;
|
||||
td::actor::send_closure_later(manager, &ValidatorManager::get_external_messages, shard_,
|
||||
[self = get_self()](td::Result<std::vector<Ref<ExtMessage>>> res) -> void {
|
||||
LOG(DEBUG) << "got answer to get_external_messages() query";
|
||||
td::actor::send_closure_later(std::move(self), &Collator::after_get_external_messages,
|
||||
std::move(res));
|
||||
});
|
||||
if (is_masterchain()) {
|
||||
if (!is_hardfork_) {
|
||||
LOG(DEBUG) << "sending get_external_messages() query to Manager";
|
||||
++pending;
|
||||
td::actor::send_closure_later(manager, &ValidatorManager::get_external_messages, shard_,
|
||||
[self = get_self()](td::Result<std::vector<Ref<ExtMessage>>> res) -> void {
|
||||
LOG(DEBUG) << "got answer to get_external_messages() query";
|
||||
td::actor::send_closure_later(
|
||||
std::move(self), &Collator::after_get_external_messages, std::move(res));
|
||||
});
|
||||
}
|
||||
if (is_masterchain() && !is_hardfork_) {
|
||||
// 5. load shard block info messages
|
||||
LOG(DEBUG) << "sending get_shard_blocks() query to Manager";
|
||||
++pending;
|
||||
|
@ -487,6 +510,7 @@ void Collator::after_get_shard_blocks(td::Result<std::vector<Ref<ShardTopBlockDe
|
|||
--pending;
|
||||
if (res.is_error()) {
|
||||
fatal_error(res.move_as_error());
|
||||
return;
|
||||
}
|
||||
auto vect = res.move_as_ok();
|
||||
shard_block_descr_ = std::move(vect);
|
||||
|
@ -521,7 +545,7 @@ bool Collator::unpack_last_mc_state() {
|
|||
prev_key_block_seqno_ = 0;
|
||||
}
|
||||
LOG(DEBUG) << "previous key block is " << prev_key_block_.to_str() << " (exists=" << prev_key_block_exists_ << ")";
|
||||
vert_seqno_ = config_->get_vert_seqno();
|
||||
vert_seqno_ = config_->get_vert_seqno() + (is_hardfork_ ? 1 : 0);
|
||||
LOG(DEBUG) << "vertical seqno (vert_seqno) is " << vert_seqno_;
|
||||
auto limits = config_->get_block_limits(is_masterchain());
|
||||
if (limits.is_error()) {
|
||||
|
@ -549,6 +573,9 @@ bool Collator::unpack_last_mc_state() {
|
|||
}
|
||||
|
||||
bool Collator::check_cur_validator_set() {
|
||||
if (is_hardfork_) {
|
||||
return true;
|
||||
}
|
||||
CatchainSeqno cc_seqno = 0;
|
||||
auto nodes = config_->compute_validator_set_cc(shard_, now_, &cc_seqno);
|
||||
if (nodes.empty()) {
|
||||
|
@ -3083,12 +3110,16 @@ bool Collator::create_mc_state_extra() {
|
|||
auto cfg_smc_config = cfg_res.move_as_ok();
|
||||
CHECK(cfg_smc_config.not_null());
|
||||
vm::Dictionary cfg_dict{cfg_smc_config, 32};
|
||||
bool ignore_cfg_changes = false;
|
||||
Ref<vm::Cell> cfg0;
|
||||
if (!block::valid_config_data(cfg_smc_config, config_addr, true, true, old_mparams_)) {
|
||||
block::gen::t_Hashmap_32_Ref_Cell.print_ref(std::cerr, cfg_smc_config);
|
||||
return fatal_error("configuration smart contract "s + config_addr.to_hex() +
|
||||
" contains an invalid configuration in its data");
|
||||
LOG(ERROR) << "configuration smart contract "s + config_addr.to_hex() +
|
||||
" contains an invalid configuration in its data, IGNORING CHANGES";
|
||||
ignore_cfg_changes = true;
|
||||
} else {
|
||||
cfg0 = cfg_dict.lookup_ref(td::BitArray<32>(1 - 1));
|
||||
}
|
||||
Ref<vm::Cell> cfg0 = cfg_dict.lookup_ref(td::BitArray<32>(1 - 1));
|
||||
bool changed_cfg = false;
|
||||
if (cfg0.not_null()) {
|
||||
ton::StdSmcAddress new_config_addr;
|
||||
|
@ -3101,7 +3132,11 @@ bool Collator::create_mc_state_extra() {
|
|||
changed_cfg = true;
|
||||
}
|
||||
}
|
||||
if (block::important_config_parameters_changed(cfg_smc_config, state_extra.config->prefetch_ref()) || changed_cfg) {
|
||||
if (ignore_cfg_changes) {
|
||||
LOG(ERROR) << "configuration changes ignored";
|
||||
return fatal_error("attempting to install invalid new configuration");
|
||||
} else if (block::important_config_parameters_changed(cfg_smc_config, state_extra.config->prefetch_ref()) ||
|
||||
changed_cfg) {
|
||||
LOG(WARNING) << "global configuration changed, updating";
|
||||
vm::CellBuilder cb;
|
||||
CHECK(cb.store_bits_bool(config_addr) && cb.store_ref_bool(cfg_smc_config));
|
||||
|
@ -3625,6 +3660,7 @@ bool Collator::store_master_ref(vm::CellBuilder& cb) {
|
|||
|
||||
bool Collator::update_processed_upto() {
|
||||
auto ref_mc_seqno = is_masterchain() ? new_block_seqno : prev_mc_block_seqno;
|
||||
update_min_mc_seqno(ref_mc_seqno);
|
||||
if (last_proc_int_msg_.first) {
|
||||
if (!processed_upto_->insert(ref_mc_seqno, last_proc_int_msg_.first, last_proc_int_msg_.second.cbits())) {
|
||||
return fatal_error("cannot update our ProcessedUpto to reflect processed inbound message");
|
||||
|
@ -3694,8 +3730,8 @@ bool Collator::compute_total_balance() {
|
|||
bool Collator::create_block_info(Ref<vm::Cell>& block_info) {
|
||||
vm::CellBuilder cb, cb2;
|
||||
bool mc = is_masterchain();
|
||||
td::uint32 val_hash = validator_set_->get_validator_set_hash();
|
||||
CatchainSeqno cc_seqno = validator_set_->get_catchain_seqno();
|
||||
td::uint32 val_hash = is_hardfork_ ? 0 : validator_set_->get_validator_set_hash();
|
||||
CatchainSeqno cc_seqno = is_hardfork_ ? 0 : validator_set_->get_catchain_seqno();
|
||||
return cb.store_long_bool(0x9bc7a987, 32) // block_info#9bc7a987
|
||||
&& cb.store_long_bool(0, 32) // version:uint32
|
||||
&& cb.store_bool_bool(!mc) // not_master:(## 1)
|
||||
|
@ -3705,7 +3741,8 @@ bool Collator::create_block_info(Ref<vm::Cell>& block_info) {
|
|||
&& cb.store_bool_bool(want_split_) // want_split:Bool
|
||||
&& cb.store_bool_bool(want_merge_) // want_merge:Bool
|
||||
&& cb.store_bool_bool(is_key_block_) // key_block:Bool
|
||||
&& cb.store_long_bool((int)report_version_, 9) // vert_seqno_incr:(## 1) flags:(## 8)
|
||||
&& cb.store_bool_bool(is_hardfork_) // vert_seqno_incr:(## 1)
|
||||
&& cb.store_long_bool((int)report_version_, 8) // flags:(## 8)
|
||||
&& cb.store_long_bool(new_block_seqno, 32) // seq_no:#
|
||||
&& cb.store_long_bool(vert_seqno_, 32) // vert_seq_no:#
|
||||
&& block::ShardId{shard_}.serialize(cb) // shard:ShardIdent
|
||||
|
@ -3721,6 +3758,9 @@ bool Collator::create_block_info(Ref<vm::Cell>& block_info) {
|
|||
&& cb.store_builder_ref_bool(std::move(cb2)))) // .. ^BlkMasterInfo
|
||||
&& store_prev_blk_ref(cb2, after_merge_) // prev_ref:..
|
||||
&& cb.store_builder_ref_bool(std::move(cb2)) // .. ^(PrevBlkInfo after_merge)
|
||||
&& (!is_hardfork_ || // prev_vert_ref:vert_seqno_incr?..
|
||||
(store_master_ref(cb2) //
|
||||
&& cb.store_builder_ref_bool(std::move(cb2)))) // .. ^(BlkPrevInfo 0)
|
||||
&& cb.finalize_to(block_info);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,8 @@ namespace ton {
|
|||
|
||||
namespace validator {
|
||||
|
||||
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_,
|
||||
td::uint32 depth) {
|
||||
return td::actor::create_actor<RootDb>("db", manager, db_root_, depth);
|
||||
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_) {
|
||||
return td::actor::create_actor<RootDb>("db", manager, db_root_);
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<LiteServerCache> create_liteserver_cache_actor(td::actor::ActorId<ValidatorManager> manager,
|
||||
|
@ -93,7 +92,11 @@ td::Result<td::Ref<ShardState>> create_shard_state(BlockIdExt block_id, td::Ref<
|
|||
}
|
||||
|
||||
td::Result<BlockHandle> create_block_handle(td::BufferSlice data) {
|
||||
return ton::validator::BlockHandleImpl::create(std::move(data));
|
||||
return ton::validator::BlockHandleImpl::create(data.as_slice());
|
||||
}
|
||||
|
||||
td::Result<BlockHandle> create_block_handle(td::Slice data) {
|
||||
return ton::validator::BlockHandleImpl::create(data);
|
||||
}
|
||||
|
||||
td::Result<ConstBlockHandle> create_temp_block_handle(td::BufferSlice data) {
|
||||
|
@ -208,9 +211,24 @@ void run_collate_query(ShardIdFull shard, td::uint32 min_ts, const BlockIdExt& m
|
|||
seqno = p.seqno();
|
||||
}
|
||||
}
|
||||
td::actor::create_actor<Collator>(PSTRING() << "collate" << shard.to_str() << ":" << (seqno + 1), shard, min_ts,
|
||||
min_masterchain_block_id, std::move(prev), std::move(validator_set), collator_id,
|
||||
std::move(manager), timeout, std::move(promise))
|
||||
td::actor::create_actor<Collator>(PSTRING() << "collate" << shard.to_str() << ":" << (seqno + 1), shard, false,
|
||||
min_ts, min_masterchain_block_id, std::move(prev), std::move(validator_set),
|
||||
collator_id, std::move(manager), timeout, std::move(promise))
|
||||
.release();
|
||||
}
|
||||
|
||||
void run_collate_hardfork(ShardIdFull shard, const BlockIdExt& min_masterchain_block_id, std::vector<BlockIdExt> prev,
|
||||
td::actor::ActorId<ValidatorManager> manager, td::Timestamp timeout,
|
||||
td::Promise<BlockCandidate> promise) {
|
||||
BlockSeqno seqno = 0;
|
||||
for (auto& p : prev) {
|
||||
if (p.seqno() > seqno) {
|
||||
seqno = p.seqno();
|
||||
}
|
||||
}
|
||||
td::actor::create_actor<Collator>(PSTRING() << "collate" << shard.to_str() << ":" << (seqno + 1), shard, true, 0,
|
||||
min_masterchain_block_id, std::move(prev), td::Ref<ValidatorSet>{},
|
||||
Ed25519_PublicKey{Bits256::zero()}, std::move(manager), timeout, std::move(promise))
|
||||
.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "block/block.h"
|
||||
#include "block/block-parse.h"
|
||||
#include "block/block-auto.h"
|
||||
#include "block/check-proof.h"
|
||||
#include "vm/dict.h"
|
||||
#include "vm/cells/MerkleProof.h"
|
||||
#include "vm/vm.h"
|
||||
|
@ -160,10 +161,10 @@ void LiteQuery::start_up() {
|
|||
static_cast<LogicalTime>((q.mode_ & 128) ? (q.after_->lt_) : 0));
|
||||
},
|
||||
[&](lite_api::liteServer_getConfigParams& q) {
|
||||
this->perform_getConfigParams(ton::create_block_id(q.id_), (q.mode_ & 0xfff) | 0x1000, q.param_list_);
|
||||
this->perform_getConfigParams(ton::create_block_id(q.id_), (q.mode_ & 0xffff) | 0x10000, q.param_list_);
|
||||
},
|
||||
[&](lite_api::liteServer_getConfigAll& q) {
|
||||
this->perform_getConfigParams(ton::create_block_id(q.id_), (q.mode_ & 0xfff) | 0x2000);
|
||||
this->perform_getConfigParams(ton::create_block_id(q.id_), (q.mode_ & 0xffff) | 0x20000);
|
||||
},
|
||||
[&](lite_api::liteServer_getBlockProof& q) {
|
||||
this->perform_getBlockProof(ton::create_block_id(q.known_block_),
|
||||
|
@ -204,7 +205,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 {
|
||||
|
@ -242,7 +243,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 {
|
||||
|
@ -268,7 +269,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 {
|
||||
|
@ -383,7 +384,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 {
|
||||
|
@ -393,7 +394,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 {
|
||||
|
@ -452,7 +453,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() + " : "));
|
||||
|
@ -478,7 +479,7 @@ bool LiteQuery::request_mc_proof(BlockIdExt blkid, int mode) {
|
|||
++pending_;
|
||||
td::actor::send_closure(
|
||||
manager_, &ValidatorManager::get_key_block_proof, blkid,
|
||||
[ Self = actor_id(this), manager = manager_, blkid, mode ](td::Result<td::BufferSlice> R) {
|
||||
[Self = actor_id(this), manager = manager_, blkid, mode](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_ok()) {
|
||||
auto proof = create_proof(blkid, R.move_as_ok());
|
||||
proof.ensure();
|
||||
|
@ -510,7 +511,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() + " : "));
|
||||
|
@ -541,7 +542,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() + " : "));
|
||||
|
@ -563,7 +564,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() + " : "));
|
||||
|
@ -586,7 +587,7 @@ bool LiteQuery::request_proof_link(BlockIdExt blkid) {
|
|||
if (blkid.is_masterchain()) {
|
||||
td::actor::send_closure(
|
||||
manager_, &ValidatorManager::get_key_block_proof_link, blkid,
|
||||
[ Self = actor_id(this), manager = manager_, blkid ](td::Result<td::BufferSlice> R) {
|
||||
[Self = actor_id(this), manager = manager_, blkid](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_ok()) {
|
||||
auto proof = create_proof(blkid, R.move_as_ok());
|
||||
proof.ensure();
|
||||
|
@ -608,7 +609,7 @@ bool LiteQuery::request_proof_link(BlockIdExt blkid) {
|
|||
} else {
|
||||
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() + " : "));
|
||||
|
@ -634,7 +635,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() + " : "));
|
||||
|
@ -679,7 +680,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 {
|
||||
|
@ -781,7 +782,7 @@ void LiteQuery::got_mc_block_state(BlockIdExt blkid, Ref<ShardState> state) {
|
|||
void LiteQuery::got_block_data(BlockIdExt blkid, Ref<BlockData> data) {
|
||||
LOG(INFO) << "obtained data for getBlock(" << blkid.to_str() << ") needed by a liteserver query";
|
||||
CHECK(data.not_null());
|
||||
block_ = std::move(data);
|
||||
block_ = Ref<BlockQ>(std::move(data));
|
||||
CHECK(block_.not_null());
|
||||
CHECK(blkid == blk_id_);
|
||||
dec_pending();
|
||||
|
@ -790,7 +791,7 @@ void LiteQuery::got_block_data(BlockIdExt blkid, Ref<BlockData> data) {
|
|||
void LiteQuery::got_mc_block_data(BlockIdExt blkid, Ref<BlockData> data) {
|
||||
LOG(INFO) << "obtained data for getBlock(" << blkid.to_str() << ") needed by a liteserver query";
|
||||
CHECK(data.not_null());
|
||||
mc_block_ = std::move(data);
|
||||
mc_block_ = Ref<BlockQ>(std::move(data));
|
||||
CHECK(mc_block_.not_null());
|
||||
CHECK(blkid == base_blk_id_);
|
||||
dec_pending();
|
||||
|
@ -1268,14 +1269,14 @@ 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<ConstBlockHandle> res) {
|
||||
trans_lt_, [Self = actor_id(this), remaining, manager = manager_](td::Result<ConstBlockHandle> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, res.move_as_error(), ton::BlockIdExt{});
|
||||
} else {
|
||||
auto handle = res.move_as_ok();
|
||||
LOG(DEBUG) << "requesting data for block " << handle->id().to_str();
|
||||
td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db, handle,
|
||||
[ Self, blkid = handle->id(), remaining ](td::Result<Ref<BlockData>> res) {
|
||||
[Self, blkid = handle->id(), remaining](td::Result<Ref<BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_getTransactions,
|
||||
res.move_as_error(), blkid);
|
||||
|
@ -1293,7 +1294,7 @@ void LiteQuery::continue_getTransactions_2(BlockIdExt blkid, Ref<BlockData> bloc
|
|||
--pending_;
|
||||
CHECK(!pending_);
|
||||
CHECK(block.not_null());
|
||||
block_ = block;
|
||||
block_ = Ref<BlockQ>(std::move(block));
|
||||
blk_id_ = blkid;
|
||||
continue_getTransactions(remaining, true);
|
||||
}
|
||||
|
@ -1339,24 +1340,122 @@ void LiteQuery::perform_getShardInfo(BlockIdExt blkid, ShardIdFull shard, bool e
|
|||
request_mc_block_data_state(blkid);
|
||||
}
|
||||
|
||||
void LiteQuery::load_prevKeyBlock(ton::BlockIdExt blkid, td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>> promise) {
|
||||
td::actor::send_closure_later(manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[Self = actor_id(this), blkid, promise = std::move(promise)](
|
||||
td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) mutable {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_loadPrevKeyBlock, blkid,
|
||||
std::move(res), std::move(promise));
|
||||
});
|
||||
}
|
||||
|
||||
void LiteQuery::continue_loadPrevKeyBlock(ton::BlockIdExt blkid,
|
||||
td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res,
|
||||
td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>> promise) {
|
||||
TRY_RESULT_PROMISE(promise, pair, std::move(res));
|
||||
base_blk_id_ = pair.second;
|
||||
if (!base_blk_id_.is_masterchain_ext()) {
|
||||
promise.set_error(
|
||||
td::Status::Error(PSTRING() << "the most recent masterchain block " << base_blk_id_.to_str() << " is invalid"));
|
||||
return;
|
||||
}
|
||||
auto state = Ref<MasterchainStateQ>(std::move(pair.first));
|
||||
if (state.is_null()) {
|
||||
promise.set_error(
|
||||
td::Status::Error(PSLICE() << "obtained no valid masterchain state for block " << base_blk_id_.to_str()));
|
||||
return;
|
||||
}
|
||||
if (blkid.seqno() > base_blk_id_.seqno()) {
|
||||
promise.set_error(td::Status::Error(PSLICE()
|
||||
<< "client knows block " << blkid.to_str()
|
||||
<< " newer than the reference masterchain block " << base_blk_id_.to_str()));
|
||||
return;
|
||||
}
|
||||
mc_state0_ = Ref<MasterchainStateQ>(state);
|
||||
if (base_blk_id_ != state->get_block_id()) {
|
||||
promise.set_error(td::Status::Error(PSLICE() << "the state for " << base_blk_id_.to_str()
|
||||
<< " is in fact a state for different block "
|
||||
<< state->get_block_id().to_str()));
|
||||
return;
|
||||
}
|
||||
if (!state->check_old_mc_block_id(blkid)) {
|
||||
promise.set_error(td::Status::Error(PSLICE() << "requested masterchain block " << blkid.to_str()
|
||||
<< " is unknown from the perspective of reference block "
|
||||
<< base_blk_id_.to_str()));
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "continuing load_prevKeyBlock(" << blkid.to_str() << ") query with a state for "
|
||||
<< base_blk_id_.to_str();
|
||||
auto key_blk_id = state->prev_key_block_id(blkid.seqno());
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_data_from_db_short, key_blk_id,
|
||||
[Self = actor_id(this), key_blk_id, promise = std::move(promise)](td::Result<Ref<BlockData>> res) mutable {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::finish_loadPrevKeyBlock, key_blk_id, std::move(res),
|
||||
std::move(promise));
|
||||
});
|
||||
}
|
||||
|
||||
void LiteQuery::finish_loadPrevKeyBlock(ton::BlockIdExt blkid, td::Result<Ref<BlockData>> res,
|
||||
td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>> promise) {
|
||||
TRY_RESULT_PROMISE_PREFIX(promise, data, std::move(res), PSLICE() << "cannot load block " << blkid.to_str() << " : ");
|
||||
Ref<BlockQ> data0{std::move(data)};
|
||||
if (data0.is_null()) {
|
||||
promise.set_error(td::Status::Error("no block data for key block "s + blkid.to_str()));
|
||||
return;
|
||||
}
|
||||
promise.set_result(std::make_pair(blkid, std::move(data0)));
|
||||
}
|
||||
|
||||
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 {
|
||||
continue_getConfigParams(mode, std::move(param_list));
|
||||
});
|
||||
request_mc_block_data_state(blkid);
|
||||
if (!blkid.is_masterchain_ext()) {
|
||||
fatal_error("configuration parameters can be loaded with respect to a masterchain block only");
|
||||
return;
|
||||
}
|
||||
if (!(mode & 0x8000)) {
|
||||
// ordinary case: get configuration from masterchain state
|
||||
set_continuation([this, mode, param_list = std::move(param_list)]() mutable {
|
||||
continue_getConfigParams(mode, std::move(param_list));
|
||||
});
|
||||
request_mc_block_data_state(blkid);
|
||||
} else {
|
||||
// get configuration from previous key block
|
||||
load_prevKeyBlock(blkid, [this, blkid, mode, param_list = std::move(param_list)](
|
||||
td::Result<std::pair<BlockIdExt, Ref<BlockQ>>> res) mutable {
|
||||
if (res.is_error()) {
|
||||
this->abort_query(res.move_as_error());
|
||||
} else {
|
||||
this->base_blk_id_ = res.ok().first;
|
||||
this->mc_block_ = res.move_as_ok().second;
|
||||
this->continue_getConfigParams(mode, std::move(param_list));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LiteQuery::continue_getConfigParams(int mode, std::vector<int> param_list) {
|
||||
LOG(INFO) << "completing getConfigParams(" << base_blk_id_.to_str() << ", " << mode << ", <list of "
|
||||
<< param_list.size() << " parameters>) liteserver query";
|
||||
Ref<vm::Cell> proof1;
|
||||
if (!make_mc_state_root_proof(proof1)) {
|
||||
bool keyblk = (mode & 0x8000);
|
||||
Ref<vm::Cell> proof1, block;
|
||||
if (keyblk) {
|
||||
block = mc_block_->root_cell();
|
||||
} else if (!make_mc_state_root_proof(proof1)) {
|
||||
return;
|
||||
}
|
||||
vm::MerkleProofBuilder mpb{mc_state_->root_cell()};
|
||||
auto res = block::Config::extract_from_state(mpb.root(), mode);
|
||||
|
||||
vm::MerkleProofBuilder mpb{keyblk ? block : mc_state_->root_cell()};
|
||||
if (keyblk) {
|
||||
auto res = block::check_block_header_proof(mpb.root(), base_blk_id_);
|
||||
if (res.is_error()) {
|
||||
fatal_error(res.move_as_error_prefix("invalid key block header:"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto res = keyblk ? block::Config::extract_from_key_block(mpb.root(), mode)
|
||||
: block::Config::extract_from_state(mpb.root(), mode);
|
||||
if (res.is_error()) {
|
||||
fatal_error(res.move_as_error());
|
||||
return;
|
||||
|
@ -1367,9 +1466,9 @@ void LiteQuery::continue_getConfigParams(int mode, std::vector<int> param_list)
|
|||
return;
|
||||
}
|
||||
try {
|
||||
if (mode & 0x2000) {
|
||||
if (mode & 0x20000) {
|
||||
visit(cfg->get_root_cell());
|
||||
} else if (mode & 0x1000) {
|
||||
} else if (mode & 0x10000) {
|
||||
for (int i : param_list) {
|
||||
visit(cfg->get_config_param(i));
|
||||
}
|
||||
|
@ -1378,7 +1477,7 @@ void LiteQuery::continue_getConfigParams(int mode, std::vector<int> param_list)
|
|||
fatal_error("error while traversing required configuration parameters: "s + err.get_msg());
|
||||
return;
|
||||
}
|
||||
auto res1 = vm::std_boc_serialize(std::move(proof1));
|
||||
auto res1 = !keyblk ? vm::std_boc_serialize(std::move(proof1)) : td::BufferSlice();
|
||||
if (res1.is_error()) {
|
||||
fatal_error("cannot serialize Merkle proof : "s + res1.move_as_error().to_string());
|
||||
return;
|
||||
|
@ -1390,7 +1489,7 @@ void LiteQuery::continue_getConfigParams(int mode, std::vector<int> param_list)
|
|||
}
|
||||
LOG(INFO) << "getConfigParams() query completed";
|
||||
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_configInfo>(
|
||||
mode & 0xfff, ton::create_tl_lite_block_id(base_blk_id_), res1.move_as_ok(), res2.move_as_ok());
|
||||
mode & 0xffff, ton::create_tl_lite_block_id(base_blk_id_), res1.move_as_ok(), res2.move_as_ok());
|
||||
finish_query(std::move(b));
|
||||
}
|
||||
|
||||
|
@ -1495,14 +1594,14 @@ 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<ConstBlockHandle> res) {
|
||||
[Self = actor_id(this), manager = manager_, mode = (mode >> 4)](td::Result<ConstBlockHandle> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
auto handle = res.move_as_ok();
|
||||
LOG(DEBUG) << "requesting data for block " << handle->id().to_str();
|
||||
td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db, handle,
|
||||
[ Self, blkid = handle->id(), mode ](td::Result<Ref<BlockData>> res) {
|
||||
[Self, blkid = handle->id(), mode](td::Result<Ref<BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -1650,7 +1749,7 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||
if (mode & 0x1000) {
|
||||
BlockIdExt bblk = (from.seqno() > to.seqno()) ? from : to;
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, bblk,
|
||||
[ Self = actor_id(this), from, to, bblk, mode ](td::Result<Ref<ShardState>> res) {
|
||||
[Self = actor_id(this), from, to, bblk, mode](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
|
@ -1662,7 +1761,7 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||
} else {
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[ Self = actor_id(this), from, to, mode ](td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res) {
|
||||
[Self = actor_id(this), from, to, 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 {
|
||||
|
@ -1675,7 +1774,7 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||
} 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) {
|
||||
[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 {
|
||||
|
@ -1686,7 +1785,7 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||
});
|
||||
} else {
|
||||
td::actor::send_closure_later(manager_, &ton::validator::ValidatorManager::get_shard_client_state, false,
|
||||
[ Self = actor_id(this), from, mode ](td::Result<BlockIdExt> res) {
|
||||
[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 {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "interfaces/block-handle.h"
|
||||
#include "interfaces/validator-manager.h"
|
||||
#include "interfaces/shard.h"
|
||||
#include "block.hpp"
|
||||
#include "shard.hpp"
|
||||
#include "proof.hpp"
|
||||
|
||||
|
@ -45,7 +46,7 @@ class LiteQuery : public td::actor::Actor {
|
|||
BlockIdExt base_blk_id_, base_blk_id_alt_, blk_id_;
|
||||
Ref<MasterchainStateQ> mc_state_, mc_state0_;
|
||||
Ref<ShardStateQ> state_;
|
||||
Ref<BlockData> mc_block_, block_;
|
||||
Ref<BlockQ> mc_block_, block_;
|
||||
Ref<ProofQ> mc_proof_, mc_proof_alt_;
|
||||
Ref<ProofLinkQ> proof_link_;
|
||||
td::BufferSlice buffer_;
|
||||
|
@ -131,6 +132,12 @@ class LiteQuery : public td::actor::Actor {
|
|||
bool adjust_last_proof_link(ton::BlockIdExt cur, Ref<vm::Cell> block_root);
|
||||
bool finish_proof_chain(ton::BlockIdExt id);
|
||||
|
||||
void load_prevKeyBlock(ton::BlockIdExt blkid, td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>>);
|
||||
void continue_loadPrevKeyBlock(ton::BlockIdExt blkid, td::Result<std::pair<Ref<MasterchainState>, BlockIdExt>> res,
|
||||
td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>>);
|
||||
void finish_loadPrevKeyBlock(ton::BlockIdExt blkid, td::Result<Ref<BlockData>> res,
|
||||
td::Promise<std::pair<BlockIdExt, Ref<BlockQ>>> promise);
|
||||
|
||||
bool request_block_data(BlockIdExt blkid);
|
||||
bool request_block_state(BlockIdExt blkid);
|
||||
bool request_block_data_state(BlockIdExt blkid);
|
||||
|
|
|
@ -4822,14 +4822,15 @@ bool ValidateQuery::check_new_state() {
|
|||
// seq_no:uint32 vert_seq_no:# -> checked in unpack_next_state()
|
||||
// gen_utime:uint32 gen_lt:uint64 -> checked in unpack_next_state()
|
||||
// min_ref_mc_seqno:uint32
|
||||
ton::BlockSeqno ref_mc_seqno = std::min(std::min(is_masterchain() ? id_.seqno() : mc_seqno_, min_shard_ref_mc_seqno_),
|
||||
ns_.processed_upto_->min_mc_seqno());
|
||||
ton::BlockSeqno my_mc_seqno = is_masterchain() ? id_.seqno() : mc_seqno_;
|
||||
ton::BlockSeqno ref_mc_seqno =
|
||||
std::min(std::min(my_mc_seqno, min_shard_ref_mc_seqno_), ns_.processed_upto_->min_mc_seqno());
|
||||
if (ns_.min_ref_mc_seqno_ != ref_mc_seqno) {
|
||||
return reject_query(
|
||||
PSTRING() << "new state of " << id_.to_str() << " has minimal referenced masterchain block seqno "
|
||||
<< ns_.min_ref_mc_seqno_
|
||||
<< " but the value computed from all shard references and previous masterchain block reference is "
|
||||
<< ref_mc_seqno << " = min(" << mc_seqno_ << "," << min_shard_ref_mc_seqno_ << ","
|
||||
<< ref_mc_seqno << " = min(" << my_mc_seqno << "," << min_shard_ref_mc_seqno_ << ","
|
||||
<< ns_.processed_upto_->min_mc_seqno() << ")");
|
||||
}
|
||||
// out_msg_queue_info:^OutMsgQueueInfo
|
||||
|
|
|
@ -201,7 +201,7 @@ void ArchiveImporter::checked_masterchain_proof(BlockHandle handle, td::Ref<Bloc
|
|||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::applied_masterchain_block, std::move(handle));
|
||||
});
|
||||
run_apply_block_query(handle->id(), std::move(data), handle->id(), manager_, td::Timestamp::in(10.0), std::move(P));
|
||||
run_apply_block_query(handle->id(), std::move(data), handle->id(), manager_, td::Timestamp::in(600.0), std::move(P));
|
||||
}
|
||||
|
||||
void ArchiveImporter::applied_masterchain_block(BlockHandle handle) {
|
||||
|
@ -353,7 +353,7 @@ void ArchiveImporter::apply_shard_block_cont3(BlockHandle handle, BlockIdExt mas
|
|||
}
|
||||
TRY_RESULT_PROMISE(promise, block, create_block(handle->id(), std::move(data.second)));
|
||||
|
||||
run_apply_block_query(handle->id(), std::move(block), masterchain_block_id, manager_, td::Timestamp::in(10.0),
|
||||
run_apply_block_query(handle->id(), std::move(block), masterchain_block_id, manager_, td::Timestamp::in(600.0),
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ class Db : public td::actor::Actor {
|
|||
|
||||
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;
|
||||
virtual void truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void add_key_block_proof(td::Ref<Proof> proof, td::Promise<td::Unit> promise) = 0;
|
||||
virtual void add_key_block_proof_link(td::Ref<ProofLink> proof_link, td::Promise<td::Unit> promise) = 0;
|
||||
|
@ -115,7 +115,7 @@ class Db : public td::actor::Actor {
|
|||
td::Promise<td::BufferSlice> promise) = 0;
|
||||
virtual void set_async_mode(bool mode, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void run_gc(UnixTime ts) = 0;
|
||||
virtual void run_gc(UnixTime ts, UnixTime archive_ttl) = 0;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -157,7 +157,7 @@ class ValidatorManager : public ValidatorManagerInterface {
|
|||
|
||||
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 truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
virtual void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) = 0;
|
||||
|
||||
|
|
|
@ -882,7 +882,7 @@ void ValidatorManagerImpl::send_top_shard_block_description(td::Ref<ShardTopBloc
|
|||
}
|
||||
|
||||
void ValidatorManagerImpl::start_up() {
|
||||
db_ = create_db_actor(actor_id(this), db_root_, opts_->get_filedb_depth());
|
||||
db_ = create_db_actor(actor_id(this), db_root_);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<ValidatorManagerInitResult> R) {
|
||||
R.ensure();
|
||||
|
|
|
@ -351,7 +351,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) override {
|
||||
void truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override {
|
||||
|
|
563
validator/manager-hardfork.cpp
Normal file
563
validator/manager-hardfork.cpp
Normal file
|
@ -0,0 +1,563 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "manager-hardfork.hpp"
|
||||
#include "validator-group.hpp"
|
||||
#include "adnl/utils.hpp"
|
||||
#include "downloaders/wait-block-state.hpp"
|
||||
#include "downloaders/wait-block-state-merge.hpp"
|
||||
#include "downloaders/wait-block-data-disk.hpp"
|
||||
#include "validator-group.hpp"
|
||||
#include "fabric.h"
|
||||
#include "manager.h"
|
||||
#include "ton/ton-io.hpp"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/utils/filesystem.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace validator {
|
||||
|
||||
void ValidatorManagerImpl::sync_complete(td::Promise<td::Unit> promise) {
|
||||
started_ = true;
|
||||
|
||||
//ShardIdFull shard_id{masterchainId, shardIdAll};
|
||||
auto shard_id = shard_to_generate_;
|
||||
|
||||
auto block_id = block_to_generate_;
|
||||
|
||||
std::vector<BlockIdExt> prev{block_id};
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockCandidate> R) {
|
||||
if (R.is_ok()) {
|
||||
auto v = R.move_as_ok();
|
||||
LOG(ERROR) << "created block " << v.id;
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::created_candidate, std::move(v));
|
||||
} else {
|
||||
LOG(ERROR) << "failed to create block: " << R.move_as_error();
|
||||
std::exit(2);
|
||||
}
|
||||
});
|
||||
|
||||
LOG(ERROR) << "running collate query";
|
||||
run_collate_hardfork(shard_id, block_id, prev, actor_id(this), td::Timestamp::in(10.0), std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::created_candidate(BlockCandidate candidate) {
|
||||
td::write_file(db_root_ + "/static/" + candidate.id.file_hash.to_hex(), candidate.data.as_slice()).ensure();
|
||||
LOG(ERROR) << "success, block " << candidate.id << " = " << candidate.id.to_str() << " saved to disk";
|
||||
std::cout << candidate.id.to_str() << std::endl << std::flush;
|
||||
std::_Exit(0);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_data(BlockHandle handle, td::Promise<td::BufferSlice> promise) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<BlockData>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto B = R.move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
get_block_data_from_db(handle, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_proof(BlockHandle handle, td::Promise<td::BufferSlice> promise) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto B = R.move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db_, &Db::get_block_proof, handle, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_proof_link(BlockHandle handle, td::Promise<td::BufferSlice> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise), handle, db = db_.get()](td::Result<td::Ref<ProofLink>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto B = R.move_as_ok()->export_as_proof_link().move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db, &Db::get_block_proof, handle, std::move(P));
|
||||
} else {
|
||||
auto B = R.move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db_, &Db::get_block_proof_link, handle, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_key_block_proof(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto B = R.move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db_, &Db::get_key_block_proof, block_id, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_key_block_proof_link(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise), block_id, db = db_.get()](td::Result<td::Ref<ProofLink>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto B = R.move_as_ok()->export_as_proof_link().move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db, &Db::get_key_block_proof, block_id, std::move(P));
|
||||
} else {
|
||||
auto B = R.move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db_, &Db::get_key_block_proof_link, block_id, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::new_external_message(td::BufferSlice data) {
|
||||
auto R = create_ext_message(std::move(data));
|
||||
if (R.is_ok()) {
|
||||
ext_messages_.emplace_back(R.move_as_ok());
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::new_ihr_message(td::BufferSlice data) {
|
||||
auto R = create_ihr_message(std::move(data));
|
||||
if (R.is_ok()) {
|
||||
ihr_messages_.emplace_back(R.move_as_ok());
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) {
|
||||
auto it = wait_state_.find(handle->id());
|
||||
if (it == wait_state_.end()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::finished_wait_state, handle->id(), std::move(R));
|
||||
});
|
||||
auto id = td::actor::create_actor<WaitBlockState>("waitstate", handle, 0, actor_id(this), td::Timestamp::in(10.0),
|
||||
std::move(P))
|
||||
.release();
|
||||
wait_state_[handle->id()].actor_ = id;
|
||||
it = wait_state_.find(handle->id());
|
||||
}
|
||||
|
||||
it->second.waiting_.emplace_back(
|
||||
std::pair<td::Timestamp, td::Promise<td::Ref<ShardState>>>(timeout, std::move(promise)));
|
||||
td::actor::send_closure(it->second.actor_, &WaitBlockState::update_timeout, timeout, 0);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_state_short(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_state, R.move_as_ok(), 0, timeout,
|
||||
std::move(promise));
|
||||
});
|
||||
get_block_handle(block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_data(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<BlockData>> promise) {
|
||||
auto it = wait_block_data_.find(handle->id());
|
||||
if (it == wait_block_data_.end()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<BlockData>> R) {
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::finished_wait_data, handle->id(), std::move(R));
|
||||
});
|
||||
auto id = td::actor::create_actor<WaitBlockDataDisk>("waitdata", handle, actor_id(this), td::Timestamp::in(10.0),
|
||||
std::move(P))
|
||||
.release();
|
||||
wait_block_data_[handle->id()].actor_ = id;
|
||||
it = wait_block_data_.find(handle->id());
|
||||
}
|
||||
|
||||
it->second.waiting_.emplace_back(
|
||||
std::pair<td::Timestamp, td::Promise<td::Ref<BlockData>>>(timeout, std::move(promise)));
|
||||
td::actor::send_closure(it->second.actor_, &WaitBlockDataDisk::update_timeout, timeout);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_data_short(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<BlockData>> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_data, R.move_as_ok(), 0, timeout,
|
||||
std::move(promise));
|
||||
});
|
||||
get_block_handle(block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority,
|
||||
td::Timestamp timeout, td::Promise<td::Ref<ShardState>> promise) {
|
||||
td::actor::create_actor<WaitBlockStateMerge>("merge", left_id, right_id, 0, actor_id(this), timeout,
|
||||
std::move(promise))
|
||||
.release();
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_prev_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) {
|
||||
CHECK(handle);
|
||||
CHECK(!handle->is_zero());
|
||||
if (!handle->merge_before()) {
|
||||
auto shard = handle->id().shard_full();
|
||||
auto prev_shard = handle->one_prev(true).shard_full();
|
||||
if (shard == prev_shard) {
|
||||
wait_block_state_short(handle->one_prev(true), 0, timeout, std::move(promise));
|
||||
} else {
|
||||
CHECK(shard_parent(shard) == prev_shard);
|
||||
bool left = shard_child(prev_shard, true) == shard;
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([promise = std::move(promise), left](td::Result<td::Ref<ShardState>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto s = R.move_as_ok();
|
||||
auto r = s->split();
|
||||
if (r.is_error()) {
|
||||
promise.set_error(r.move_as_error());
|
||||
} else {
|
||||
auto v = r.move_as_ok();
|
||||
promise.set_value(left ? std::move(v.first) : std::move(v.second));
|
||||
}
|
||||
}
|
||||
});
|
||||
wait_block_state_short(handle->one_prev(true), 0, timeout, std::move(P));
|
||||
}
|
||||
} else {
|
||||
wait_block_state_merge(handle->one_prev(true), handle->one_prev(false), 0, timeout, std::move(promise));
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_proof(BlockHandle handle, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<Proof>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_proof, handle, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_proof_short(BlockIdExt block_id, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<Proof>> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_proof, R.move_as_ok(), timeout,
|
||||
std::move(promise));
|
||||
});
|
||||
get_block_handle(block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_proof_link(BlockHandle handle, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ProofLink>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_proof_link, std::move(handle), std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_proof_link_short(BlockIdExt block_id, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ProofLink>> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_proof_link, R.move_as_ok(), timeout,
|
||||
std::move(promise));
|
||||
});
|
||||
get_block_handle(block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_signatures(BlockHandle handle, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<BlockSignatureSet>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_signatures, handle, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_signatures_short(BlockIdExt block_id, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<BlockSignatureSet>> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_signatures, R.move_as_ok(), timeout,
|
||||
std::move(promise));
|
||||
});
|
||||
get_block_handle(block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_message_queue(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<MessageQueue>> promise) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<ShardState>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto state = R.move_as_ok();
|
||||
promise.set_result(state->message_queue());
|
||||
}
|
||||
});
|
||||
|
||||
wait_block_state(handle, 0, timeout, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_block_message_queue_short(BlockIdExt block_id, td::uint32 priority,
|
||||
td::Timestamp timeout,
|
||||
td::Promise<td::Ref<MessageQueue>> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), timeout, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::wait_block_message_queue, R.move_as_ok(), 0, timeout,
|
||||
std::move(promise));
|
||||
});
|
||||
get_block_handle(block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_external_messages(ShardIdFull shard,
|
||||
td::Promise<std::vector<td::Ref<ExtMessage>>> promise) {
|
||||
promise.set_result(ext_messages_);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_ihr_messages(ShardIdFull shard, td::Promise<std::vector<td::Ref<IhrMessage>>> promise) {
|
||||
promise.set_result(ihr_messages_);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_shard_blocks(BlockIdExt masterchain_block_id,
|
||||
td::Promise<std::vector<td::Ref<ShardTopBlockDescription>>> promise) {
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_data_from_db(ConstBlockHandle handle, td::Promise<td::Ref<BlockData>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_data, handle, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_data_from_db_short(BlockIdExt block_id, td::Promise<td::Ref<BlockData>> promise) {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto handle = R.move_as_ok();
|
||||
td::actor::send_closure(db, &Db::get_block_data, std::move(handle), std::move(promise));
|
||||
}
|
||||
});
|
||||
get_block_handle(block_id, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_shard_state_from_db(ConstBlockHandle handle, td::Promise<td::Ref<ShardState>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_state, handle, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_shard_state_from_db_short(BlockIdExt block_id,
|
||||
td::Promise<td::Ref<ShardState>> promise) {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto handle = R.move_as_ok();
|
||||
td::actor::send_closure(db, &Db::get_block_state, std::move(handle), std::move(promise));
|
||||
}
|
||||
});
|
||||
get_block_handle(block_id, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_candidate_from_db(PublicKey source, BlockIdExt id,
|
||||
FileHash collated_data_file_hash,
|
||||
td::Promise<BlockCandidate> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_candidate, source, id, collated_data_file_hash, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_proof_from_db(ConstBlockHandle handle, td::Promise<td::Ref<Proof>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_proof, std::move(handle), std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_proof_from_db_short(BlockIdExt block_id, td::Promise<td::Ref<Proof>> promise) {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto handle = R.move_as_ok();
|
||||
td::actor::send_closure(db, &Db::get_block_proof, std::move(handle), std::move(promise));
|
||||
}
|
||||
});
|
||||
get_block_handle(block_id, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_proof_link_from_db(ConstBlockHandle handle,
|
||||
td::Promise<td::Ref<ProofLink>> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_proof_link, std::move(handle), std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_proof_link_from_db_short(BlockIdExt block_id,
|
||||
td::Promise<td::Ref<ProofLink>> promise) {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto handle = R.move_as_ok();
|
||||
td::actor::send_closure(db, &Db::get_block_proof_link, std::move(handle), std::move(promise));
|
||||
}
|
||||
});
|
||||
get_block_handle(block_id, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_by_lt_from_db(AccountIdPrefixFull account, LogicalTime lt,
|
||||
td::Promise<ConstBlockHandle> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_by_lt, account, lt, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_by_unix_time_from_db(AccountIdPrefixFull account, UnixTime ts,
|
||||
td::Promise<ConstBlockHandle> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_by_unix_time, account, ts, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_by_seqno_from_db(AccountIdPrefixFull account, BlockSeqno seqno,
|
||||
td::Promise<ConstBlockHandle> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_block_by_seqno, account, seqno, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::finished_wait_state(BlockIdExt block_id, td::Result<td::Ref<ShardState>> R) {
|
||||
auto it = wait_state_.find(block_id);
|
||||
if (it != wait_state_.end()) {
|
||||
if (R.is_error()) {
|
||||
auto S = R.move_as_error();
|
||||
for (auto &X : it->second.waiting_) {
|
||||
X.second.set_error(S.clone());
|
||||
}
|
||||
} else {
|
||||
auto r = R.move_as_ok();
|
||||
for (auto &X : it->second.waiting_) {
|
||||
X.second.set_result(r);
|
||||
}
|
||||
}
|
||||
wait_state_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::finished_wait_data(BlockIdExt block_id, td::Result<td::Ref<BlockData>> R) {
|
||||
auto it = wait_block_data_.find(block_id);
|
||||
if (it != wait_block_data_.end()) {
|
||||
if (R.is_error()) {
|
||||
auto S = R.move_as_error();
|
||||
for (auto &X : it->second.waiting_) {
|
||||
X.second.set_error(S.clone());
|
||||
}
|
||||
} else {
|
||||
auto r = R.move_as_ok();
|
||||
for (auto &X : it->second.waiting_) {
|
||||
X.second.set_result(r);
|
||||
}
|
||||
}
|
||||
wait_block_data_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_block_handle(BlockIdExt id, bool force, td::Promise<BlockHandle> promise) {
|
||||
auto it = handles_.find(id);
|
||||
if (it != handles_.end()) {
|
||||
auto handle = it->second.lock();
|
||||
if (handle) {
|
||||
promise.set_value(std::move(handle));
|
||||
return;
|
||||
} else {
|
||||
handles_.erase(it);
|
||||
}
|
||||
}
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[id, force, promise = std::move(promise), SelfId = actor_id(this)](td::Result<BlockHandle> R) mutable {
|
||||
BlockHandle handle;
|
||||
if (R.is_error()) {
|
||||
auto S = R.move_as_error();
|
||||
if (S.code() == ErrorCode::notready && force) {
|
||||
handle = create_empty_block_handle(id);
|
||||
} else {
|
||||
promise.set_error(std::move(S));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
handle = R.move_as_ok();
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::register_block_handle, std::move(handle),
|
||||
std::move(promise));
|
||||
});
|
||||
|
||||
td::actor::send_closure(db_, &Db::get_block_handle, id, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::register_block_handle(BlockHandle handle, td::Promise<BlockHandle> promise) {
|
||||
auto it = handles_.find(handle->id());
|
||||
if (it != handles_.end()) {
|
||||
auto h = it->second.lock();
|
||||
if (h) {
|
||||
promise.set_value(std::move(h));
|
||||
return;
|
||||
}
|
||||
handles_.erase(it);
|
||||
}
|
||||
handles_.emplace(handle->id(), std::weak_ptr<BlockHandleInterface>(handle));
|
||||
promise.set_value(std::move(handle));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::start_up() {
|
||||
db_ = create_db_actor(actor_id(this), db_root_);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::try_get_static_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) {
|
||||
td::actor::send_closure(db_, &Db::try_get_static_file, file_hash, std::move(promise));
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<ValidatorManagerInterface> ValidatorManagerHardforkFactory::create(
|
||||
td::Ref<ValidatorManagerOptions> opts, ShardIdFull shard, BlockIdExt shard_top_block_id, std::string db_root) {
|
||||
return td::actor::create_actor<validator::ValidatorManagerImpl>("manager", std::move(opts), shard_top_block_id,
|
||||
db_root);
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
35
validator/manager-hardfork.h
Normal file
35
validator/manager-hardfork.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "validator/validator.h"
|
||||
#include "adnl/adnl.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace validator {
|
||||
|
||||
class ValidatorManagerHardforkFactory {
|
||||
public:
|
||||
static td::actor::ActorOwn<ValidatorManagerInterface> create(td::Ref<ValidatorManagerOptions> opts, ShardIdFull shard,
|
||||
BlockIdExt shard_top_block_id, std::string db_root);
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
429
validator/manager-hardfork.hpp
Normal file
429
validator/manager-hardfork.hpp
Normal file
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "interfaces/validator-manager.h"
|
||||
#include "interfaces/db.h"
|
||||
#include "validator-group.hpp"
|
||||
#include "manager-init.h"
|
||||
#include "manager-hardfork.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace validator {
|
||||
|
||||
class WaitBlockState;
|
||||
class WaitZeroState;
|
||||
class WaitShardState;
|
||||
class WaitBlockDataDisk;
|
||||
|
||||
class ValidatorManagerImpl : public ValidatorManager {
|
||||
private:
|
||||
std::vector<td::Ref<ExtMessage>> ext_messages_;
|
||||
std::vector<td::Ref<IhrMessage>> ihr_messages_;
|
||||
struct Compare {
|
||||
bool operator()(const td::Ref<ShardTopBlockDescription> &l, const td::Ref<ShardTopBlockDescription> &r) const {
|
||||
return l->block_id() < r->block_id();
|
||||
}
|
||||
};
|
||||
std::set<td::Ref<ShardTopBlockDescription>, Compare> shard_blocks_, out_shard_blocks_;
|
||||
std::vector<td::BufferSlice> shard_blocks_raw_;
|
||||
|
||||
struct WaitBlockStateList {
|
||||
std::vector<std::pair<td::Timestamp, td::Promise<td::Ref<ShardState>>>> waiting_;
|
||||
td::actor::ActorId<WaitBlockState> actor_;
|
||||
};
|
||||
std::map<BlockIdExt, WaitBlockStateList> wait_state_;
|
||||
struct WaitBlockDataList {
|
||||
std::vector<std::pair<td::Timestamp, td::Promise<td::Ref<BlockData>>>> waiting_;
|
||||
td::actor::ActorId<WaitBlockDataDisk> actor_;
|
||||
};
|
||||
std::map<BlockIdExt, WaitBlockDataList> wait_block_data_;
|
||||
|
||||
std::map<BlockIdExt, std::weak_ptr<BlockHandleInterface>> handles_;
|
||||
|
||||
std::unique_ptr<Callback> callback_;
|
||||
td::actor::ActorOwn<Db> db_;
|
||||
BlockSeqno last_masterchain_seqno_ = 0;
|
||||
bool started_ = false;
|
||||
td::Ref<MasterchainState> last_masterchain_state_;
|
||||
//BlockHandle last_masterchain_block_;
|
||||
|
||||
public:
|
||||
void install_callback(std::unique_ptr<Callback> new_callback, td::Promise<td::Unit> promise) override {
|
||||
callback_ = std::move(new_callback);
|
||||
promise.set_value(td::Unit());
|
||||
|
||||
callback_->initial_read_complete(nullptr);
|
||||
}
|
||||
void add_permanent_key(PublicKeyHash key, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void add_temp_key(PublicKeyHash key, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void del_permanent_key(PublicKeyHash key, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void del_temp_key(PublicKeyHash key, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void validate_block_is_next_proof(BlockIdExt prev_block_id, BlockIdExt next_block_id, td::BufferSlice proof,
|
||||
td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void validate_block_proof(BlockIdExt block_id, td::BufferSlice proof, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void validate_block_proof_link(BlockIdExt block_id, td::BufferSlice proof, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void validate_block_proof_rel(BlockIdExt block_id, BlockIdExt rel_block_id, td::BufferSlice proof,
|
||||
td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void validate_block(ReceivedBlock block, td::Promise<BlockHandle> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void prevalidate_block(BlockBroadcast broadcast, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
//void create_validate_block(BlockId block, td::BufferSlice data, td::Promise<Block> promise) = 0;
|
||||
void sync_complete(td::Promise<td::Unit> promise) override;
|
||||
void created_candidate(BlockCandidate candidate);
|
||||
|
||||
void get_next_block(BlockIdExt block_id, td::Promise<BlockHandle> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_next_key_blocks(BlockIdExt block_id, td::uint32 cnt, td::Promise<std::vector<BlockIdExt>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_block_data(BlockHandle handle, td::Promise<td::BufferSlice> promise) override;
|
||||
void get_zero_state(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void check_zero_state_exists(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void check_persistent_state_exists(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::Promise<bool> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_persistent_state(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_persistent_state_slice(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::int64 offset,
|
||||
td::int64 max_length, td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_block_proof(BlockHandle handle, td::Promise<td::BufferSlice> promise) override;
|
||||
void get_block_proof_link(BlockHandle block_id, td::Promise<td::BufferSlice> promise) override;
|
||||
void get_key_block_proof(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) override;
|
||||
void get_key_block_proof_link(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) override;
|
||||
|
||||
void new_external_message(td::BufferSlice data) override;
|
||||
void new_ihr_message(td::BufferSlice data) override;
|
||||
void new_shard_block(BlockIdExt block_id, CatchainSeqno cc_seqno, td::BufferSlice data) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void add_ext_server_id(adnl::AdnlNodeIdShort id) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void add_ext_server_port(td::uint16 port) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void get_block_handle(BlockIdExt id, bool force, td::Promise<BlockHandle> promise) override;
|
||||
|
||||
void set_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::BufferSlice state,
|
||||
td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void store_zero_state_file(BlockIdExt block_id, td::BufferSlice state, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void wait_block_state_short(BlockIdExt block_id, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
|
||||
void set_block_data(BlockHandle handle, td::Ref<BlockData> data, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_block_data(BlockHandle handle, td::uint32 priority, td::Timestamp,
|
||||
td::Promise<td::Ref<BlockData>> promise) override;
|
||||
void wait_block_data_short(BlockIdExt block_id, td::uint32 priority, td::Timestamp,
|
||||
td::Promise<td::Ref<BlockData>> promise) override;
|
||||
|
||||
void set_block_proof(BlockHandle handle, td::Ref<Proof> proof, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_block_proof(BlockHandle handle, td::Timestamp timeout, td::Promise<td::Ref<Proof>> promise) override;
|
||||
void wait_block_proof_short(BlockIdExt id, td::Timestamp timeout, td::Promise<td::Ref<Proof>> promise) override;
|
||||
|
||||
void set_block_proof_link(BlockHandle handle, td::Ref<ProofLink> proof, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_block_proof_link(BlockHandle handle, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ProofLink>> promise) override;
|
||||
void wait_block_proof_link_short(BlockIdExt id, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ProofLink>> promise) override;
|
||||
|
||||
void set_block_signatures(BlockHandle handle, td::Ref<BlockSignatureSet> signatures,
|
||||
td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void wait_block_signatures(BlockHandle handle, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<BlockSignatureSet>> promise) override;
|
||||
void wait_block_signatures_short(BlockIdExt id, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<BlockSignatureSet>> promise) override;
|
||||
|
||||
void set_block_candidate(BlockIdExt id, BlockCandidate candidate, td::Promise<td::Unit> promise) override {
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
void wait_block_state_merge(BlockIdExt left_id, BlockIdExt right_id, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void wait_prev_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<ShardState>> promise) override;
|
||||
|
||||
void wait_block_message_queue(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<MessageQueue>> promise) override;
|
||||
void wait_block_message_queue_short(BlockIdExt id, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<td::Ref<MessageQueue>> promise) override;
|
||||
void get_external_messages(ShardIdFull shard, td::Promise<std::vector<td::Ref<ExtMessage>>> promise) override;
|
||||
void get_ihr_messages(ShardIdFull shard, td::Promise<std::vector<td::Ref<IhrMessage>>> promise) override;
|
||||
void get_shard_blocks(BlockIdExt masterchain_block_id,
|
||||
td::Promise<std::vector<td::Ref<ShardTopBlockDescription>>> promise) override;
|
||||
void complete_external_messages(std::vector<ExtMessage::Hash> to_delay,
|
||||
std::vector<ExtMessage::Hash> to_delete) override {
|
||||
}
|
||||
void complete_ihr_messages(std::vector<IhrMessage::Hash> to_delay, std::vector<IhrMessage::Hash> to_delete) override {
|
||||
}
|
||||
|
||||
//void set_first_block(ZeroStateIdExt state, BlockIdExt block, td::Promise<td::Unit> promise) override;
|
||||
void set_next_block(BlockIdExt prev, BlockIdExt next, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void get_block_data_from_db(ConstBlockHandle handle, td::Promise<td::Ref<BlockData>> promise) override;
|
||||
void get_block_data_from_db_short(BlockIdExt block_id, td::Promise<td::Ref<BlockData>> promise) override;
|
||||
void get_shard_state_from_db(ConstBlockHandle handle, td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void get_shard_state_from_db_short(BlockIdExt block_id, td::Promise<td::Ref<ShardState>> promise) override;
|
||||
void get_block_candidate_from_db(PublicKey source, BlockIdExt id, FileHash collated_data_file_hash,
|
||||
td::Promise<BlockCandidate> promise) override;
|
||||
void get_block_proof_from_db(ConstBlockHandle handle, td::Promise<td::Ref<Proof>> promise) override;
|
||||
void get_block_proof_from_db_short(BlockIdExt id, td::Promise<td::Ref<Proof>> promise) override;
|
||||
void get_block_proof_link_from_db(ConstBlockHandle handle, td::Promise<td::Ref<ProofLink>> promise) override;
|
||||
void get_block_proof_link_from_db_short(BlockIdExt id, td::Promise<td::Ref<ProofLink>> promise) override;
|
||||
|
||||
void get_block_by_lt_from_db(AccountIdPrefixFull account, LogicalTime lt,
|
||||
td::Promise<ConstBlockHandle> promise) override;
|
||||
void get_block_by_unix_time_from_db(AccountIdPrefixFull account, UnixTime ts,
|
||||
td::Promise<ConstBlockHandle> promise) override;
|
||||
void get_block_by_seqno_from_db(AccountIdPrefixFull account, BlockSeqno seqno,
|
||||
td::Promise<ConstBlockHandle> promise) override;
|
||||
|
||||
// get block handle declared in parent class
|
||||
void write_handle(BlockHandle handle, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void new_block(BlockHandle handle, td::Ref<ShardState> state, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void new_block_cont(BlockHandle handle, td::Ref<ShardState> state, td::Promise<td::Unit> promise) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_top_masterchain_state(td::Promise<td::Ref<MasterchainState>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_top_masterchain_block(td::Promise<BlockIdExt> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_top_masterchain_state_block(td::Promise<std::pair<td::Ref<MasterchainState>, BlockIdExt>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void send_get_block_request(BlockIdExt id, td::uint32 priority, td::Promise<ReceivedBlock> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_get_zero_state_request(BlockIdExt id, td::uint32 priority, td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_get_persistent_state_request(BlockIdExt id, BlockIdExt masterchain_block_id, td::uint32 priority,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_get_block_proof_request(BlockIdExt block_id, td::uint32 priority,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_get_block_proof_link_request(BlockIdExt block_id, td::uint32 priority,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_get_next_key_blocks_request(BlockIdExt block_id, td::uint32 priority,
|
||||
td::Promise<std::vector<BlockIdExt>> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_external_message(td::Ref<ExtMessage> message) override {
|
||||
new_external_message(message->serialize());
|
||||
}
|
||||
void send_ihr_message(td::Ref<IhrMessage> message) override {
|
||||
new_ihr_message(message->serialize());
|
||||
}
|
||||
void send_top_shard_block_description(td::Ref<ShardTopBlockDescription> desc) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void send_block_broadcast(BlockBroadcast broadcast) override {
|
||||
}
|
||||
|
||||
void update_shard_client_state(BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_shard_client_state(bool from_db, td::Promise<BlockIdExt> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void subscribe_to_shard(ShardIdFull shard) override {
|
||||
}
|
||||
|
||||
void update_async_serializer_state(AsyncSerializerState state, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_async_serializer_state(td::Promise<AsyncSerializerState> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void try_get_static_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) override;
|
||||
|
||||
void get_download_token(size_t download_size, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<std::unique_ptr<DownloadToken>> promise) override {
|
||||
promise.set_error(td::Status::Error(ErrorCode::error, "download disabled"));
|
||||
}
|
||||
|
||||
void get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
void get_archive_slice(td::uint64 archive_id, td::uint64 offset, td::uint32 limit,
|
||||
td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void add_shard_block_description(td::Ref<ShardTopBlockDescription> desc);
|
||||
|
||||
void register_block_handle(BlockHandle handle, td::Promise<BlockHandle> promise);
|
||||
|
||||
void finished_wait_state(BlockIdExt id, td::Result<td::Ref<ShardState>> R);
|
||||
void finished_wait_data(BlockIdExt id, td::Result<td::Ref<BlockData>> R);
|
||||
|
||||
void start_up() override;
|
||||
|
||||
void check_is_hardfork(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
CHECK(block_id.is_masterchain());
|
||||
promise.set_result(opts_->is_hardfork(block_id));
|
||||
}
|
||||
void get_vertical_seqno(BlockSeqno seqno, td::Promise<td::uint32> promise) override {
|
||||
promise.set_result(opts_->get_vertical_seqno(seqno));
|
||||
}
|
||||
void run_ext_query(td::BufferSlice data, td::Promise<td::BufferSlice> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
ValidatorManagerImpl(td::Ref<ValidatorManagerOptions> opts, BlockIdExt shard_to_block_id, std::string db_root)
|
||||
: opts_(std::move(opts))
|
||||
, db_root_(db_root)
|
||||
, shard_to_generate_(shard_to_block_id.shard_full())
|
||||
, block_to_generate_(shard_to_block_id) {
|
||||
}
|
||||
|
||||
public:
|
||||
void update_gc_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override {
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
void allow_block_data_gc(BlockIdExt block_id, bool is_archive, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_block_state_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_zero_state_file_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_persistent_state_file_gc(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_block_signatures_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_block_proof_gc(BlockIdExt block_id, bool is_archive, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_block_proof_link_gc(BlockIdExt block_id, bool is_archive, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_block_candidate_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void allow_block_info_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
promise.set_result(false);
|
||||
}
|
||||
void archive(BlockHandle handle, td::Promise<td::Unit> promise) override {
|
||||
UNREACHABLE();
|
||||
}
|
||||
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(BlockSeqno seqno, ConstBlockHandle handle, 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:
|
||||
td::Ref<ValidatorManagerOptions> opts_;
|
||||
|
||||
private:
|
||||
std::string db_root_;
|
||||
ShardIdFull shard_to_generate_;
|
||||
BlockIdExt block_to_generate_;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
|
@ -320,6 +320,25 @@ void ValidatorManagerMasterchainStarter::got_init_block_id(BlockIdExt block_id)
|
|||
|
||||
void ValidatorManagerMasterchainStarter::got_init_block_handle(BlockHandle handle) {
|
||||
handle_ = std::move(handle);
|
||||
if (!handle_->received_state()) {
|
||||
LOG(ERROR) << "db inconsistent: last state ( " << handle_->id() << " ) not received";
|
||||
td::actor::send_closure(manager_, &ValidatorManager::wait_block_state, handle_, 1, td::Timestamp::in(600.0),
|
||||
[SelfId = actor_id(this), handle = handle_](td::Result<td::Ref<ShardState>> R) {
|
||||
td::actor::send_closure(
|
||||
SelfId, &ValidatorManagerMasterchainStarter::got_init_block_handle, handle);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!handle_->is_applied()) {
|
||||
CHECK(handle_->inited_prev());
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, handle_->one_prev(true), false,
|
||||
[SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(
|
||||
SelfId, &ValidatorManagerMasterchainStarter::got_init_block_handle, R.move_as_ok());
|
||||
});
|
||||
return;
|
||||
}
|
||||
LOG_CHECK(handle_->received_state()) << "block_id=" << handle_->id();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
|
@ -401,7 +420,7 @@ void ValidatorManagerMasterchainStarter::got_gc_block_state(td::Ref<MasterchainS
|
|||
|
||||
void ValidatorManagerMasterchainStarter::got_key_block_handle(BlockHandle handle) {
|
||||
CHECK(handle);
|
||||
CHECK(handle->id().id.seqno == 0 || handle->is_key_block());
|
||||
//CHECK(handle->id().id.seqno == 0 || handle->is_key_block());
|
||||
last_key_block_handle_ = std::move(handle);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockIdExt> R) {
|
||||
|
@ -413,10 +432,6 @@ void ValidatorManagerMasterchainStarter::got_key_block_handle(BlockHandle handle
|
|||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_shard_block_id(BlockIdExt block_id) {
|
||||
client_block_id_ = block_id;
|
||||
start_shard_client();
|
||||
return;
|
||||
|
||||
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());
|
||||
|
@ -437,6 +452,13 @@ void ValidatorManagerMasterchainStarter::got_hardforks(std::vector<BlockIdExt> v
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (opts_->need_db_truncate()) {
|
||||
auto seq = opts_->get_truncate_seqno();
|
||||
if (seq <= handle_->id().seqno()) {
|
||||
got_truncate_block_seqno(seq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
start_shard_client();
|
||||
return;
|
||||
}
|
||||
|
@ -444,9 +466,10 @@ void ValidatorManagerMasterchainStarter::got_hardforks(std::vector<BlockIdExt> v
|
|||
LOG(FATAL) << "cannot start: number of hardforks increase is too big";
|
||||
return;
|
||||
}
|
||||
has_new_hardforks_ = true;
|
||||
|
||||
auto b = *h.rbegin();
|
||||
if (b.seqno() > handle_->id().seqno()) {
|
||||
if (handle_->id().seqno() + 1 < b.seqno()) {
|
||||
truncated();
|
||||
return;
|
||||
}
|
||||
|
@ -455,8 +478,16 @@ void ValidatorManagerMasterchainStarter::got_hardforks(std::vector<BlockIdExt> v
|
|||
return;
|
||||
}
|
||||
|
||||
got_truncate_block_seqno(b.seqno() - 1);
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_truncate_block_seqno(BlockSeqno seqno) {
|
||||
BlockIdExt id;
|
||||
if (state_->get_old_mc_block_id(b.seqno() - 1, id)) {
|
||||
if (handle_->id().seqno() == seqno) {
|
||||
got_truncate_block_handle(handle_);
|
||||
return;
|
||||
}
|
||||
if (state_->get_old_mc_block_id(seqno, id)) {
|
||||
got_truncate_block_id(id);
|
||||
return;
|
||||
}
|
||||
|
@ -465,8 +496,7 @@ void ValidatorManagerMasterchainStarter::got_hardforks(std::vector<BlockIdExt> v
|
|||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_truncate_block_id, R.move_as_ok()->id());
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::get_block_by_seqno, AccountIdPrefixFull{masterchainId, 0}, b.seqno() - 1,
|
||||
std::move(P));
|
||||
td::actor::send_closure(db_, &Db::get_block_by_seqno, AccountIdPrefixFull{masterchainId, 0}, seqno, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_truncate_block_id(BlockIdExt block_id) {
|
||||
|
@ -491,76 +521,66 @@ void ValidatorManagerMasterchainStarter::got_truncate_block_handle(BlockHandle h
|
|||
|
||||
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) {
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::truncated_db);
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::got_prev_key_block_handle, R.move_as_ok());
|
||||
});
|
||||
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));
|
||||
}
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, state_->last_key_block_id(), false,
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::got_prev_key_block_handle(BlockHandle handle) {
|
||||
last_key_block_handle_ = std::move(handle);
|
||||
//LOG_CHECK(last_key_block_handle_->inited_is_key_block() && last_key_block_handle_->is_key_block())
|
||||
// << last_key_block_handle_->id();
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::truncated);
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::truncate, block_id_.seqno(), handle_, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::truncate_shard_next(BlockIdExt block_id, td::Promise<td::Unit> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), manager = manager_, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
R.ensure();
|
||||
auto handle = R.move_as_ok();
|
||||
handle->unsafe_clear_next();
|
||||
handle->flush(manager, handle, std::move(promise));
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, block_id, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::truncated() {
|
||||
handle_->set_next(*opts_->get_hardforks().rbegin());
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
|
||||
ig.add_promise([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::written_next);
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::truncated_next);
|
||||
});
|
||||
handle_->flush(manager_, handle_, std::move(P));
|
||||
|
||||
truncate_shard_next(handle_->id(), ig.get_promise());
|
||||
auto s = state_->get_shards();
|
||||
for (auto &shard : s) {
|
||||
if (opts_->need_monitor(shard->shard())) {
|
||||
truncate_shard_next(shard->top_block_id(), ig.get_promise());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::truncated_next() {
|
||||
if (has_new_hardforks_) {
|
||||
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));
|
||||
} else {
|
||||
start_shard_client();
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::written_next() {
|
||||
|
|
|
@ -98,12 +98,15 @@ class ValidatorManagerMasterchainStarter : public td::actor::Actor {
|
|||
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_seqno(BlockSeqno seqno);
|
||||
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 truncate_shard_next(BlockIdExt block_id, td::Promise<td::Unit> promise);
|
||||
void truncated_next();
|
||||
void written_next();
|
||||
void start_shard_client();
|
||||
void finish();
|
||||
|
@ -117,13 +120,13 @@ class ValidatorManagerMasterchainStarter : public td::actor::Actor {
|
|||
BlockHandle gc_handle_;
|
||||
td::Ref<MasterchainState> gc_state_;
|
||||
BlockHandle last_key_block_handle_;
|
||||
bool has_new_hardforks_{false};
|
||||
|
||||
td::actor::ActorId<ValidatorManager> manager_;
|
||||
td::actor::ActorId<Db> db_;
|
||||
|
||||
td::Promise<ValidatorManagerInitResult> promise_;
|
||||
|
||||
BlockIdExt client_block_id_;
|
||||
td::actor::ActorOwn<ShardClient> client_;
|
||||
};
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ void ValidatorManagerImpl::get_key_block_proof_link(BlockIdExt block_id, td::Pro
|
|||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise), block_id, db = db_.get()](td::Result<td::Ref<Proof>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<Proof>> R) mutable {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Ref<ProofLink>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
|
@ -352,7 +352,7 @@ void ValidatorManagerImpl::get_key_block_proof_link(BlockIdExt block_id, td::Pro
|
|||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(db, &Db::get_key_block_proof, block_id, std::move(P));
|
||||
td::actor::send_closure(db, &Db::get_key_block_proof_link, block_id, std::move(P));
|
||||
} else {
|
||||
auto B = R.move_as_ok()->export_as_proof_link().move_as_ok();
|
||||
promise.set_value(B->data());
|
||||
|
@ -1123,15 +1123,14 @@ void ValidatorManagerImpl::write_handle(BlockHandle handle, td::Promise<td::Unit
|
|||
void ValidatorManagerImpl::written_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
bool received = handle->received();
|
||||
bool inited_state = handle->received_state();
|
||||
bool inited_proof = handle->inited_proof();
|
||||
bool inited_proof_link = handle->inited_proof_link();
|
||||
bool inited_proof = handle->id().is_masterchain() ? handle->inited_proof() : handle->inited_proof();
|
||||
|
||||
if (handle->need_flush()) {
|
||||
handle->flush(actor_id(this), handle, std::move(promise));
|
||||
return;
|
||||
}
|
||||
|
||||
if (received && (inited_proof || inited_proof_link)) {
|
||||
if (received && inited_proof) {
|
||||
auto it = wait_block_data_.find(handle->id());
|
||||
if (it != wait_block_data_.end()) {
|
||||
td::actor::send_closure(it->second.actor_, &WaitBlockData::force_read_from_db);
|
||||
|
@ -1375,7 +1374,7 @@ void ValidatorManagerImpl::send_block_broadcast(BlockBroadcast broadcast) {
|
|||
}
|
||||
|
||||
void ValidatorManagerImpl::start_up() {
|
||||
db_ = create_db_actor(actor_id(this), db_root_, opts_->get_filedb_depth());
|
||||
db_ = create_db_actor(actor_id(this), db_root_);
|
||||
lite_server_cache_ = create_liteserver_cache_actor(actor_id(this), db_root_);
|
||||
token_manager_ = td::actor::create_actor<TokenManager>("tokenmanager");
|
||||
td::mkdir(db_root_ + "/tmp/").ensure();
|
||||
|
@ -1448,7 +1447,9 @@ void ValidatorManagerImpl::started(ValidatorManagerInitResult R) {
|
|||
last_known_key_block_handle_ = last_key_block_handle_;
|
||||
|
||||
CHECK(last_masterchain_block_handle_->is_applied());
|
||||
callback_->new_key_block(last_key_block_handle_);
|
||||
if (last_known_key_block_handle_->inited_is_key_block()) {
|
||||
callback_->new_key_block(last_key_block_handle_);
|
||||
}
|
||||
|
||||
gc_masterchain_handle_ = std::move(R.gc_handle);
|
||||
gc_masterchain_state_ = std::move(R.gc_state);
|
||||
|
@ -1480,6 +1481,38 @@ void ValidatorManagerImpl::read_gc_list(std::vector<ValidatorSessionId> list) {
|
|||
serializer_ =
|
||||
td::actor::create_actor<AsyncStateSerializer>("serializer", last_key_block_handle_->id(), opts_, actor_id(this));
|
||||
|
||||
if (last_masterchain_block_handle_->inited_next_left()) {
|
||||
auto b = last_masterchain_block_handle_->one_next(true);
|
||||
if (opts_->is_hardfork(b) && !out_of_sync()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), b](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(INFO) << "NO HARDFORK BLOCK IN STATIC FILES";
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::applied_hardfork);
|
||||
return;
|
||||
}
|
||||
|
||||
auto dataR = create_block(b, R.move_as_ok());
|
||||
dataR.ensure();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::applied_hardfork);
|
||||
});
|
||||
run_hardfork_accept_block_query(b, dataR.move_as_ok(), SelfId, std::move(P));
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::try_get_static_file, b.file_hash, std::move(P));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!out_of_sync()) {
|
||||
completed_prestart_sync();
|
||||
} else {
|
||||
prestart_sync();
|
||||
}
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::applied_hardfork() {
|
||||
if (!out_of_sync()) {
|
||||
completed_prestart_sync();
|
||||
} else {
|
||||
|
@ -1488,6 +1521,13 @@ void ValidatorManagerImpl::read_gc_list(std::vector<ValidatorSessionId> list) {
|
|||
}
|
||||
|
||||
bool ValidatorManagerImpl::out_of_sync() {
|
||||
auto seqno = std::min(last_masterchain_seqno_, shard_client_handle_->id().seqno());
|
||||
if (seqno < opts_->sync_upto()) {
|
||||
return true;
|
||||
}
|
||||
if (shard_client_handle_->id().seqno() + 16 < last_masterchain_seqno_) {
|
||||
return true;
|
||||
}
|
||||
if (last_masterchain_block_handle_->unix_time() + 600 > td::Clocks::system()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1496,7 +1536,16 @@ bool ValidatorManagerImpl::out_of_sync() {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (validator_groups_.size() > 0 && last_known_key_block_handle_->id().seqno() <= last_masterchain_seqno_) {
|
||||
bool masterchain_validator = false;
|
||||
if (!validator_groups_.size()) {
|
||||
auto val_set = last_masterchain_state_->get_validator_set(ShardIdFull{masterchainId});
|
||||
if (!get_validator(ShardIdFull{masterchainId}, val_set).is_zero()) {
|
||||
masterchain_validator = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((masterchain_validator || validator_groups_.size() > 0) &&
|
||||
last_known_key_block_handle_->id().seqno() <= last_masterchain_seqno_) {
|
||||
return false;
|
||||
}
|
||||
LOG(INFO) << "groups=" << validator_groups_.size() << " seqno=" << last_known_key_block_handle_->id().seqno()
|
||||
|
@ -1538,7 +1587,7 @@ void ValidatorManagerImpl::download_next_archive() {
|
|||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::downloaded_archive_slice, R.move_as_ok(), true);
|
||||
}
|
||||
});
|
||||
callback_->download_archive(seqno + 1, db_root_ + "/tmp/", td::Timestamp::in(3600.0), std::move(P));
|
||||
callback_->download_archive(seqno + 1, db_root_ + "/tmp/", td::Timestamp::in(36000.0), std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::downloaded_archive_slice(std::string name, bool is_tmp) {
|
||||
|
@ -2167,14 +2216,17 @@ void ValidatorManagerImpl::alarm() {
|
|||
try_advance_gc_masterchain_block();
|
||||
alarm_timestamp() = td::Timestamp::in(1.0);
|
||||
if (gc_masterchain_handle_) {
|
||||
td::actor::send_closure(db_, &Db::run_gc, gc_masterchain_handle_->unix_time());
|
||||
td::actor::send_closure(db_, &Db::run_gc, gc_masterchain_handle_->unix_time(),
|
||||
static_cast<UnixTime>(opts_->archive_ttl()));
|
||||
}
|
||||
if (log_status_at_.is_in_past()) {
|
||||
if (last_masterchain_block_handle_) {
|
||||
LOG(INFO) << "STATUS: last_masterchain_block_ago="
|
||||
<< td::format::as_time(td::Clocks::system() - last_masterchain_block_handle_->unix_time())
|
||||
<< " last_known_key_block_ago="
|
||||
<< td::format::as_time(td::Clocks::system() - last_known_key_block_handle_->unix_time())
|
||||
<< td::format::as_time(td::Clocks::system() - (last_known_key_block_handle_->inited_unix_time()
|
||||
? last_known_key_block_handle_->unix_time()
|
||||
: 0))
|
||||
<< " shard_client_ago="
|
||||
<< td::format::as_time(td::Clocks::system() -
|
||||
(shard_client_handle_ ? shard_client_handle_->unix_time() : 0));
|
||||
|
@ -2268,7 +2320,7 @@ bool ValidatorManagerImpl::is_validator() {
|
|||
}
|
||||
|
||||
PublicKeyHash ValidatorManagerImpl::get_validator(ShardIdFull shard, td::Ref<ValidatorSet> val_set) {
|
||||
if (!opts_->need_validate(shard)) {
|
||||
if (!opts_->need_validate(shard, val_set->get_catchain_seqno())) {
|
||||
return PublicKeyHash::zero();
|
||||
}
|
||||
for (auto &key : temp_keys_) {
|
||||
|
@ -2359,8 +2411,8 @@ 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::truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(db_, &Db::truncate, seqno, std::move(handle), std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout,
|
||||
|
|
|
@ -264,6 +264,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void update_shard_client_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
|
||||
bool out_of_sync();
|
||||
void applied_hardfork();
|
||||
void prestart_sync();
|
||||
void download_next_archive();
|
||||
void downloaded_archive_slice(std::string name, bool is_tmp);
|
||||
|
@ -512,7 +513,7 @@ 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 truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
|
||||
void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise<td::Unit> promise) override;
|
||||
|
||||
|
|
|
@ -25,10 +25,10 @@ namespace ton {
|
|||
namespace validator {
|
||||
|
||||
td::Ref<ValidatorManagerOptions> ValidatorManagerOptions::create(
|
||||
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) {
|
||||
BlockIdExt zero_block_id, BlockIdExt init_block_id,
|
||||
std::function<bool(ShardIdFull, CatchainSeqno, 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) {
|
||||
return td::make_ref<ValidatorManagerOptionsImpl>(zero_block_id, init_block_id, std::move(check_shard),
|
||||
allow_blockchain_init, sync_blocks_before, block_ttl, state_ttl,
|
||||
archive_ttl, key_proof_ttl, initial_sync_disabled);
|
||||
|
|
|
@ -33,10 +33,10 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
return init_block_id_;
|
||||
}
|
||||
bool need_monitor(ShardIdFull shard) const override {
|
||||
return check_shard_(shard, ShardCheckMode::m_monitor);
|
||||
return check_shard_(shard, 0, ShardCheckMode::m_monitor);
|
||||
}
|
||||
bool need_validate(ShardIdFull shard) const override {
|
||||
return check_shard_(shard, ShardCheckMode::m_validate);
|
||||
bool need_validate(ShardIdFull shard, CatchainSeqno cc_seqno) const override {
|
||||
return check_shard_(shard, cc_seqno, ShardCheckMode::m_validate);
|
||||
}
|
||||
bool allow_blockchain_init() const override {
|
||||
return allow_blockchain_init_;
|
||||
|
@ -88,9 +88,6 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
std::vector<BlockIdExt> get_hardforks() const override {
|
||||
return hardforks_;
|
||||
}
|
||||
td::uint32 get_filedb_depth() const override {
|
||||
return db_depth_;
|
||||
}
|
||||
bool check_unsafe_resync_allowed(CatchainSeqno seqno) const override {
|
||||
return unsafe_catchains_.count(seqno) > 0;
|
||||
}
|
||||
|
@ -102,6 +99,15 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
return it->second.first <= seqno ? it->second.second : 0;
|
||||
}
|
||||
}
|
||||
bool need_db_truncate() const override {
|
||||
return truncate_ > 0;
|
||||
}
|
||||
BlockSeqno get_truncate_seqno() const override {
|
||||
return truncate_;
|
||||
}
|
||||
BlockSeqno sync_upto() const override {
|
||||
return sync_upto_;
|
||||
}
|
||||
|
||||
void set_zero_block_id(BlockIdExt block_id) override {
|
||||
zero_block_id_ = block_id;
|
||||
|
@ -109,7 +115,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, ShardCheckMode)> check_shard) override {
|
||||
void set_shard_check_function(std::function<bool(ShardIdFull, CatchainSeqno, ShardCheckMode)> check_shard) override {
|
||||
check_shard_ = std::move(check_shard);
|
||||
}
|
||||
void set_allow_blockchain_init(bool value) override {
|
||||
|
@ -136,26 +142,29 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
void set_hardforks(std::vector<BlockIdExt> vec) override {
|
||||
hardforks_ = std::move(vec);
|
||||
}
|
||||
void set_filedb_depth(td::uint32 value) override {
|
||||
CHECK(value <= 32);
|
||||
db_depth_ = value;
|
||||
}
|
||||
void add_unsafe_resync_catchain(CatchainSeqno seqno) override {
|
||||
unsafe_catchains_.insert(seqno);
|
||||
}
|
||||
void add_unsafe_catchain_rotate(BlockSeqno seqno, CatchainSeqno cc_seqno, td::uint32 value) override {
|
||||
unsafe_catchain_rotates_[cc_seqno] = std::make_pair(seqno, value);
|
||||
}
|
||||
void truncate_db(BlockSeqno seqno) override {
|
||||
truncate_ = seqno;
|
||||
}
|
||||
void set_sync_upto(BlockSeqno seqno) override {
|
||||
sync_upto_ = seqno;
|
||||
}
|
||||
|
||||
ValidatorManagerOptionsImpl *make_copy() const override {
|
||||
return new ValidatorManagerOptionsImpl(*this);
|
||||
}
|
||||
|
||||
ValidatorManagerOptionsImpl(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)
|
||||
std::function<bool(ShardIdFull, CatchainSeqno, 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)
|
||||
: zero_block_id_(zero_block_id)
|
||||
, init_block_id_(init_block_id)
|
||||
, check_shard_(std::move(check_shard))
|
||||
|
@ -171,7 +180,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
private:
|
||||
BlockIdExt zero_block_id_;
|
||||
BlockIdExt init_block_id_;
|
||||
std::function<bool(ShardIdFull, ShardCheckMode)> check_shard_;
|
||||
std::function<bool(ShardIdFull, CatchainSeqno, ShardCheckMode)> check_shard_;
|
||||
bool allow_blockchain_init_;
|
||||
td::ClocksBase::Duration sync_blocks_before_;
|
||||
td::ClocksBase::Duration block_ttl_;
|
||||
|
@ -180,9 +189,10 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
|||
td::ClocksBase::Duration key_proof_ttl_;
|
||||
bool initial_sync_disabled_;
|
||||
std::vector<BlockIdExt> hardforks_;
|
||||
td::uint32 db_depth_ = 2;
|
||||
std::set<CatchainSeqno> unsafe_catchains_;
|
||||
std::map<CatchainSeqno, std::pair<BlockSeqno, td::uint32>> unsafe_catchain_rotates_;
|
||||
BlockSeqno truncate_{0};
|
||||
BlockSeqno sync_upto_{0};
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -51,7 +51,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
|||
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 need_validate(ShardIdFull shard, CatchainSeqno cc_seqno) 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;
|
||||
|
@ -64,16 +64,19 @@ struct ValidatorManagerOptions : public td::CntObject {
|
|||
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;
|
||||
}
|
||||
virtual bool check_unsafe_resync_allowed(CatchainSeqno seqno) const = 0;
|
||||
virtual td::uint32 check_unsafe_catchain_rotate(BlockSeqno seqno, CatchainSeqno cc_seqno) const = 0;
|
||||
virtual bool need_db_truncate() const = 0;
|
||||
virtual BlockSeqno get_truncate_seqno() const = 0;
|
||||
virtual BlockSeqno sync_upto() const = 0;
|
||||
|
||||
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, ShardCheckMode)> check_shard) = 0;
|
||||
virtual void set_shard_check_function(
|
||||
std::function<bool(ShardIdFull, CatchainSeqno, 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;
|
||||
|
@ -82,13 +85,15 @@ struct ValidatorManagerOptions : public td::CntObject {
|
|||
virtual void set_key_proof_ttl(td::ClocksBase::Duration value) = 0;
|
||||
virtual void set_initial_sync_disabled(bool value) = 0;
|
||||
virtual void set_hardforks(std::vector<BlockIdExt> hardforks) = 0;
|
||||
virtual void set_filedb_depth(td::uint32 value) = 0;
|
||||
virtual void add_unsafe_resync_catchain(CatchainSeqno seqno) = 0;
|
||||
virtual void add_unsafe_catchain_rotate(BlockSeqno seqno, CatchainSeqno cc_seqno, td::uint32 value) = 0;
|
||||
virtual void truncate_db(BlockSeqno seqno) = 0;
|
||||
virtual void set_sync_upto(BlockSeqno seqno) = 0;
|
||||
|
||||
static td::Ref<ValidatorManagerOptions> create(
|
||||
BlockIdExt zero_block_id, BlockIdExt init_block_id,
|
||||
std::function<bool(ShardIdFull, ShardCheckMode)> check_shard = [](ShardIdFull, ShardCheckMode) { return true; },
|
||||
std::function<bool(ShardIdFull, CatchainSeqno, ShardCheckMode)> check_shard = [](ShardIdFull, CatchainSeqno,
|
||||
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