mirror of
https://github.com/danog/ton.git
synced 2024-11-26 12:04:48 +01:00
update tonlib
tonlib: update collator: increased collation speed for masterchain fift: bugfixes
This commit is contained in:
parent
7ea00ebfcf
commit
dd745485e2
@ -897,7 +897,7 @@ static int process_workchain_shard_hashes(Ref<vm::Cell>& branch, ton::ShardIdFul
|
||||
int f = (int)cs.fetch_ulong(1);
|
||||
if (f == 1) {
|
||||
if ((shard.shard & 1) || cs.size_ext() != 0x20000) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
auto left = cs.prefetch_ref(0), right = cs.prefetch_ref(1);
|
||||
int r = process_workchain_shard_hashes(left, ton::shard_child(shard, true), func);
|
||||
|
@ -1922,7 +1922,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
||||
if (--ptr > buff) {
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
} else {
|
||||
int mask = (-0x100 >> offs) & 0xff;
|
||||
int mask = (0xff00 >> offs) & 0xff;
|
||||
if (((unsigned char)v ^ s) & mask) {
|
||||
return false;
|
||||
}
|
||||
@ -1943,7 +1943,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
||||
if (--ptr > buff) {
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
} else {
|
||||
int mask = (-0x100 >> offs) & 0xff;
|
||||
int mask = (0xff00 >> offs) & 0xff;
|
||||
if (((unsigned char)v ^ s) & mask) {
|
||||
return false;
|
||||
}
|
||||
@ -1961,7 +1961,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
v >>= 8;
|
||||
}
|
||||
int mask = (-0x100 >> offs) & 0xff;
|
||||
int mask = (0xff00 >> offs) & 0xff;
|
||||
if (((unsigned char)v ^ s) & mask) {
|
||||
return false;
|
||||
}
|
||||
|
@ -132,9 +132,7 @@ int main(int argc, char* const argv[]) {
|
||||
|
||||
if (!no_env) {
|
||||
const char* path = std::getenv("FIFTPATH");
|
||||
if (path) {
|
||||
parse_include_path_set(path ? path : "/usr/lib/fift", source_include_path);
|
||||
}
|
||||
parse_include_path_set(path ? path : "/usr/lib/fift", source_include_path);
|
||||
}
|
||||
std::string current_dir;
|
||||
auto r_current_dir = td::realpath(".");
|
||||
|
@ -138,7 +138,7 @@ bool Op::set_var_info_except(const VarDescrList& new_var_info, const std::vector
|
||||
}
|
||||
VarDescrList tmp_info{new_var_info};
|
||||
tmp_info -= var_list;
|
||||
return set_var_info(new_var_info);
|
||||
return set_var_info(tmp_info);
|
||||
}
|
||||
|
||||
bool Op::set_var_info_except(VarDescrList&& new_var_info, const std::vector<var_idx_t>& var_list) {
|
||||
|
@ -31,8 +31,9 @@ serialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1)
|
||||
absent:(##(size * 8)) { roots + absent <= cells }
|
||||
tot_cells_size:(##(off_bytes * 8))
|
||||
root_list:(roots * ##(size * 8))
|
||||
index:(cells * ##(off_bytes * 8))
|
||||
index:has_idx?(cells * ##(off_bytes * 8))
|
||||
cell_data:(tot_cells_size * [ uint8 ])
|
||||
crc32c:has_crc32c?uint32
|
||||
= BagOfCells;
|
||||
|
||||
compiled_smart_contract
|
||||
|
@ -75,7 +75,7 @@ td::Result<int> CellSerializationInfo::get_bits(td::Slice cell) const {
|
||||
if (data_with_bits) {
|
||||
DCHECK(data_len != 0);
|
||||
int last = cell[data_offset + data_len - 1];
|
||||
if (!last || last == 0x80) {
|
||||
if (!(last & 0x7f)) {
|
||||
return td::Status::Error("overlong encoding");
|
||||
}
|
||||
return td::narrow_cast<int>((data_len - 1) * 8 + 7 - td::count_trailing_zeroes_non_zero32(last));
|
||||
@ -391,15 +391,6 @@ td::uint64 BagOfCells::compute_sizes(int mode, int& r_size, int& o_size) {
|
||||
r_size = o_size = 0;
|
||||
return 0;
|
||||
}
|
||||
if (!(mode & Mode::WithIndex)) {
|
||||
if (rs > 2 || os > 4) {
|
||||
rs = std::max(3, rs);
|
||||
os = 8;
|
||||
data_bytes_adj = data_bytes + (unsigned long long)int_refs * rs + hashes;
|
||||
} else {
|
||||
os = 4;
|
||||
}
|
||||
}
|
||||
r_size = rs;
|
||||
o_size = os;
|
||||
return data_bytes_adj;
|
||||
|
@ -527,9 +527,6 @@ int CellBuilder::serialize(unsigned char* buff, int buff_size) const {
|
||||
|
||||
CellBuilder* CellBuilder::make_copy() const {
|
||||
CellBuilder* c = new CellBuilder();
|
||||
if (!c) {
|
||||
throw CellWriteError();
|
||||
}
|
||||
c->bits = bits;
|
||||
std::memcpy(c->data, data, (bits + 7) >> 3);
|
||||
c->refs_cnt = refs_cnt;
|
||||
|
@ -2000,36 +2000,46 @@ In addition to the values listed in~\ptref{sp:boc.ser.class}, fixed by the choic
|
||||
\end{itemize}
|
||||
|
||||
\nxsubpoint\label{sp:boc.ser.sch}\emb{TL-B scheme for serializing bags of cells}
|
||||
Several TL-B constructors can be used to serialize bags of cells into octet (i.e., 8-bit byte) sequences:
|
||||
Several TL-B constructors can be used to serialize bags of cells into octet (i.e., 8-bit byte) sequences. The only one that is currently used to serialize new bags of cell is
|
||||
\begin{verbatim}
|
||||
serialized_boc_tiny cells:uint8 roots:uint8 absent:uint8
|
||||
tot_cells_size:(## 32) cell_data:(tot_cells_size * [ uint8 ])
|
||||
= BagOfCells;
|
||||
serialized_boc_small cells:uint16 roots:uint16 absent:uint16
|
||||
tot_cells_size:(## 32) cell_data:(tot_cells_size * [ uint8 ])
|
||||
= BagOfCells;
|
||||
serialized_boc_medium cells:uint24 roots:uint24 absent:uint24
|
||||
tot_cells_size:(## 64) cell_data:(tot_cells_size * [ uint8 ])
|
||||
= BagOfCells;
|
||||
serialized_boc_large cells:uint32 roots:uint32 absent:uint32
|
||||
tot_cells_size:(## 64) cell_data:(tot_cells_size * [ uint8 ])
|
||||
= BagOfCells;
|
||||
\end{verbatim}
|
||||
Field {\tt cells} is $n$, {\tt roots} is $k$, {\tt absent} is $l$, and {\tt tot\_cells\_size} is $L_n$ (the total size of the serialization of all cells in bytes).
|
||||
|
||||
If an index is present, parameters $s/8$ and $t/8$ are serialized separately as 8-bit fields {\tt size} and {\tt off\_bytes}, respectively:
|
||||
\begin{verbatim}
|
||||
serialized_boc_idx size:(## 8) { size <= 4 }
|
||||
serialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1)
|
||||
has_cache_bits:(## 1) flags:(## 2) { flags = 0 }
|
||||
size:(## 3) { size <= 4 }
|
||||
off_bytes:(## 8) { off_bytes <= 8 }
|
||||
cells:(##(size * 8))
|
||||
roots:(##(size * 8))
|
||||
roots:(##(size * 8)) { roots >= 1 }
|
||||
absent:(##(size * 8)) { roots + absent <= cells }
|
||||
tot_cells_size:(##(off_bytes * 8))
|
||||
index:(cells * [ ##(off_bytes * 8) ])
|
||||
root_list:(roots * ##(size * 8))
|
||||
index:has_idx?(cells * ##(off_bytes * 8))
|
||||
cell_data:(tot_cells_size * [ uint8 ])
|
||||
crc32c:has_crc32c?uint32
|
||||
= BagOfCells;
|
||||
\end{verbatim}
|
||||
Finally, constructors {\tt serialized\_boc\_*\_crc32}, with the asterisk replaced by either {\tt tiny}, {\tt small}, {\tt medium}, {\tt large}, or {\tt idx}, are also introduced, with one extra field {\tt crc32c:uint32} added as the last field.
|
||||
Field {\tt cells} is $n$, {\tt roots} is $k$, {\tt absent} is $l$, and {\tt tot\_cells\_size} is $L_n$ (the total size of the serialization of all cells in bytes). If an index is present, parameters $s/8$ and $t/8$ are serialized separately as {\tt size} and {\tt off\_bytes}, respectively, and the flag {\tt has\_idx} is set. The index itself is contained in {\tt index}, present only if {\tt has\_idx} is set. The field {\tt root\_list} contains the (zero-based) indices of the root nodes of the bag of cells.
|
||||
|
||||
Two older constructors are still supported in the bag-of-cells deserialization functions:
|
||||
\begin{verbatim}
|
||||
serialized_boc_idx#68ff65f3 size:(## 8) { size <= 4 }
|
||||
off_bytes:(## 8) { off_bytes <= 8 }
|
||||
cells:(##(size * 8))
|
||||
roots:(##(size * 8)) { roots = 1 }
|
||||
absent:(##(size * 8)) { roots + absent <= cells }
|
||||
tot_cells_size:(##(off_bytes * 8))
|
||||
index:(cells * ##(off_bytes * 8))
|
||||
cell_data:(tot_cells_size * [ uint8 ])
|
||||
= BagOfCells;
|
||||
|
||||
serialized_boc_idx_crc32c#acc3a728 size:(## 8) { size <= 4 }
|
||||
off_bytes:(## 8) { off_bytes <= 8 }
|
||||
cells:(##(size * 8))
|
||||
roots:(##(size * 8)) { roots = 1 }
|
||||
absent:(##(size * 8)) { roots + absent <= cells }
|
||||
tot_cells_size:(##(off_bytes * 8))
|
||||
index:(cells * ##(off_bytes * 8))
|
||||
cell_data:(tot_cells_size * [ uint8 ])
|
||||
crc32c:uint32 = BagOfCells;
|
||||
\end{verbatim}
|
||||
|
||||
\nxsubpoint\emb{Storing compiled TVM code in files}
|
||||
Notice that the above procedure for serializing bags of cells may be used to serialize compiled smart contracts and other TVM code. One must define a TL-B constructor similar to the following:
|
||||
|
@ -38,7 +38,7 @@ unpackedAccountAddress workchain_id:int32 bounceable:Bool testnet:Bool addr:byte
|
||||
internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
|
||||
|
||||
raw.initialAccountState code:bytes data:bytes = raw.InitialAccountState;
|
||||
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId sync_utime:int53 = raw.AccountState;
|
||||
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId frozen_hash:bytes sync_utime:int53 = raw.AccountState;
|
||||
raw.message source:string destination:string value:int64 fwd_fee:int64 ihr_fee:int64 created_lt:int64 body_hash:bytes message:bytes = raw.Message;
|
||||
raw.transaction utime:int53 data:bytes transaction_id:internal.transactionId fee:int64 storage_fee:int64 other_fee:int64 in_msg:raw.message out_msgs:vector<raw.message> = raw.Transaction;
|
||||
raw.transactions transactions:vector<raw.transaction> previous_transaction_id:internal.transactionId = raw.Transactions;
|
||||
@ -51,7 +51,7 @@ wallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.trans
|
||||
|
||||
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53= testGiver.AccountState;
|
||||
|
||||
uninited.accountState balance:int64 last_transaction_id:internal.transactionId sync_utime:int53 = uninited.AccountState;
|
||||
uninited.accountState balance:int64 last_transaction_id:internal.transactionId frozen_hash:bytes sync_utime:int53 = uninited.AccountState;
|
||||
|
||||
//generic.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState;
|
||||
//generic.initialAccountStateTestWallet initital_account_state:testWallet.initialAccountState = generic.InitialAccountState;
|
||||
|
Binary file not shown.
@ -434,9 +434,10 @@ TEST(Tonlib, KeysApi) {
|
||||
using tonlib_api::make_object;
|
||||
Client client;
|
||||
|
||||
td::mkdir("testdir").ignore();
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(
|
||||
make_object<tonlib_api::options>(nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("."))))
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("testdir"))))
|
||||
.ensure();
|
||||
auto local_password = td::SecureString("local password");
|
||||
auto mnemonic_password = td::SecureString("mnemonic password");
|
||||
|
@ -61,15 +61,14 @@ class ExtClient {
|
||||
auto raw_query = ton::serialize_tl_object(&query, true);
|
||||
td::uint32 tag = td::Random::fast_uint32();
|
||||
VLOG(lite_server) << "send query to liteserver: " << tag << " " << to_string(query);
|
||||
td::BufferSlice liteserver_query =
|
||||
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(raw_query)), true);
|
||||
|
||||
if (seq_no >= 0) {
|
||||
auto wait = ton::lite_api::liteServer_waitMasterchainSeqno(seq_no, 5000);
|
||||
VLOG(lite_server) << " with prefix " << to_string(wait);
|
||||
auto prefix = ton::serialize_tl_object(&wait, true);
|
||||
liteserver_query = td::BufferSlice(PSLICE() << prefix.as_slice() << liteserver_query.as_slice());
|
||||
raw_query = td::BufferSlice(PSLICE() << prefix.as_slice() << raw_query.as_slice());
|
||||
}
|
||||
td::BufferSlice liteserver_query =
|
||||
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(raw_query)), true);
|
||||
|
||||
send_raw_query(
|
||||
std::move(liteserver_query), [promise = std::move(promise), tag](td::Result<td::BufferSlice> R) mutable {
|
||||
|
@ -69,7 +69,7 @@ td::Result<DecryptedKey> KeyStorage::export_decrypted_key(InputKey input_key) {
|
||||
if (r_encrypted_data.is_error()) {
|
||||
r_encrypted_data = kv_->get(to_file_name_old(input_key.key));
|
||||
if (r_encrypted_data.is_ok()) {
|
||||
LOG(WARNING) << "Restore private from deprecated location " << to_file_name_old(input_key.key) << " --> "
|
||||
LOG(WARNING) << "Restore private key from deprecated location " << to_file_name_old(input_key.key) << " --> "
|
||||
<< to_file_name(input_key.key);
|
||||
TRY_STATUS_PREFIX(kv_->set(to_file_name(input_key.key), r_encrypted_data.ok()), TonlibError::Internal());
|
||||
kv_->erase(to_file_name_old(input_key.key)).ignore();
|
||||
@ -78,6 +78,21 @@ td::Result<DecryptedKey> KeyStorage::export_decrypted_key(InputKey input_key) {
|
||||
TRY_RESULT_PREFIX(encrypted_data, std::move(r_encrypted_data), TonlibError::KeyUnknown());
|
||||
EncryptedKey encrypted_key{std::move(encrypted_data), td::Ed25519::PublicKey(std::move(input_key.key.public_key)),
|
||||
std::move(input_key.key.secret)};
|
||||
{
|
||||
auto r_decrypted_key = encrypted_key.decrypt(input_key.local_password.copy(), true, true);
|
||||
if (r_decrypted_key.is_ok()) {
|
||||
LOG(WARNING) << "Restore private from deprecated encryption " << to_file_name(input_key.key);
|
||||
auto decrypted_key = r_decrypted_key.move_as_ok();
|
||||
auto key = Key{encrypted_key.public_key.as_octet_string(), encrypted_key.secret.copy()};
|
||||
auto new_encrypted_key = decrypted_key.encrypt(input_key.local_password.copy(), encrypted_key.secret);
|
||||
CHECK(new_encrypted_key.public_key.as_octet_string() == encrypted_key.public_key.as_octet_string());
|
||||
CHECK(new_encrypted_key.secret == encrypted_key.secret);
|
||||
CHECK(new_encrypted_key.decrypt(input_key.local_password.copy()).ok().private_key.as_octet_string() ==
|
||||
decrypted_key.private_key.as_octet_string());
|
||||
kv_->set(to_file_name(key), new_encrypted_key.encrypted_data);
|
||||
return std::move(decrypted_key);
|
||||
}
|
||||
}
|
||||
TRY_RESULT_PREFIX(decrypted_key, encrypted_key.decrypt(std::move(input_key.local_password)),
|
||||
TonlibError::KeyDecrypt());
|
||||
return std::move(decrypted_key);
|
||||
@ -139,14 +154,9 @@ td::Result<KeyStorage::ExportedPemKey> KeyStorage::export_pem_key(InputKey input
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::change_local_password(InputKey input_key, td::Slice new_local_password) {
|
||||
auto new_secret =
|
||||
DecryptedKey::change_local_password(input_key.key.secret, input_key.local_password, new_local_password);
|
||||
Key res;
|
||||
res.public_key = std::move(input_key.key.public_key);
|
||||
res.secret = std::move(new_secret);
|
||||
TRY_RESULT_PREFIX(value, kv_->get(to_file_name(input_key.key)), TonlibError::KeyUnknown());
|
||||
TRY_STATUS_PREFIX(kv_->add(to_file_name(res), value), TonlibError::Internal());
|
||||
return std::move(res);
|
||||
auto old_name = to_file_name(input_key.key);
|
||||
TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key)));
|
||||
return save_key(std::move(decrypted_key), new_local_password);
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::import_pem_key(td::Slice local_password, td::Slice key_password,
|
||||
|
@ -39,7 +39,7 @@ class KeyValueDir : public KeyValue {
|
||||
}
|
||||
|
||||
td::Status erase(td::Slice key) override {
|
||||
return td::unlink(key.str());
|
||||
return td::unlink(to_file_path(key.str()));
|
||||
}
|
||||
|
||||
void foreach_key(std::function<void(td::Slice)> f) override {
|
||||
|
@ -32,7 +32,8 @@ namespace tonlib {
|
||||
//
|
||||
td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state) {
|
||||
return sb << td::tag("last_block", state.last_block_id.to_str())
|
||||
<< td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime);
|
||||
<< td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime)
|
||||
<< td::tag("init_block", state.init_block_id.to_str());
|
||||
}
|
||||
|
||||
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr<Callback> callback)
|
||||
@ -40,8 +41,7 @@ LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, t
|
||||
client_.set_client(client);
|
||||
state_.last_block_id = state_.last_key_block_id;
|
||||
|
||||
VLOG(last_block) << "check_init_block: skip - FIXME before release";
|
||||
check_init_block_state_ = QueryState::Done;
|
||||
VLOG(last_block) << "State: " << state_;
|
||||
}
|
||||
|
||||
void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
|
||||
@ -87,7 +87,7 @@ void LastBlock::sync_loop() {
|
||||
} else {
|
||||
check_init_block_state_ = QueryState::Active;
|
||||
check_init_block_stats_.start();
|
||||
if (state_.last_block_id.id.seqno >= config_.init_block_id.id.seqno) {
|
||||
if (state_.last_key_block_id.id.seqno >= config_.init_block_id.id.seqno) {
|
||||
VLOG(last_block) << "check_init_block: start - init_block -> last_block";
|
||||
do_check_init_block(config_.init_block_id, state_.last_key_block_id);
|
||||
} else {
|
||||
@ -162,10 +162,18 @@ void LastBlock::update_state(block::BlockProofChain& chain) {
|
||||
update_utime(chain.last_utime);
|
||||
}
|
||||
if (is_changed) {
|
||||
callback_->on_state_changed(state_);
|
||||
save_state();
|
||||
}
|
||||
}
|
||||
|
||||
void LastBlock::save_state() {
|
||||
if (check_init_block_state_ != QueryState::Done) {
|
||||
VLOG(last_block) << "skip `save_state` because `check_init_block` is not finished";
|
||||
return;
|
||||
}
|
||||
callback_->on_state_changed(state_);
|
||||
}
|
||||
|
||||
void LastBlock::on_block_proof(
|
||||
ton::BlockIdExt from,
|
||||
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
|
||||
@ -209,6 +217,9 @@ void LastBlock::on_init_block_proof(
|
||||
if (chain->complete) {
|
||||
VLOG(last_block) << "check_init_block: done\n" << check_init_block_stats_;
|
||||
check_init_block_state_ = QueryState::Done;
|
||||
if (update_init_block(config_.init_block_id)) {
|
||||
save_state();
|
||||
}
|
||||
sync_loop();
|
||||
} else {
|
||||
do_check_init_block(chain->to, to);
|
||||
@ -291,6 +302,22 @@ bool LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LastBlock::update_init_block(ton::BlockIdExt init_block_id) {
|
||||
if (has_fatal_error()) {
|
||||
return false;
|
||||
}
|
||||
if (!init_block_id.is_valid()) {
|
||||
LOG(ERROR) << "Ignore invalid init block";
|
||||
return false;
|
||||
}
|
||||
if (state_.init_block_id != init_block_id) {
|
||||
state_.init_block_id = init_block_id;
|
||||
LOG(INFO) << "Update init block id: " << state_.init_block_id.to_str();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LastBlock::update_utime(td::int64 utime) {
|
||||
if (state_.utime < utime) {
|
||||
state_.utime = utime;
|
||||
|
@ -201,7 +201,9 @@ class LastBlock : public td::actor::Actor {
|
||||
bool update_mc_last_block(ton::BlockIdExt mc_block_id);
|
||||
bool update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
|
||||
void update_utime(td::int64 utime);
|
||||
bool update_init_block(ton::BlockIdExt init_block_id);
|
||||
|
||||
void save_state();
|
||||
void on_sync_ok();
|
||||
void on_sync_error(td::Status status);
|
||||
void on_fatal_error(td::Status status);
|
||||
|
@ -108,7 +108,6 @@ class GetTransactionHistory : public td::actor::Actor {
|
||||
|
||||
void check(td::Status status) {
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << status;
|
||||
promise_.set_error(std::move(status));
|
||||
stop();
|
||||
}
|
||||
@ -208,7 +207,7 @@ class GetRawAccountState : public td::actor::Actor {
|
||||
auto cell = res.info.root;
|
||||
std::ostringstream outp;
|
||||
block::gen::t_Account.print_ref(outp, cell);
|
||||
LOG(ERROR) << outp.str();
|
||||
LOG(INFO) << outp.str();
|
||||
if (cell.is_null()) {
|
||||
return res;
|
||||
}
|
||||
@ -682,8 +681,9 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_accountState>> to_raw_accountS
|
||||
.as_slice()
|
||||
.str();
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(
|
||||
raw_state.balance, std::move(code), std::move(data), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
|
||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(raw_state.balance, std::move(code), std::move(data),
|
||||
to_transaction_id(raw_state.info), raw_state.frozen_hash,
|
||||
raw_state.info.gen_utime);
|
||||
}
|
||||
|
||||
td::Result<std::string> to_std_address_or_throw(td::Ref<vm::CellSlice> cs) {
|
||||
@ -803,7 +803,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_transaction>> to_raw_transacti
|
||||
|
||||
std::ostringstream outp;
|
||||
block::gen::t_Transaction.print_ref(outp, info.transaction);
|
||||
LOG(ERROR) << outp.str();
|
||||
LOG(INFO) << outp.str();
|
||||
|
||||
auto is_just = trans.r1.in_msg->prefetch_long(1);
|
||||
if (is_just == trans.r1.in_msg->fetch_long_eof) {
|
||||
@ -917,7 +917,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_
|
||||
if (raw_state.code.is_null()) {
|
||||
return tonlib_api::make_object<tonlib_api::generic_accountStateUninited>(
|
||||
tonlib_api::make_object<tonlib_api::uninited_accountState>(raw_state.balance, to_transaction_id(raw_state.info),
|
||||
raw_state.info.gen_utime));
|
||||
raw_state.frozen_hash, raw_state.info.gen_utime));
|
||||
}
|
||||
|
||||
auto code_hash = raw_state.code->prefetch_ref()->get_hash();
|
||||
@ -953,7 +953,6 @@ td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request,
|
||||
client_.send_query(ton::lite_api::liteServer_sendMessage(vm::std_boc_serialize(message).move_as_ok()),
|
||||
[promise = std::move(promise)](auto r_info) mutable {
|
||||
TRY_RESULT_PROMISE(promise, info, std::move(r_info));
|
||||
LOG(ERROR) << "info: " << to_string(info);
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
});
|
||||
return td::Status::OK();
|
||||
@ -1042,7 +1041,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ
|
||||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||
auto address = GenericAccount::get_address(
|
||||
0 /*zerochain*/, TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
||||
@ -1116,7 +1114,6 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_sendGrams& request,
|
||||
TRY_RESULT_PREFIX(valid_until, td::narrow_cast_safe<td::uint32>(request.valid_until_),
|
||||
TonlibError::InvalidField("valid_until", "overflow"));
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||
auto address = GenericAccount::get_address(
|
||||
0 /*zerochain*/, Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
||||
@ -1168,7 +1165,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testGiver_sendGrams& reque
|
||||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
auto message = TestGiver::make_a_gift_message(request.seqno_, request.amount_, request.message_, account_address);
|
||||
auto message_hash = message->get_hash().as_slice().str();
|
||||
td::Promise<object_ptr<tonlib_api::ok>> new_promise =
|
||||
@ -1245,7 +1241,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||
block::StdAddress source_address_;
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::generic_AccountState> destination_state_;
|
||||
bool is_destination_bounce_{false};
|
||||
bool is_destination_bounceable_{false};
|
||||
|
||||
void check(td::Status status) {
|
||||
if (status.is_error()) {
|
||||
@ -1263,7 +1259,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||
return TonlibError::EmptyField("destination");
|
||||
}
|
||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
||||
is_destination_bounce_ = destination_address.bounceable;
|
||||
is_destination_bounceable_ = destination_address.bounceable;
|
||||
|
||||
if (!send_grams_.source_) {
|
||||
return TonlibError::EmptyField("destination");
|
||||
@ -1333,9 +1329,23 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||
td::Status do_on_destination_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> r_state) {
|
||||
TRY_RESULT(state, std::move(r_state));
|
||||
destination_state_ = std::move(state);
|
||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounce_ &&
|
||||
!send_grams_.allow_send_to_uninited_) {
|
||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounceable_) {
|
||||
//FIXME: after restoration of frozen accounts will be supported
|
||||
if (!static_cast<tonlib_api::generic_accountStateUninited&>(*destination_state_)
|
||||
.account_state_->frozen_hash_.empty()) {
|
||||
return TonlibError::TransferToFrozen();
|
||||
//return TonlibError::DangerousTransaction("Transfer to frozen wallet");
|
||||
}
|
||||
if (send_grams_.allow_send_to_uninited_) {
|
||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
||||
destination_address.bounceable = false;
|
||||
auto new_destination_address = destination_address.rserialize(true);
|
||||
LOG(INFO) << "Change destination address from bounceable to non-bounceable "
|
||||
<< send_grams_.destination_->account_address_ << " -> " << new_destination_address;
|
||||
send_grams_.destination_->account_address_ = std::move(new_destination_address);
|
||||
} else {
|
||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
||||
}
|
||||
}
|
||||
return do_loop();
|
||||
}
|
||||
|
@ -128,6 +128,9 @@ struct TonlibError {
|
||||
static td::Status NotEnoughFunds() {
|
||||
return td::Status::Error(500, "NOT_ENOUGH_FUNDS");
|
||||
}
|
||||
static td::Status TransferToFrozen() {
|
||||
return td::Status::Error(500, "TRANSFER_TO_FROZEN");
|
||||
}
|
||||
|
||||
static td::Status LiteServer(td::int32 code, td::Slice message) {
|
||||
auto f = [&](td::Slice code_description) { return LiteServer(code, code_description, message); };
|
||||
|
@ -35,36 +35,15 @@ DecryptedKey::DecryptedKey(RawDecryptedKey key)
|
||||
: DecryptedKey(std::move(key.mnemonic_words), td::Ed25519::PrivateKey(key.private_key.copy())) {
|
||||
}
|
||||
|
||||
td::SecureString DecryptedKey::change_local_password(td::Slice secret_str, td::Slice old_local_password,
|
||||
td::Slice new_local_password) {
|
||||
CHECK(secret_str.size() == 32);
|
||||
td::SecureString old_local_password_hash(32);
|
||||
sha256(old_local_password, old_local_password_hash.as_mutable_slice());
|
||||
td::SecureString new_local_password_hash(32);
|
||||
sha256(new_local_password, new_local_password_hash.as_mutable_slice());
|
||||
|
||||
td::SecureString new_secret(32);
|
||||
for (size_t i = 0; i < new_secret.size(); i++) {
|
||||
new_secret.as_mutable_slice()[i] =
|
||||
secret_str[i] ^ old_local_password_hash.as_slice()[i] ^ new_local_password_hash.as_slice()[i];
|
||||
}
|
||||
return new_secret;
|
||||
}
|
||||
|
||||
EncryptedKey DecryptedKey::encrypt(td::Slice local_password, td::Slice old_secret) const {
|
||||
LOG(ERROR) << "encrypt";
|
||||
td::SecureString secret(32);
|
||||
if (old_secret.size() == td::as_slice(secret).size()) {
|
||||
secret.as_mutable_slice().copy_from(old_secret);
|
||||
} else {
|
||||
td::Random::secure_bytes(secret.as_mutable_slice());
|
||||
}
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
td::SecureString decrypted_secret(32);
|
||||
for (size_t i = 0; i < decrypted_secret.size(); i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS,
|
||||
|
@ -56,8 +56,6 @@ struct DecryptedKey {
|
||||
std::vector<td::SecureString> mnemonic_words;
|
||||
td::Ed25519::PrivateKey private_key;
|
||||
|
||||
static td::SecureString change_local_password(td::Slice secret, td::Slice old_local_password,
|
||||
td::Slice new_local_password);
|
||||
EncryptedKey encrypt(td::Slice local_password, td::Slice secret = {}) const;
|
||||
};
|
||||
|
||||
|
@ -24,15 +24,19 @@
|
||||
#include "td/utils/crypto.h"
|
||||
|
||||
namespace tonlib {
|
||||
td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool check_public_key) {
|
||||
td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool check_public_key, bool old) const {
|
||||
if (secret.size() != 32) {
|
||||
return td::Status::Error("Failed to decrypt key: invalid secret size");
|
||||
}
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
td::SecureString decrypted_secret(32);
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
if (old) {
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
} else {
|
||||
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||
}
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
|
@ -32,7 +32,7 @@ struct EncryptedKey {
|
||||
td::Ed25519::PublicKey public_key;
|
||||
td::SecureString secret;
|
||||
|
||||
td::Result<DecryptedKey> decrypt(td::Slice local_password, bool check_public_key = true);
|
||||
td::Result<DecryptedKey> decrypt(td::Slice local_password, bool check_public_key = true, bool old = false) const;
|
||||
};
|
||||
|
||||
} // namespace tonlib
|
||||
|
@ -186,11 +186,21 @@ class TonlibCli : public td::actor::Actor {
|
||||
if (cmd.empty()) {
|
||||
return;
|
||||
}
|
||||
auto to_bool = [](td::Slice word, bool def = false) {
|
||||
if (word.empty()) {
|
||||
return def;
|
||||
}
|
||||
if (word == "0" || word == "FALSE" || word == "false") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (cmd == "help") {
|
||||
td::TerminalIO::out() << "help - show this help\n";
|
||||
td::TerminalIO::out() << "genkey - generate new secret key\n";
|
||||
td::TerminalIO::out() << "keys - show all stored keys\n";
|
||||
td::TerminalIO::out() << "unpackaddress <address> - validate and parse address\n";
|
||||
td::TerminalIO::out() << "setbounceble <address> [<bounceble>] - change bounceble flag in address\n";
|
||||
td::TerminalIO::out() << "importkey - import key\n";
|
||||
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
|
||||
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
|
||||
@ -214,6 +224,8 @@ class TonlibCli : public td::actor::Actor {
|
||||
try_stop();
|
||||
} else if (cmd == "keys") {
|
||||
dump_keys();
|
||||
} else if (cmd == "deletekey") {
|
||||
//delete_key(parser.read_word());
|
||||
} else if (cmd == "deletekeys") {
|
||||
delete_all_keys();
|
||||
} else if (cmd == "exportkey") {
|
||||
@ -223,15 +235,6 @@ class TonlibCli : public td::actor::Actor {
|
||||
} else if (cmd == "setconfig") {
|
||||
auto config = parser.read_word();
|
||||
auto name = parser.read_word();
|
||||
auto to_bool = [](td::Slice word) {
|
||||
if (word.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (word == "0" || word == "FALSE" || word == "false") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto use_callback = parser.read_word();
|
||||
auto force = parser.read_word();
|
||||
set_config(config, name, to_bool(use_callback), to_bool(force));
|
||||
@ -251,6 +254,10 @@ class TonlibCli : public td::actor::Actor {
|
||||
get_hints(parser.read_word());
|
||||
} else if (cmd == "unpackaddress") {
|
||||
unpack_address(parser.read_word());
|
||||
} else if (cmd == "setbounceable") {
|
||||
auto addr = parser.read_word();
|
||||
auto bounceable = parser.read_word();
|
||||
set_bounceable(addr, to_bool(bounceable, true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,6 +332,26 @@ class TonlibCli : public td::actor::Actor {
|
||||
});
|
||||
}
|
||||
|
||||
void set_bounceable(td::Slice addr, bool bounceable) {
|
||||
send_query(tonlib_api::make_object<tonlib_api::unpackAccountAddress>(addr.str()),
|
||||
[addr = addr.str(), bounceable, this](auto r_parsed_addr) mutable {
|
||||
if (r_parsed_addr.is_error()) {
|
||||
LOG(ERROR) << "Failed to parse address: " << r_parsed_addr.error();
|
||||
return;
|
||||
}
|
||||
auto parsed_addr = r_parsed_addr.move_as_ok();
|
||||
parsed_addr->bounceable_ = bounceable;
|
||||
this->send_query(tonlib_api::make_object<tonlib_api::packAccountAddress>(std::move(parsed_addr)),
|
||||
[](auto r_addr) mutable {
|
||||
if (r_addr.is_error()) {
|
||||
LOG(ERROR) << "Failed to pack address";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << r_addr.ok()->account_address_ << "\n";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void generate_key(td::SecureString entropy = {}) {
|
||||
if (entropy.size() < 20) {
|
||||
td::TerminalIO::out() << "Enter some entropy";
|
||||
@ -527,6 +554,25 @@ class TonlibCli : public td::actor::Actor {
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
void delete_key(td::Slice key) {
|
||||
auto r_key_i = to_key_i(key);
|
||||
if (r_key_i.is_error()) {
|
||||
td::TerminalIO::out() << "Unknown key id: [" << key << "]\n";
|
||||
return;
|
||||
}
|
||||
using tonlib_api::make_object;
|
||||
auto key_i = r_key_i.move_as_ok();
|
||||
send_query(make_object<tonlib_api::deleteKey>(
|
||||
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy())),
|
||||
|
||||
[key = key.str()](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't delete key id: [" << key << "] " << r_res.error() << "\n";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << "Ok\n";
|
||||
});
|
||||
}
|
||||
void export_key(td::Slice key) {
|
||||
if (key.empty()) {
|
||||
dump_keys();
|
||||
@ -754,6 +800,11 @@ class TonlibCli : public td::actor::Actor {
|
||||
}
|
||||
void transfer(Address from, Address to, td::uint64 grams, td::Slice password, td::Slice message,
|
||||
bool allow_send_to_uninited) {
|
||||
auto r_sz = td::to_integer_safe<td::size_t>(message);
|
||||
auto msg = message.str();
|
||||
if (r_sz.is_ok()) {
|
||||
msg = std::string(r_sz.ok(), 'Z');
|
||||
}
|
||||
using tonlib_api::make_object;
|
||||
auto key = !from.secret.empty()
|
||||
? make_object<tonlib_api::inputKey>(
|
||||
@ -761,7 +812,7 @@ class TonlibCli : public td::actor::Actor {
|
||||
: nullptr;
|
||||
send_query(
|
||||
make_object<tonlib_api::generic_sendGrams>(std::move(key), std::move(from.address), std::move(to.address),
|
||||
grams, 30, allow_send_to_uninited, message.str()),
|
||||
grams, 60, allow_send_to_uninited, std::move(msg)),
|
||||
[this](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n";
|
||||
@ -881,6 +932,10 @@ int main(int argc, char* argv[]) {
|
||||
options.config = std::move(data);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('N', "config-name", "set lite server config name", [&](td::Slice arg) {
|
||||
options.name = arg.str();
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('n', "use-callbacks-for-network", "do not use this", [&]() {
|
||||
options.use_callbacks_for_network = true;
|
||||
return td::Status::OK();
|
||||
|
@ -3099,7 +3099,8 @@ bool Collator::create_mc_state_extra() {
|
||||
CHECK(cb.store_long_bool(0x17, 8) && cb.append_cellslice_bool(block_create_stats_->get_root()));
|
||||
auto cs = vm::load_cell_slice_ref(cb.finalize());
|
||||
state_extra.r1.block_create_stats = cs;
|
||||
if (verify >= 1) {
|
||||
if (verify >= 2) {
|
||||
LOG(INFO) << "verifying new BlockCreateStats";
|
||||
if (!block::gen::t_BlockCreateStats.validate_csr(cs)) {
|
||||
cs->print_rec(std::cerr);
|
||||
block::gen::t_BlockCreateStats.print(std::cerr, *cs);
|
||||
@ -3154,10 +3155,12 @@ bool Collator::update_block_creator_count(td::ConstBitPtr key, unsigned shard_in
|
||||
int Collator::creator_count_outdated(td::ConstBitPtr key, vm::CellSlice& cs) {
|
||||
block::DiscountedCounter mc_cnt, shard_cnt;
|
||||
if (!(block::fetch_CreatorStats(cs, mc_cnt, shard_cnt) && cs.empty_ext())) {
|
||||
return fatal_error("cannot unpack CreatorStats for "s + key.to_hex(256) + " from previous masterchain state");
|
||||
fatal_error("cannot unpack CreatorStats for "s + key.to_hex(256) + " from previous masterchain state");
|
||||
return -1;
|
||||
}
|
||||
if (!(mc_cnt.increase_by(0, now_) && shard_cnt.increase_by(0, now_))) {
|
||||
return fatal_error("cannot amortize counters in CreatorStats for "s + key.to_hex(256));
|
||||
fatal_error("cannot amortize counters in CreatorStats for "s + key.to_hex(256));
|
||||
return -1;
|
||||
}
|
||||
if (!(mc_cnt.cnt65536 | shard_cnt.cnt65536)) {
|
||||
LOG(DEBUG) << "removing stale CreatorStats for " << key.to_hex(256);
|
||||
@ -3178,17 +3181,42 @@ bool Collator::update_block_creator_stats() {
|
||||
return fatal_error("cannot update CreatorStats for "s + p.first.to_hex());
|
||||
}
|
||||
}
|
||||
if (!created_by_.is_zero() && !update_block_creator_count(created_by_.as_bits256().bits(), 0, 1)) {
|
||||
auto has_creator = !created_by_.is_zero();
|
||||
if (has_creator && !update_block_creator_count(created_by_.as_bits256().bits(), 0, 1)) {
|
||||
return fatal_error("cannot update CreatorStats for "s + created_by_.as_bits256().to_hex());
|
||||
}
|
||||
if (!update_block_creator_count(td::Bits256::zero().bits(), block_create_total_, !created_by_.is_zero())) {
|
||||
if ((has_creator || block_create_total_) &&
|
||||
!update_block_creator_count(td::Bits256::zero().bits(), block_create_total_, has_creator)) {
|
||||
return fatal_error("cannot update CreatorStats with zero index (representing the sum of other CreatorStats)");
|
||||
}
|
||||
// -> DEBUG
|
||||
LOG(INFO) << "scanning for outdated CreatorStats entries";
|
||||
/*
|
||||
int cnt = block_create_stats_->filter([this](vm::CellSlice& cs, td::ConstBitPtr key, int key_len) {
|
||||
CHECK(key_len == 256);
|
||||
return creator_count_outdated(key, cs);
|
||||
});
|
||||
LOG(DEBUG) << "removed " << cnt << " stale CreatorStats entries";
|
||||
*/
|
||||
// alternative version with partial scan
|
||||
td::Bits256 key;
|
||||
prng::rand_gen().rand_bytes(key.data(), 32);
|
||||
int scanned, cnt = 0;
|
||||
for (scanned = 0; scanned < 100; scanned++) {
|
||||
auto cs = block_create_stats_->lookup_nearest_key(key.bits(), 256, true);
|
||||
if (cs.is_null()) {
|
||||
break;
|
||||
}
|
||||
auto res = creator_count_outdated(key.bits(), cs.write());
|
||||
if (!res) {
|
||||
LOG(DEBUG) << "prunning CreatorStats for " << key.to_hex();
|
||||
block_create_stats_->lookup_delete(key);
|
||||
++cnt;
|
||||
} else if (res < 0) {
|
||||
return fatal_error("error scanning stale CreatorStats entries");
|
||||
}
|
||||
}
|
||||
// -> DEBUG
|
||||
LOG(INFO) << "removed " << cnt << " stale CreatorStats entries out of " << scanned << " scanned";
|
||||
return cnt >= 0;
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ void LiteQuery::perform_getMasterchainInfo(int mode) {
|
||||
}
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[Self = actor_id(this), mode](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) {
|
||||
[ Self = actor_id(this), mode ](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -230,7 +230,7 @@ void LiteQuery::perform_getBlock(BlockIdExt blkid) {
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -256,7 +256,7 @@ void LiteQuery::perform_getBlockHeader(BlockIdExt blkid, int mode) {
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid, mode](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
[ Self = actor_id(this), blkid, mode ](td::Result<Ref<ton::validator::BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -371,7 +371,7 @@ void LiteQuery::perform_getState(BlockIdExt blkid) {
|
||||
}
|
||||
if (blkid.id.seqno) {
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ton::validator::ShardState>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ton::validator::ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -381,7 +381,7 @@ void LiteQuery::perform_getState(BlockIdExt blkid) {
|
||||
});
|
||||
} else {
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_zero_state, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<td::BufferSlice> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -440,7 +440,7 @@ bool LiteQuery::request_mc_block_data(BlockIdExt blkid) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<BlockData>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
||||
@ -466,7 +466,7 @@ bool LiteQuery::request_mc_proof(BlockIdExt blkid, int mode) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_proof_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid, mode](td::Result<Ref<Proof>> res) {
|
||||
[ Self = actor_id(this), blkid, mode ](td::Result<Ref<Proof>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load proof for "s + blkid.to_str() + " : "));
|
||||
@ -488,7 +488,7 @@ bool LiteQuery::request_mc_block_state(BlockIdExt blkid) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ShardState>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load state for "s + blkid.to_str() + " : "));
|
||||
@ -519,7 +519,7 @@ bool LiteQuery::request_block_state(BlockIdExt blkid) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ShardState>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load state for "s + blkid.to_str() + " : "));
|
||||
@ -541,7 +541,7 @@ bool LiteQuery::request_block_data(BlockIdExt blkid) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<BlockData>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<BlockData>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
||||
@ -563,7 +563,7 @@ bool LiteQuery::request_proof_link(BlockIdExt blkid) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_proof_link_from_db_short, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<Ref<ProofLink>> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<Ref<ProofLink>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load proof link for "s + blkid.to_str() + " : "));
|
||||
@ -588,7 +588,7 @@ bool LiteQuery::request_zero_state(BlockIdExt blkid) {
|
||||
++pending_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_zero_state, blkid,
|
||||
[Self = actor_id(this), blkid](td::Result<td::BufferSlice> res) {
|
||||
[ Self = actor_id(this), blkid ](td::Result<td::BufferSlice> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||
res.move_as_error_prefix("cannot load zerostate of "s + blkid.to_str() + " : "));
|
||||
@ -632,7 +632,7 @@ void LiteQuery::perform_getAccountState(BlockIdExt blkid, WorkchainId workchain,
|
||||
LOG(INFO) << "sending a get_top_masterchain_state_block query to manager";
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
||||
[Self = actor_id(this)](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res) -> void {
|
||||
[Self = actor_id(this)](td::Result<std::pair<Ref<ton::validator::MasterchainState>, BlockIdExt>> res)->void {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -1067,7 +1067,7 @@ void LiteQuery::continue_getTransactions(unsigned remaining, bool exact) {
|
||||
<< " " << trans_lt_;
|
||||
td::actor::send_closure_later(
|
||||
manager_, &ValidatorManager::get_block_by_lt_from_db, ton::extract_addr_prefix(acc_workchain_, acc_addr_),
|
||||
trans_lt_, [Self = actor_id(this), remaining, manager = manager_](td::Result<BlockIdExt> res) {
|
||||
trans_lt_, [ Self = actor_id(this), remaining, manager = manager_ ](td::Result<BlockIdExt> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, res.move_as_error(), ton::BlockIdExt{});
|
||||
} else {
|
||||
@ -1141,7 +1141,7 @@ void LiteQuery::perform_getShardInfo(BlockIdExt blkid, ShardIdFull shard, bool e
|
||||
void LiteQuery::perform_getConfigParams(BlockIdExt blkid, int mode, std::vector<int> param_list) {
|
||||
LOG(INFO) << "started a getConfigParams(" << blkid.to_str() << ", " << mode << ", <list of " << param_list.size()
|
||||
<< " parameters>) liteserver query";
|
||||
set_continuation([this, mode, param_list = std::move(param_list)]() mutable {
|
||||
set_continuation([ this, mode, param_list = std::move(param_list) ]() mutable {
|
||||
continue_getConfigParams(mode, std::move(param_list));
|
||||
});
|
||||
request_mc_block_data_state(blkid);
|
||||
@ -1294,7 +1294,7 @@ void LiteQuery::perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, Uni
|
||||
LOG(INFO) << "performing a lookupBlock(" << blkid.to_str() << ", " << mode << ", " << lt << ", " << utime
|
||||
<< ") query";
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[Self = actor_id(this), manager = manager_, mode = (mode >> 4)](td::Result<BlockIdExt> res) {
|
||||
[ Self = actor_id(this), manager = manager_, mode = (mode >> 4) ](td::Result<BlockIdExt> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
@ -1446,58 +1446,83 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
||||
return;
|
||||
}
|
||||
if (mode & 1) {
|
||||
base_blk_id_ = (from.seqno() > to.seqno()) ? from : to;
|
||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, base_blk_id_,
|
||||
[Self = actor_id(this), from, to, mode](td::Result<Ref<ShardState>> res) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, to,
|
||||
mode, Ref<MasterchainStateQ>(res.move_as_ok()));
|
||||
}
|
||||
});
|
||||
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) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from,
|
||||
to, mode, bblk,
|
||||
Ref<MasterchainStateQ>(res.move_as_ok()));
|
||||
}
|
||||
});
|
||||
} 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) {
|
||||
if (res.is_error()) {
|
||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||
} else {
|
||||
auto pair = res.move_as_ok();
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, to, mode, pair.second,
|
||||
Ref<MasterchainStateQ>(std::move(pair.first)));
|
||||
}
|
||||
});
|
||||
}
|
||||
} 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 {
|
||||
auto pair = res.move_as_ok();
|
||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, pair.second, mode,
|
||||
Ref<MasterchainStateQ>(std::move(pair.first)));
|
||||
pair.second, Ref<MasterchainStateQ>(std::move(pair.first)));
|
||||
}
|
||||
});
|
||||
} 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 {
|
||||
td::actor::send_closure_later(Self, &LiteQuery::perform_getBlockProof, from,
|
||||
res.move_as_ok(), mode | 1);
|
||||
res.move_as_ok(), mode | 0x1001);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void LiteQuery::continue_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode,
|
||||
void LiteQuery::continue_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode, BlockIdExt baseblk,
|
||||
Ref<MasterchainStateQ> state) {
|
||||
base_blk_id_ = baseblk;
|
||||
if (!base_blk_id_.is_masterchain_ext()) {
|
||||
fatal_error("reference masterchain block "s + base_blk_id_.to_str() + " for constructing a proof chain is invalid");
|
||||
return;
|
||||
}
|
||||
if (!(mode & 1)) {
|
||||
base_blk_id_ = to;
|
||||
if (!to.is_masterchain_ext()) {
|
||||
fatal_error("last masterchain block id "s + to.to_str() + " is invalid");
|
||||
return;
|
||||
}
|
||||
if (from.seqno() > to.seqno()) {
|
||||
fatal_error("client knows block "s + from.to_str() + " newer than the latest masterchain block " + to.to_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (state.is_null()) {
|
||||
fatal_error("obtained no valid masterchain state for block "s + base_blk_id_.to_str());
|
||||
return;
|
||||
}
|
||||
if (from.seqno() > base_blk_id_.seqno()) {
|
||||
fatal_error("client knows block "s + from.to_str() + " newer than the reference masterchain block " +
|
||||
base_blk_id_.to_str());
|
||||
return;
|
||||
}
|
||||
if (to.seqno() > base_blk_id_.seqno()) {
|
||||
fatal_error("client knows block "s + to.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()) {
|
||||
fatal_error("the state for "s + base_blk_id_.to_str() + " is in fact a state for different block " +
|
||||
@ -1507,13 +1532,13 @@ void LiteQuery::continue_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
||||
LOG(INFO) << "continuing getBlockProof(" << mode << ", " << from.to_str() << ", " << to.to_str()
|
||||
<< ") query with a state for " << base_blk_id_.to_str();
|
||||
if (!state->check_old_mc_block_id(from)) {
|
||||
fatal_error("source masterchain block "s + from.to_str() + " is unknown from the perspective of newer block " +
|
||||
base_blk_id_.to_str());
|
||||
fatal_error("proof source masterchain block "s + from.to_str() +
|
||||
" is unknown from the perspective of reference block " + base_blk_id_.to_str());
|
||||
return;
|
||||
}
|
||||
if (!state->check_old_mc_block_id(to)) {
|
||||
fatal_error("destination masterchain block "s + to.to_str() + " is unknown from the perspective of newer block " +
|
||||
base_blk_id_.to_str());
|
||||
fatal_error("proof destination masterchain block "s + to.to_str() +
|
||||
" is unknown from the perspective of reference block " + base_blk_id_.to_str());
|
||||
return;
|
||||
}
|
||||
chain_ = std::make_unique<block::BlockProofChain>(from, to, mode);
|
||||
|
@ -111,9 +111,10 @@ class LiteQuery : public td::actor::Actor {
|
||||
void perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime);
|
||||
void perform_listBlockTransactions(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
||||
void finish_listBlockTransactions(int mode, int count);
|
||||
void perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode);
|
||||
void continue_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode, Ref<MasterchainStateQ> state);
|
||||
bool construct_proof_chain(ton::BlockIdExt id);
|
||||
void perform_getBlockProof(BlockIdExt from, BlockIdExt to, int mode);
|
||||
void continue_getBlockProof(BlockIdExt from, BlockIdExt to, int mode, BlockIdExt baseblk,
|
||||
Ref<MasterchainStateQ> state);
|
||||
bool construct_proof_chain(BlockIdExt id);
|
||||
bool construct_proof_link_forward(ton::BlockIdExt cur, ton::BlockIdExt next);
|
||||
bool construct_proof_link_forward_cont(ton::BlockIdExt cur, ton::BlockIdExt next);
|
||||
bool construct_proof_link_back(ton::BlockIdExt cur, ton::BlockIdExt next);
|
||||
|
@ -1880,10 +1880,12 @@ void ValidatorManagerImpl::update_shard_client_block_handle(BlockHandle handle,
|
||||
void ValidatorManagerImpl::shard_client_update(BlockSeqno seqno) {
|
||||
if (min_confirmed_masterchain_seqno_ < seqno) {
|
||||
min_confirmed_masterchain_seqno_ = seqno;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
while (shard_client_waiters_.size() > 0) {
|
||||
auto it = shard_client_waiters_.begin();
|
||||
if (it->first > seqno) {
|
||||
if (it->first > min_confirmed_masterchain_seqno_) {
|
||||
break;
|
||||
}
|
||||
for (auto &y : it->second.waiting_) {
|
||||
|
Loading…
Reference in New Issue
Block a user