mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
speed up synchronization
- download old files in chunks - updated docs - fixed elector/config smartcontracts
This commit is contained in:
parent
0dae2c157b
commit
7f3a22a217
21 changed files with 365 additions and 191 deletions
|
@ -26,7 +26,7 @@
|
|||
|
||||
(int, int) check_validator_set(cell vset) {
|
||||
var cs = vset.begin_parse();
|
||||
throw_if(9, (cs~load_uint(8) - 0x11) & -2); ;; validators#11 or validators_ext#12
|
||||
throw_unless(9, cs~load_uint(8) == 0x12); ;; validators_ext#12 only
|
||||
int utime_since = cs~load_uint(32);
|
||||
int utime_until = cs~load_uint(32);
|
||||
int total = cs~load_uint(16);
|
||||
|
@ -103,7 +103,7 @@
|
|||
.end_cell(), 0);
|
||||
}
|
||||
|
||||
() after_code_upgrade(slice param, cell old_code) impure method_id(1666) {
|
||||
() after_code_upgrade(slice param, cont old_code) impure method_id(1666) {
|
||||
}
|
||||
|
||||
_ perform_action(cfg_dict, public_key, action, cs) {
|
||||
|
@ -119,7 +119,7 @@ _ perform_action(cfg_dict, public_key, action, cs) {
|
|||
var new_code = cs~load_ref();
|
||||
set_code(new_code);
|
||||
var old_code = get_c3();
|
||||
set_c3(new_code);
|
||||
set_c3(new_code.begin_parse().bless());
|
||||
after_code_upgrade(cs, old_code);
|
||||
throw(0);
|
||||
return (cfg_dict, public_key);
|
||||
|
@ -231,7 +231,7 @@ cell register_vote(vote_dict, action, cs, idx, weight) {
|
|||
if (ds.slice_bits() >= 40) {
|
||||
var tag = ds~load_uint(8);
|
||||
var since = ds.preload_uint(32);
|
||||
if ((tag == 0x11) & (since >= now())) {
|
||||
if ((since <= now()) & (tag == 0x12)) {
|
||||
;; next validator set becomes active!
|
||||
var cur_vset = cfg_dict~idict_set_get_ref(kl, 34, next_vset); ;; next_vset -> cur_vset
|
||||
cfg_dict~idict_set_get_ref(kl, 32, cur_vset); ;; cur_vset -> prev_vset
|
||||
|
@ -241,3 +241,7 @@ cell register_vote(vote_dict, action, cs, idx, weight) {
|
|||
}
|
||||
set_data(begin_cell().store_ref(cfg_dict).store_slice(cs).end_cell());
|
||||
}
|
||||
|
||||
int seqno() impure method_id {
|
||||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ int upgrade_code(s_addr, cs, query_id) {
|
|||
var code = cs~load_ref();
|
||||
set_code(code);
|
||||
ifnot(cs.slice_empty?()) {
|
||||
set_c3(code);
|
||||
set_c3(code.begin_parse().bless());
|
||||
;; run_method3(1666, s_addr, cs, query_id);
|
||||
after_code_upgrade(s_addr, cs, query_id);
|
||||
throw(0);
|
||||
|
|
|
@ -215,10 +215,11 @@ now dup orig_vset_valid_for + 0 config.validators!
|
|||
*
|
||||
*/
|
||||
"auto/config-code.fif" include // code in separate source file
|
||||
<b 0 32 u,
|
||||
<b configdict ref, // initial configuration
|
||||
0 32 u, // seqno
|
||||
"config-master" +suffix +".pk" load-generate-keypair drop
|
||||
B,
|
||||
configdict ref,
|
||||
newdict dict, // vote dict
|
||||
b> // data
|
||||
empty_cell // libraries
|
||||
GR$10 // balance
|
||||
|
|
|
@ -35,8 +35,10 @@ int check_data_signature(slice data, slice signature, int public_key) asm "CHKSI
|
|||
|
||||
cell get_data() asm "c4 PUSH";
|
||||
() set_data(cell c) impure asm "c4 POP";
|
||||
cell get_c3() impure asm "c3 PUSH";
|
||||
() set_c3(cell c) impure asm "c3 POP";
|
||||
cont get_c3() impure asm "c3 PUSH";
|
||||
() set_c3(cont c) impure asm "c3 POP";
|
||||
cont bless(slice s) impure asm "BLESS";
|
||||
|
||||
() accept_message() impure asm "ACCEPT";
|
||||
() commit() impure asm "COMMIT";
|
||||
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
$# dup 2 < swap 3 > or ' usage if
|
||||
|
||||
"config-master" constant file-base
|
||||
0 constant seqno
|
||||
0 constant qseqno
|
||||
-1 constant idx
|
||||
true constant bounce
|
||||
"auto/config-code.fif" constant config-source
|
||||
100 constant interval // valid for 100 seconds
|
||||
|
||||
$1 =: file-base
|
||||
$2 parse-int =: seqno
|
||||
$2 parse-int =: qseqno
|
||||
def? $3 { @' $3 } { "config-query" } cond constant savefile
|
||||
|
||||
file-base +".addr" load-address
|
||||
|
@ -30,7 +30,7 @@ config-source include
|
|||
dup <s csr. cr
|
||||
|
||||
// create a message
|
||||
<b x{4e436f64} s, seqno 32 u, now interval + 32 u, swap ref, b>
|
||||
<b x{4e436f64} s, qseqno 32 u, now interval + 32 u, swap ref, b>
|
||||
dup ."signing message: " <s csr. cr
|
||||
dup hashu config_pk ed25519_sign_uint
|
||||
<b b{1000100} s, config_addr addr, 0 Gram, b{00} s,
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <seqno> <amount> [-B <body-boc>] [-C <transfer-comment>] [<savefile>]" cr
|
||||
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <seqno> <amount> [-n] [-B <body-boc>] [-C <transfer-comment>] [<savefile>]" cr
|
||||
."Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file <filename-base>.pk "
|
||||
."and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)" cr 1 halt
|
||||
} : usage
|
||||
"" =: comment // comment for simple transfers
|
||||
true =: allow-bounce
|
||||
def? $5 { @' $5 "-n" $= { false =: allow-bounce [forget] $5
|
||||
def? $6 { @' $6 =: $5 [forget] $6 } if
|
||||
def? $7 { @' $7 =: $6 [forget] $7 } if
|
||||
@' $# 1- =: $#
|
||||
} if
|
||||
} if
|
||||
|
||||
def? $6 { @' $5 dup "-B" $= swap "-C" $= tuck or
|
||||
{ @' $6 swap { =: comment } { =: body-boc-file } cond [forget] $6
|
||||
def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond
|
||||
|
@ -17,7 +25,7 @@ $# dup 4 < swap 5 > or ' usage if
|
|||
true constant bounce
|
||||
|
||||
$1 =: file-base
|
||||
$2 bounce parse-load-address =: bounce 2=: dest_addr
|
||||
$2 bounce parse-load-address allow-bounce and =: bounce 2=: dest_addr
|
||||
$3 parse-int =: seqno
|
||||
$4 $>GR =: amount
|
||||
def? $5 { @' $5 } { "wallet-query" } cond constant savefile
|
||||
|
|
|
@ -626,9 +626,23 @@ inline void throw_rangechk(bool ok) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
int exec_bless_pop_c3(VmState* st) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute CTOSBLESSPOPc3";
|
||||
stack.check_underflow(1);
|
||||
throw_typechk(st->set_c(3, Ref<OrdCont>{true, vm::load_cell_slice_ref(stack.pop_cell()), st->get_cp()}));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exec_pop_ctr(VmState* st, unsigned args) {
|
||||
unsigned idx = args & 15;
|
||||
VM_LOG(st) << "execute POP c" << idx;
|
||||
/*
|
||||
if (idx == 3 && st->get_stack().depth() > 0 && st->get_stack().tos().is(StackEntry::t_cell)) {
|
||||
// temp hack: accept cell argument for POP c3 and do auto-BLESSing
|
||||
return exec_bless_pop_c3(st);
|
||||
}
|
||||
*/
|
||||
throw_typechk(st->set(idx, st->get_stack().pop_chk()));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ Note that you need a machine with a public IP address and a high-bandwidth netwo
|
|||
0. Downloading and compiling
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The complete TON Blockchain Library and Validator software is downloaded and compiled similarly to the Lite Client. This process is outlined in the corresponding README file. The most important difference is that you have to download the complete sources from public GitHub repository https://github.com/ton-blockchain/ton (e.g., by running `git clone https://github.com/ton-blockchain/ton`) instead of downloading the smaller Lite Client source archive. You should also build all goals defined in CMakeLists.txt (e.g. by running `cmake <path-to-source-directory>` and `make` in your build directory), not only those specifically related to the Lite Client (which is also included in the larger distribution; you don't have to download and build it separately). We strongly recommend building a "release" or a "release with debug information" version of the TON Blockchain Library and especially of the Validator/Full Node by passing `-DCMAKE_BUILD_TYPE=Release` or `-DCMAKE_BUILD_TYPE=RelWithDebInfo` as an extra argument to `cmake` during its first run (if you forgot to do this, you can later delete file `CMakeCache.txt` from your build directory and re-run `cmake` with the appropriate options).
|
||||
The complete TON Blockchain Library and Validator software is downloaded and compiled similarly to the Lite Client. This process is outlined in the corresponding README file. The most important difference is that you have to download the complete sources from public GitHub repository https://github.com/ton-blockchain/ton (e.g., by running `git clone https://github.com/ton-blockchain/ton` and `git submodule update` afterwards) instead of downloading the smaller Lite Client source archive. You should also build all goals defined in CMakeLists.txt (e.g. by running `cmake <path-to-source-directory>` and `make` in your build directory), not only those specifically related to the Lite Client (which is also included in the larger distribution; you don't have to download and build it separately). We strongly recommend building a "release" or a "release with debug information" version of the TON Blockchain Library and especially of the Validator/Full Node by passing `-DCMAKE_BUILD_TYPE=Release` or `-DCMAKE_BUILD_TYPE=RelWithDebInfo` as an extra argument to `cmake` during its first run (if you forgot to do this, you can later delete file `CMakeCache.txt` from your build directory and re-run `cmake` with the appropriate options).
|
||||
|
||||
1. Full Node binaries
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -10,7 +10,7 @@ The basic instructions are the same as for a TON Blockchain Full Node, as explai
|
|||
1. Controlling smart contract of a validator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In order to run a Validator, you'll need a Full Node that is already up and running (and completely synchronized with the current blockchain state), and a wallet in the masterchain holding a large amount of Grams (or test Grams, if you want to run a validator in the "testnet" TON Blockchain instance). Typically you'll need at least 100,000 Grams.
|
||||
In order to run a Validator, you'll need a Full Node that is already up and running (and completely synchronized with the current blockchain state), and a wallet in the masterchain holding a large amount of Grams (or test Grams, if you want to run a validator in the "testnet" TON Blockchain instance). Typically you'll need at least 100,001 Grams in the production network, and at least 10,001 test Grams in the test network. The actual value (in nanograms) can be found as the value of `min_stake` in configuration parameter #17 (available by typing `getconfig 17` into the Lite Client), plus one Gram.
|
||||
|
||||
Each validator is identified by its (Ed25519) public key. During the validator elections, the validator (or rather its public key) is also associated with a smart contract residing in the masterchain. For simplicity, we say that the validator is "controlled" by this smart contract (e.g., a wallet smart contract). Stakes are accepted on behalf of this validator only if they arrive from its associated smart contract, and only that associated smart contract is entitled to collect the validator's stake after it is unfrozen, along with the validator's share of bonuses (e.g., block mining fees, transaction and message forwarding fees collected from the users of the TON Blockchain by the validator pool). Typically the bonuses are distributed proportionally to the (effective) stakes of the validators. On the other hand, validators with higher stakes are assigned a larger amount of work to perform (i.e., they have to create and validate blocks for more shardchains), so it is important not to stake an amount that will yield more validation work than your node is capable of handling.
|
||||
|
||||
|
|
|
@ -8,18 +8,19 @@ The software is likely to compile and work properly on most Linux systems. It sh
|
|||
|
||||
BASIC COMPILATION AND INSTALLATION INSTRUCTIONS
|
||||
|
||||
1) Download and unpack the newest version of this archive, available at
|
||||
1) Download the newest version of the TON blockchain sources, available at GitHub repository https://github.com/ton-blockchain/ton/ :
|
||||
|
||||
https://test.ton.org/download
|
||||
git clone https://github.com/ton-blockchain/ton.git
|
||||
git submodule update
|
||||
|
||||
The TON Blockchain Test Network is updated quite often, so we cannot guarantee that older versions of the Lite Client will always work. Backward compatibility is not enforced at this development stage.
|
||||
|
||||
2) Install the newest versions of make, cmake (version 3.0.2 or later), OpenSSL (including C header files), and g++ or clang (or another C++14-compatible compiler as appropriate for your operating system). We strongly recommend installing OpenSSL version 1.1.1 or later for better performance, especially if you intend to run a Full Node or a Validator as well.
|
||||
|
||||
3) Suppose that you have unpacked this archive to directory ~/lite-client, where ~ is your home directory, and that you have created an empty directory ~/liteclient-build. Then run the following in a terminal on a Linux system:
|
||||
3) Suppose that you have fetched the source tree to directory ~/ton, where ~ is your home directory, and that you have created an empty directory ~/liteclient-build. Then run the following in a terminal on a Linux system:
|
||||
|
||||
cd ~/liteclient-build
|
||||
cmake ~/lite-client
|
||||
cmake ~/ton
|
||||
cmake --build . --target lite-client
|
||||
|
||||
You might also build some extra utilities useful for smart-contract development:
|
||||
|
|
|
@ -250,8 +250,7 @@ void ArchiveManager::get_file_short_cont(FileReference ref_id, PackageId idx, td
|
|||
|
||||
void ArchiveManager::get_file(BlockHandle handle, FileReference ref_id, td::Promise<td::BufferSlice> promise) {
|
||||
if (handle->moved_to_archive()) {
|
||||
auto f = get_file_desc(handle->id().shard_full(), PackageId{handle->masterchain_ref_block(), false, false}, 0, 0, 0,
|
||||
false);
|
||||
auto f = get_file_desc(handle->id().shard_full(), get_package_id(handle->masterchain_ref_block()), 0, 0, 0, false);
|
||||
if (f) {
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveSlice::get_file, std::move(ref_id), std::move(promise));
|
||||
return;
|
||||
|
|
|
@ -193,6 +193,9 @@ void DownloadShardState::written_shard_state(td::Ref<ShardState> state) {
|
|||
handle_->set_logical_time(state_->get_logical_time());
|
||||
handle_->set_applied();
|
||||
handle_->set_split(state_->before_split());
|
||||
if (!block_id_.is_masterchain()) {
|
||||
handle_->set_masterchain_ref_block(masterchain_block_id_.seqno());
|
||||
}
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle = handle_](td::Result<td::Unit> R) {
|
||||
CHECK(handle->handle_moved_to_archive());
|
||||
|
|
|
@ -99,7 +99,6 @@ void FullNodeImpl::initial_read_complete(BlockHandle top_handle) {
|
|||
}
|
||||
|
||||
void FullNodeImpl::add_shard(ShardIdFull shard) {
|
||||
LOG(WARNING) << "add shard " << shard;
|
||||
while (true) {
|
||||
if (shards_.count(shard) == 0) {
|
||||
shards_.emplace(shard, FullNodeShard::create(shard, local_id_, adnl_id_, zero_state_file_hash_, keyring_, adnl_,
|
||||
|
@ -239,6 +238,7 @@ void FullNodeImpl::download_archive(BlockSeqno masterchain_seqno, std::string tm
|
|||
}
|
||||
|
||||
td::actor::ActorId<FullNodeShard> FullNodeImpl::get_shard(ShardIdFull shard) {
|
||||
add_shard(ShardIdFull{shard.workchain, shardIdAll});
|
||||
while (shards_.count(shard) == 0) {
|
||||
if (shard.shard == shardIdAll) {
|
||||
return td::actor::ActorId<FullNodeShard>{};
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "td/actor/MultiPromise.h"
|
||||
#include "common/checksum.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "ton/ton-io.hpp"
|
||||
#include "downloaders/download-state.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -94,79 +96,85 @@ void ArchiveImporter::check_masterchain_block(BlockSeqno seqno) {
|
|||
checked_all_masterchain_blocks(seqno - 1);
|
||||
return;
|
||||
}
|
||||
if (seqno < state_->get_block_id().seqno()) {
|
||||
if (!state_->check_old_mc_block_id(it->second)) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad old masterchain block id"));
|
||||
return;
|
||||
}
|
||||
check_masterchain_block(seqno + 1);
|
||||
} else if (seqno == state_->get_block_id().seqno()) {
|
||||
if (state_->get_block_id() != it->second) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad old masterchain block id"));
|
||||
return;
|
||||
}
|
||||
check_masterchain_block(seqno + 1);
|
||||
} else {
|
||||
if (seqno != state_->get_block_id().seqno() + 1) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "hole in masterchain seqno"));
|
||||
return;
|
||||
}
|
||||
auto it2 = blocks_.find(it->second);
|
||||
CHECK(it2 != blocks_.end());
|
||||
|
||||
auto R1 = package_->read(it2->second[0]);
|
||||
if (R1.is_error()) {
|
||||
abort_query(R1.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto proofR = create_proof(it->second, std::move(R1.move_as_ok().second));
|
||||
if (proofR.is_error()) {
|
||||
abort_query(proofR.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto R2 = package_->read(it2->second[1]);
|
||||
if (R2.is_error()) {
|
||||
abort_query(R2.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
if (sha256_bits256(R2.ok().second.as_slice()) != it->second.file_hash) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad block file hash"));
|
||||
return;
|
||||
}
|
||||
auto dataR = create_block(it->second, std::move(R2.move_as_ok().second));
|
||||
if (dataR.is_error()) {
|
||||
abort_query(dataR.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto proof = proofR.move_as_ok();
|
||||
auto data = dataR.move_as_ok();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), id = state_->get_block_id(),
|
||||
data](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::abort_query, R.move_as_error());
|
||||
while (seqno <= state_->get_block_id().seqno()) {
|
||||
if (seqno < state_->get_block_id().seqno()) {
|
||||
if (!state_->check_old_mc_block_id(it->second)) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad old masterchain block id"));
|
||||
return;
|
||||
}
|
||||
auto handle = R.move_as_ok();
|
||||
CHECK(!handle->merge_before());
|
||||
if (handle->one_prev(true) != id) {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::abort_query,
|
||||
td::Status::Error(ErrorCode::protoviolation, "prev block mismatch"));
|
||||
} else {
|
||||
if (state_->get_block_id() != it->second) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad old masterchain block id"));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::checked_masterchain_proof, std::move(handle), std::move(data));
|
||||
});
|
||||
|
||||
run_check_proof_query(it->second, std::move(proof), manager_, td::Timestamp::in(2.0), std::move(P), state_,
|
||||
opts_->is_hardfork(it->second));
|
||||
}
|
||||
seqno++;
|
||||
it = masterchain_blocks_.find(seqno);
|
||||
if (it == masterchain_blocks_.end()) {
|
||||
checked_all_masterchain_blocks(seqno - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (seqno != state_->get_block_id().seqno() + 1) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "hole in masterchain seqno"));
|
||||
return;
|
||||
}
|
||||
auto it2 = blocks_.find(it->second);
|
||||
CHECK(it2 != blocks_.end());
|
||||
|
||||
auto R1 = package_->read(it2->second[0]);
|
||||
if (R1.is_error()) {
|
||||
abort_query(R1.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto proofR = create_proof(it->second, std::move(R1.move_as_ok().second));
|
||||
if (proofR.is_error()) {
|
||||
abort_query(proofR.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto R2 = package_->read(it2->second[1]);
|
||||
if (R2.is_error()) {
|
||||
abort_query(R2.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
if (sha256_bits256(R2.ok().second.as_slice()) != it->second.file_hash) {
|
||||
abort_query(td::Status::Error(ErrorCode::protoviolation, "bad block file hash"));
|
||||
return;
|
||||
}
|
||||
auto dataR = create_block(it->second, std::move(R2.move_as_ok().second));
|
||||
if (dataR.is_error()) {
|
||||
abort_query(dataR.move_as_error());
|
||||
return;
|
||||
}
|
||||
|
||||
auto proof = proofR.move_as_ok();
|
||||
auto data = dataR.move_as_ok();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), id = state_->get_block_id(),
|
||||
data](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::abort_query, R.move_as_error());
|
||||
return;
|
||||
}
|
||||
auto handle = R.move_as_ok();
|
||||
CHECK(!handle->merge_before());
|
||||
if (handle->one_prev(true) != id) {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::abort_query,
|
||||
td::Status::Error(ErrorCode::protoviolation, "prev block mismatch"));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::checked_masterchain_proof, std::move(handle), std::move(data));
|
||||
});
|
||||
|
||||
run_check_proof_query(it->second, std::move(proof), manager_, td::Timestamp::in(2.0), std::move(P), state_,
|
||||
opts_->is_hardfork(it->second));
|
||||
}
|
||||
|
||||
void ArchiveImporter::checked_masterchain_proof(BlockHandle handle, td::Ref<BlockData> data) {
|
||||
CHECK(data.not_null());
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::applied_masterchain_block, std::move(handle));
|
||||
|
@ -189,17 +197,16 @@ void ArchiveImporter::got_new_materchain_state(td::Ref<MasterchainState> state)
|
|||
}
|
||||
|
||||
void ArchiveImporter::checked_all_masterchain_blocks(BlockSeqno seqno) {
|
||||
max_shard_client_seqno_ = seqno;
|
||||
check_next_shard_client_seqno(shard_client_seqno_ + 1);
|
||||
}
|
||||
|
||||
void ArchiveImporter::check_next_shard_client_seqno(BlockSeqno seqno) {
|
||||
if (seqno > max_shard_client_seqno_) {
|
||||
if (seqno > state_->get_seqno()) {
|
||||
finish_query();
|
||||
return;
|
||||
}
|
||||
|
||||
if (seqno == max_shard_client_seqno_) {
|
||||
if (seqno == state_->get_seqno()) {
|
||||
got_masterchain_state(state_);
|
||||
} else {
|
||||
BlockIdExt b;
|
||||
|
@ -217,14 +224,13 @@ void ArchiveImporter::check_next_shard_client_seqno(BlockSeqno seqno) {
|
|||
void ArchiveImporter::got_masterchain_state(td::Ref<MasterchainState> state) {
|
||||
auto s = state->get_shards();
|
||||
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), seqno = state->get_block_id().seqno()](td::Result<td::Unit> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::abort_query, R.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::check_next_shard_client_seqno, seqno + 1);
|
||||
}
|
||||
});
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), seqno = state->get_seqno()](td::Result<td::Unit> R) {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::abort_query, R.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::checked_shard_client_seqno, seqno);
|
||||
}
|
||||
});
|
||||
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
|
@ -235,6 +241,12 @@ void ArchiveImporter::got_masterchain_state(td::Ref<MasterchainState> state) {
|
|||
}
|
||||
}
|
||||
|
||||
void ArchiveImporter::checked_shard_client_seqno(BlockSeqno seqno) {
|
||||
CHECK(shard_client_seqno_ + 1 == seqno);
|
||||
shard_client_seqno_++;
|
||||
check_next_shard_client_seqno(seqno + 1);
|
||||
}
|
||||
|
||||
void ArchiveImporter::apply_shard_block(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::Promise<td::Unit> promise) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
|
@ -253,9 +265,18 @@ void ArchiveImporter::apply_shard_block_cont1(BlockHandle handle, BlockIdExt mas
|
|||
return;
|
||||
}
|
||||
|
||||
if (handle->id().seqno() == 0) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise)](td::Result<td::Ref<ShardState>> R) mutable { promise.set_value(td::Unit()); });
|
||||
td::actor::create_actor<DownloadShardState>("downloadstate", handle->id(), masterchain_block_id, 2, manager_,
|
||||
td::Timestamp::in(3600), std::move(P))
|
||||
.release();
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = blocks_.find(handle->id());
|
||||
if (it == blocks_.end()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "no proof for shard block"));
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, PSTRING() << "no proof for shard block " << handle->id()));
|
||||
return;
|
||||
}
|
||||
TRY_RESULT_PROMISE(promise, data, package_->read(it->second[0]));
|
||||
|
@ -280,21 +301,21 @@ void ArchiveImporter::apply_shard_block_cont2(BlockHandle handle, BlockIdExt mas
|
|||
}
|
||||
CHECK(handle->id().seqno() > 0);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle, masterchain_block_id,
|
||||
promise = std::move(promise)](td::Result<td::Unit> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::apply_shard_block_cont3, std::move(handle),
|
||||
masterchain_block_id, std::move(promise));
|
||||
}
|
||||
});
|
||||
if (!handle->merge_before() && handle->one_prev(true).shard_full() == handle->id().shard_full()) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle, masterchain_block_id,
|
||||
promise = std::move(promise)](td::Result<td::Unit> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ArchiveImporter::apply_shard_block_cont3, std::move(handle),
|
||||
masterchain_block_id, std::move(promise));
|
||||
}
|
||||
});
|
||||
apply_shard_block(handle->one_prev(true), masterchain_block_id, std::move(P));
|
||||
} else {
|
||||
td::MultiPromise mp;
|
||||
auto ig = mp.init_guard();
|
||||
ig.add_promise(std::move(promise));
|
||||
ig.add_promise(std::move(P));
|
||||
check_shard_block_applied(handle->one_prev(true), ig.get_promise());
|
||||
if (handle->merge_before()) {
|
||||
check_shard_block_applied(handle->one_prev(false), ig.get_promise());
|
||||
|
@ -335,15 +356,12 @@ void ArchiveImporter::check_shard_block_applied(BlockIdExt block_id, td::Promise
|
|||
}
|
||||
|
||||
void ArchiveImporter::abort_query(td::Status error) {
|
||||
if (promise_) {
|
||||
promise_.set_error(std::move(error));
|
||||
td::unlink(path_).ensure();
|
||||
}
|
||||
stop();
|
||||
LOG(INFO) << error;
|
||||
finish_query();
|
||||
}
|
||||
void ArchiveImporter::finish_query() {
|
||||
if (promise_) {
|
||||
promise_.set_value(std::vector<BlockSeqno>(state_->get_block_id().seqno(), max_shard_client_seqno_));
|
||||
promise_.set_value(std::vector<BlockSeqno>{state_->get_seqno(), shard_client_seqno_});
|
||||
td::unlink(path_).ensure();
|
||||
}
|
||||
stop();
|
||||
|
|
|
@ -25,6 +25,7 @@ class ArchiveImporter : public td::actor::Actor {
|
|||
void checked_all_masterchain_blocks(BlockSeqno seqno);
|
||||
|
||||
void check_next_shard_client_seqno(BlockSeqno seqno);
|
||||
void checked_shard_client_seqno(BlockSeqno seqno);
|
||||
void got_masterchain_state(td::Ref<MasterchainState> state);
|
||||
void apply_shard_block(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise);
|
||||
void apply_shard_block_cont1(BlockHandle handle, BlockIdExt masterchain_block_id, td::Promise<td::Unit> promise);
|
||||
|
@ -36,7 +37,6 @@ class ArchiveImporter : public td::actor::Actor {
|
|||
std::string path_;
|
||||
td::Ref<MasterchainState> state_;
|
||||
BlockSeqno shard_client_seqno_;
|
||||
BlockSeqno max_shard_client_seqno_;
|
||||
|
||||
td::Ref<ValidatorManagerOptions> opts_;
|
||||
|
||||
|
|
|
@ -414,7 +414,8 @@ void ValidatorManagerMasterchainStarter::got_key_block_handle(BlockHandle handle
|
|||
|
||||
void ValidatorManagerMasterchainStarter::got_shard_block_id(BlockIdExt block_id) {
|
||||
client_block_id_ = block_id;
|
||||
finish();
|
||||
start_shard_client();
|
||||
return;
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<BlockIdExt>> R) {
|
||||
R.ensure();
|
||||
|
@ -436,7 +437,7 @@ void ValidatorManagerMasterchainStarter::got_hardforks(std::vector<BlockIdExt> v
|
|||
return;
|
||||
}
|
||||
}
|
||||
finish();
|
||||
start_shard_client();
|
||||
return;
|
||||
}
|
||||
if (h.size() > vec.size() + 1) {
|
||||
|
@ -565,13 +566,20 @@ void ValidatorManagerMasterchainStarter::truncated() {
|
|||
void ValidatorManagerMasterchainStarter::written_next() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::finish);
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::start_shard_client);
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::update_hardforks, opts_->get_hardforks(), std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::start_shard_client() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerMasterchainStarter::finish);
|
||||
});
|
||||
client_ = td::actor::create_actor<ShardClient>("shardclient", opts_, manager_, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerMasterchainStarter::finish() {
|
||||
client_ = td::actor::create_actor<ShardClient>("shardclient", opts_, manager_);
|
||||
promise_.set_value(
|
||||
ValidatorManagerInitResult{handle_, state_, std::move(client_), gc_handle_, gc_state_, last_key_block_handle_});
|
||||
stop();
|
||||
|
|
|
@ -105,6 +105,7 @@ class ValidatorManagerMasterchainStarter : public td::actor::Actor {
|
|||
void got_prev_key_block_handle(BlockHandle handle);
|
||||
void truncated();
|
||||
void written_next();
|
||||
void start_shard_client();
|
||||
void finish();
|
||||
|
||||
private:
|
||||
|
|
|
@ -1414,7 +1414,6 @@ void ValidatorManagerImpl::started(ValidatorManagerInitResult R) {
|
|||
gc_masterchain_state_ = std::move(R.gc_state);
|
||||
|
||||
shard_client_ = std::move(R.clients);
|
||||
td::actor::send_closure(shard_client_, &ShardClient::start);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<ValidatorSessionId>> R) {
|
||||
if (R.is_error()) {
|
||||
|
@ -1429,8 +1428,6 @@ void ValidatorManagerImpl::started(ValidatorManagerInitResult R) {
|
|||
});
|
||||
|
||||
td::actor::send_closure(db_, &Db::get_destroyed_validator_sessions, std::move(P));
|
||||
|
||||
send_peek_key_block_request();
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::read_gc_list(std::vector<ValidatorSessionId> list) {
|
||||
|
@ -1443,6 +1440,104 @@ 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 (!out_of_sync()) {
|
||||
completed_prestart_sync();
|
||||
} else {
|
||||
prestart_sync();
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidatorManagerImpl::out_of_sync() {
|
||||
if (last_masterchain_block_handle_->unix_time() + 600 > td::Clocks::system()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (validator_groups_.size() > 0 && last_known_key_block_handle_->id().seqno() <= last_masterchain_seqno_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::prestart_sync() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive);
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::set_async_mode, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::download_next_archive() {
|
||||
if (!out_of_sync()) {
|
||||
finish_prestart_sync();
|
||||
return;
|
||||
}
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::string> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(INFO) << "failed to download archive slice: " << R.error();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive);
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::downloaded_archive_slice, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
callback_->download_archive(shard_client_handle_->id().seqno() + 1, db_root_ + "/tmp/", td::Timestamp::in(3600.0),
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::downloaded_archive_slice(std::string name) {
|
||||
LOG(INFO) << "downloaded archive slice: " << name;
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<BlockSeqno>> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(INFO) << "failed to check downloaded archive slice: " << R.error();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive);
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::checked_archive_slice, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::create_actor<ArchiveImporter>("archiveimport", name, last_masterchain_state_,
|
||||
shard_client_handle_->id().seqno(), opts_, actor_id(this), std::move(P))
|
||||
.release();
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::checked_archive_slice(std::vector<BlockSeqno> seqno) {
|
||||
CHECK(seqno.size() == 2);
|
||||
LOG(INFO) << "checked downloaded archive slice: mc_top_seqno=" << seqno[0] << " shard_top_seqno_=" << seqno[1];
|
||||
CHECK(seqno[0] <= last_masterchain_seqno_);
|
||||
|
||||
BlockIdExt b;
|
||||
CHECK(last_masterchain_state_->get_old_mc_block_id(seqno[1], b));
|
||||
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), db = db_.get(), client = shard_client_.get()](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
auto handle = R.move_as_ok();
|
||||
auto P = td::PromiseCreator::lambda([SelfId, client, handle](td::Result<td::Ref<ShardState>> R) mutable {
|
||||
auto P = td::PromiseCreator::lambda([SelfId](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::download_next_archive);
|
||||
});
|
||||
td::actor::send_closure(client, &ShardClient::force_update_shard_client_ex, std::move(handle),
|
||||
td::Ref<MasterchainState>{R.move_as_ok()}, std::move(P));
|
||||
});
|
||||
td::actor::send_closure(db, &Db::get_block_state, std::move(handle), std::move(P));
|
||||
});
|
||||
get_block_handle(b, true, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::finish_prestart_sync() {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::completed_prestart_sync);
|
||||
});
|
||||
td::actor::send_closure(db_, &Db::set_async_mode, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::completed_prestart_sync() {
|
||||
td::actor::send_closure(shard_client_, &ShardClient::start);
|
||||
|
||||
send_peek_key_block_request();
|
||||
|
||||
LOG(WARNING) << "initial read complete: " << last_masterchain_block_handle_->id() << " "
|
||||
<< last_masterchain_block_id_;
|
||||
callback_->initial_read_complete(last_masterchain_block_handle_);
|
||||
|
@ -1979,11 +2074,6 @@ void ValidatorManagerImpl::alarm() {
|
|||
}
|
||||
log_status_at_ = td::Timestamp::in(60.0);
|
||||
}
|
||||
if (false && !downloading_archive_slice_ && shard_client_handle_ &&
|
||||
shard_client_handle_->unix_time() + 600 <= td::Clocks::system() && next_download_archive_slice_at_.is_in_past()) {
|
||||
next_download_archive_slice_at_ = td::Timestamp::in(10.0);
|
||||
try_download_archive_slice();
|
||||
}
|
||||
alarm_timestamp().relax(log_status_at_);
|
||||
if (resend_shard_blocks_at_ && resend_shard_blocks_at_.is_in_past()) {
|
||||
resend_shard_blocks_at_ = td::Timestamp::never();
|
||||
|
@ -2053,49 +2143,6 @@ void ValidatorManagerImpl::try_get_static_file(FileHash file_hash, td::Promise<t
|
|||
td::actor::send_closure(db_, &Db::try_get_static_file, file_hash, std::move(promise));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::try_download_archive_slice() {
|
||||
CHECK(shard_client_handle_);
|
||||
downloading_archive_slice_ = true;
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::string> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(INFO) << "failed to download archive slice: " << R.error();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::failed_to_download_archive_slice);
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::downloaded_archive_slice, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
callback_->download_archive(shard_client_handle_->id().seqno(), db_root_ + "/tmp/", td::Timestamp::in(3600.0),
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::failed_to_download_archive_slice() {
|
||||
downloading_archive_slice_ = false;
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::downloaded_archive_slice(std::string name) {
|
||||
LOG(INFO) << "downloaded archive slice: " << name;
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<std::vector<BlockSeqno>> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(INFO) << "failed to check downloaded archive slice: " << R.error();
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::failed_to_download_archive_slice);
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &ValidatorManagerImpl::checked_archive_slice, R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::create_actor<ArchiveImporter>("archiveimport", name, last_masterchain_state_,
|
||||
shard_client_handle_->id().seqno(), opts_, actor_id(this), std::move(P))
|
||||
.release();
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::checked_archive_slice(std::vector<BlockSeqno> seqno) {
|
||||
CHECK(seqno.size() == 2);
|
||||
LOG(INFO) << "checked downloaded archive slice: mc_top_seqno=" << seqno[0] << " shard_top_seqno_=" << seqno[1];
|
||||
downloading_archive_slice_ = false;
|
||||
next_download_archive_slice_at_ = td::Timestamp::in(10.0);
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise) {
|
||||
td::actor::send_closure(db_, &Db::get_archive_id, masterchain_seqno, std::move(promise));
|
||||
}
|
||||
|
|
|
@ -261,6 +261,14 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void update_gc_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
void update_shard_client_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) override;
|
||||
|
||||
bool out_of_sync();
|
||||
void prestart_sync();
|
||||
void download_next_archive();
|
||||
void downloaded_archive_slice(std::string name);
|
||||
void checked_archive_slice(std::vector<BlockSeqno> seqno);
|
||||
void finish_prestart_sync();
|
||||
void completed_prestart_sync();
|
||||
|
||||
public:
|
||||
void install_callback(std::unique_ptr<Callback> new_callback, td::Promise<td::Unit> promise) override {
|
||||
callback_ = std::move(new_callback);
|
||||
|
@ -427,10 +435,6 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void get_async_serializer_state(td::Promise<AsyncSerializerState> promise) override;
|
||||
|
||||
void try_get_static_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) override;
|
||||
void try_download_archive_slice();
|
||||
void downloaded_archive_slice(std::string name);
|
||||
void checked_archive_slice(std::vector<BlockSeqno> seqno);
|
||||
void failed_to_download_archive_slice();
|
||||
|
||||
void get_download_token(size_t download_size, td::uint32 priority, td::Timestamp timeout,
|
||||
td::Promise<std::unique_ptr<DownloadToken>> promise) override {
|
||||
|
@ -558,9 +562,6 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
bool started_ = false;
|
||||
bool allow_validate_ = false;
|
||||
|
||||
bool downloading_archive_slice_ = false;
|
||||
td::Timestamp next_download_archive_slice_at_ = td::Timestamp::now();
|
||||
|
||||
private:
|
||||
double state_ttl() const {
|
||||
return opts_->state_ttl();
|
||||
|
|
|
@ -40,11 +40,9 @@ void ShardClient::start_up() {
|
|||
}
|
||||
|
||||
void ShardClient::start() {
|
||||
if (!started_ && masterchain_state_.not_null()) {
|
||||
started_ = true;
|
||||
apply_all_shards();
|
||||
} else {
|
||||
if (!started_) {
|
||||
started_ = true;
|
||||
saved_to_db();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +50,31 @@ void ShardClient::got_state_from_db(BlockIdExt state) {
|
|||
CHECK(!init_mode_);
|
||||
|
||||
CHECK(state.is_valid());
|
||||
new_masterchain_block_id(state);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<BlockHandle> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ShardClient::got_init_handle_from_db, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_block_handle, state, true, std::move(P));
|
||||
}
|
||||
|
||||
void ShardClient::got_init_handle_from_db(BlockHandle handle) {
|
||||
masterchain_block_handle_ = std::move(handle);
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Ref<ShardState>> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ShardClient::got_init_state_from_db, td::Ref<MasterchainState>{R.move_as_ok()});
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_state_from_db, masterchain_block_handle_,
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void ShardClient::got_init_state_from_db(td::Ref<MasterchainState> state) {
|
||||
masterchain_state_ = std::move(state);
|
||||
build_shard_overlays();
|
||||
masterchain_state_.clear();
|
||||
|
||||
saved_to_db();
|
||||
}
|
||||
|
||||
void ShardClient::start_up_init_mode() {
|
||||
|
@ -97,14 +119,19 @@ void ShardClient::applied_all_shards() {
|
|||
}
|
||||
|
||||
void ShardClient::saved_to_db() {
|
||||
if (init_mode_) {
|
||||
promise_.set_value(td::Unit());
|
||||
init_mode_ = false;
|
||||
}
|
||||
|
||||
CHECK(masterchain_block_handle_);
|
||||
td::actor::send_closure(manager_, &ValidatorManager::update_shard_client_block_handle, masterchain_block_handle_,
|
||||
[](td::Unit) {});
|
||||
if (promise_) {
|
||||
promise_.set_value(td::Unit());
|
||||
}
|
||||
if (init_mode_) {
|
||||
init_mode_ = false;
|
||||
}
|
||||
|
||||
if (!started_) {
|
||||
return;
|
||||
}
|
||||
if (masterchain_block_handle_->inited_next_left()) {
|
||||
new_masterchain_block_id(masterchain_block_handle_->one_next(true));
|
||||
} else {
|
||||
|
@ -239,6 +266,40 @@ void ShardClient::build_shard_overlays() {
|
|||
}
|
||||
}
|
||||
|
||||
void ShardClient::force_update_shard_client(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
CHECK(!init_mode_);
|
||||
CHECK(!started_);
|
||||
|
||||
if (masterchain_block_handle_->id().seqno() >= handle->id().seqno()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), handle, promise = std::move(promise)](td::Result<td::Ref<ShardState>> R) mutable {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &ShardClient::force_update_shard_client_ex, std::move(handle),
|
||||
td::Ref<MasterchainState>{R.move_as_ok()}, std::move(promise));
|
||||
});
|
||||
td::actor::send_closure(manager_, &ValidatorManager::get_shard_state_from_db, std::move(handle), std::move(P));
|
||||
}
|
||||
|
||||
void ShardClient::force_update_shard_client_ex(BlockHandle handle, td::Ref<MasterchainState> state,
|
||||
td::Promise<td::Unit> promise) {
|
||||
CHECK(!init_mode_);
|
||||
CHECK(!started_);
|
||||
|
||||
if (masterchain_block_handle_->id().seqno() >= handle->id().seqno()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
masterchain_block_handle_ = std::move(handle);
|
||||
masterchain_state_ = std::move(state);
|
||||
promise_ = std::move(promise);
|
||||
build_shard_overlays();
|
||||
applied_all_shards();
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -55,8 +55,9 @@ class ShardClient : public td::actor::Actor {
|
|||
, promise_(std::move(promise)) {
|
||||
init_mode_ = true;
|
||||
}
|
||||
ShardClient(td::Ref<ValidatorManagerOptions> opts, td::actor::ActorId<ValidatorManager> manager)
|
||||
: opts_(std::move(opts)), manager_(manager) {
|
||||
ShardClient(td::Ref<ValidatorManagerOptions> opts, td::actor::ActorId<ValidatorManager> manager,
|
||||
td::Promise<td::Unit> promise)
|
||||
: opts_(std::move(opts)), manager_(manager), promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
static constexpr td::uint32 shard_client_priority() {
|
||||
|
@ -70,6 +71,8 @@ class ShardClient : public td::actor::Actor {
|
|||
void start_up_init_mode_finished();
|
||||
void start();
|
||||
void got_state_from_db(BlockIdExt masterchain_block_id);
|
||||
void got_init_handle_from_db(BlockHandle handle);
|
||||
void got_init_state_from_db(td::Ref<MasterchainState> state);
|
||||
|
||||
void im_download_shard_state(BlockIdExt block_id, td::Promise<td::Unit> promise);
|
||||
void im_downloaded_zero_state(BlockIdExt block_id, td::BufferSlice data, td::Promise<td::Unit> promise);
|
||||
|
@ -91,6 +94,9 @@ class ShardClient : public td::actor::Actor {
|
|||
|
||||
void get_processed_masterchain_block(td::Promise<BlockSeqno> promise);
|
||||
void get_processed_masterchain_block_id(td::Promise<BlockIdExt> promise);
|
||||
|
||||
void force_update_shard_client(BlockHandle handle, td::Promise<td::Unit> promise);
|
||||
void force_update_shard_client_ex(BlockHandle handle, td::Ref<MasterchainState> state, td::Promise<td::Unit> promise);
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue