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);
|
int f = (int)cs.fetch_ulong(1);
|
||||||
if (f == 1) {
|
if (f == 1) {
|
||||||
if ((shard.shard & 1) || cs.size_ext() != 0x20000) {
|
if ((shard.shard & 1) || cs.size_ext() != 0x20000) {
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
auto left = cs.prefetch_ref(0), right = cs.prefetch_ref(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);
|
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) {
|
if (--ptr > buff) {
|
||||||
*ptr = (unsigned char)(v & 0xff);
|
*ptr = (unsigned char)(v & 0xff);
|
||||||
} else {
|
} else {
|
||||||
int mask = (-0x100 >> offs) & 0xff;
|
int mask = (0xff00 >> offs) & 0xff;
|
||||||
if (((unsigned char)v ^ s) & mask) {
|
if (((unsigned char)v ^ s) & mask) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1943,7 +1943,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
|||||||
if (--ptr > buff) {
|
if (--ptr > buff) {
|
||||||
*ptr = (unsigned char)(v & 0xff);
|
*ptr = (unsigned char)(v & 0xff);
|
||||||
} else {
|
} else {
|
||||||
int mask = (-0x100 >> offs) & 0xff;
|
int mask = (0xff00 >> offs) & 0xff;
|
||||||
if (((unsigned char)v ^ s) & mask) {
|
if (((unsigned char)v ^ s) & mask) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1961,7 +1961,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
|||||||
*ptr = (unsigned char)(v & 0xff);
|
*ptr = (unsigned char)(v & 0xff);
|
||||||
v >>= 8;
|
v >>= 8;
|
||||||
}
|
}
|
||||||
int mask = (-0x100 >> offs) & 0xff;
|
int mask = (0xff00 >> offs) & 0xff;
|
||||||
if (((unsigned char)v ^ s) & mask) {
|
if (((unsigned char)v ^ s) & mask) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -132,9 +132,7 @@ int main(int argc, char* const argv[]) {
|
|||||||
|
|
||||||
if (!no_env) {
|
if (!no_env) {
|
||||||
const char* path = std::getenv("FIFTPATH");
|
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;
|
std::string current_dir;
|
||||||
auto r_current_dir = td::realpath(".");
|
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};
|
VarDescrList tmp_info{new_var_info};
|
||||||
tmp_info -= var_list;
|
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) {
|
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 }
|
absent:(##(size * 8)) { roots + absent <= cells }
|
||||||
tot_cells_size:(##(off_bytes * 8))
|
tot_cells_size:(##(off_bytes * 8))
|
||||||
root_list:(roots * ##(size * 8))
|
root_list:(roots * ##(size * 8))
|
||||||
index:(cells * ##(off_bytes * 8))
|
index:has_idx?(cells * ##(off_bytes * 8))
|
||||||
cell_data:(tot_cells_size * [ uint8 ])
|
cell_data:(tot_cells_size * [ uint8 ])
|
||||||
|
crc32c:has_crc32c?uint32
|
||||||
= BagOfCells;
|
= BagOfCells;
|
||||||
|
|
||||||
compiled_smart_contract
|
compiled_smart_contract
|
||||||
|
@ -75,7 +75,7 @@ td::Result<int> CellSerializationInfo::get_bits(td::Slice cell) const {
|
|||||||
if (data_with_bits) {
|
if (data_with_bits) {
|
||||||
DCHECK(data_len != 0);
|
DCHECK(data_len != 0);
|
||||||
int last = cell[data_offset + data_len - 1];
|
int last = cell[data_offset + data_len - 1];
|
||||||
if (!last || last == 0x80) {
|
if (!(last & 0x7f)) {
|
||||||
return td::Status::Error("overlong encoding");
|
return td::Status::Error("overlong encoding");
|
||||||
}
|
}
|
||||||
return td::narrow_cast<int>((data_len - 1) * 8 + 7 - td::count_trailing_zeroes_non_zero32(last));
|
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;
|
r_size = o_size = 0;
|
||||||
return 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;
|
r_size = rs;
|
||||||
o_size = os;
|
o_size = os;
|
||||||
return data_bytes_adj;
|
return data_bytes_adj;
|
||||||
|
@ -527,9 +527,6 @@ int CellBuilder::serialize(unsigned char* buff, int buff_size) const {
|
|||||||
|
|
||||||
CellBuilder* CellBuilder::make_copy() const {
|
CellBuilder* CellBuilder::make_copy() const {
|
||||||
CellBuilder* c = new CellBuilder();
|
CellBuilder* c = new CellBuilder();
|
||||||
if (!c) {
|
|
||||||
throw CellWriteError();
|
|
||||||
}
|
|
||||||
c->bits = bits;
|
c->bits = bits;
|
||||||
std::memcpy(c->data, data, (bits + 7) >> 3);
|
std::memcpy(c->data, data, (bits + 7) >> 3);
|
||||||
c->refs_cnt = refs_cnt;
|
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}
|
\end{itemize}
|
||||||
|
|
||||||
\nxsubpoint\label{sp:boc.ser.sch}\emb{TL-B scheme for serializing bags of cells}
|
\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}
|
\begin{verbatim}
|
||||||
serialized_boc_tiny cells:uint8 roots:uint8 absent:uint8
|
serialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1)
|
||||||
tot_cells_size:(## 32) cell_data:(tot_cells_size * [ uint8 ])
|
has_cache_bits:(## 1) flags:(## 2) { flags = 0 }
|
||||||
= BagOfCells;
|
size:(## 3) { size <= 4 }
|
||||||
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 }
|
|
||||||
off_bytes:(## 8) { off_bytes <= 8 }
|
off_bytes:(## 8) { off_bytes <= 8 }
|
||||||
cells:(##(size * 8))
|
cells:(##(size * 8))
|
||||||
roots:(##(size * 8))
|
roots:(##(size * 8)) { roots >= 1 }
|
||||||
absent:(##(size * 8)) { roots + absent <= cells }
|
absent:(##(size * 8)) { roots + absent <= cells }
|
||||||
tot_cells_size:(##(off_bytes * 8))
|
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 ])
|
cell_data:(tot_cells_size * [ uint8 ])
|
||||||
|
crc32c:has_crc32c?uint32
|
||||||
= BagOfCells;
|
= BagOfCells;
|
||||||
\end{verbatim}
|
\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}
|
\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:
|
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;
|
internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
|
||||||
|
|
||||||
raw.initialAccountState code:bytes data:bytes = raw.InitialAccountState;
|
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.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.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;
|
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;
|
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.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState;
|
||||||
//generic.initialAccountStateTestWallet initital_account_state:testWallet.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;
|
using tonlib_api::make_object;
|
||||||
Client client;
|
Client client;
|
||||||
|
|
||||||
|
td::mkdir("testdir").ignore();
|
||||||
// init
|
// init
|
||||||
sync_send(client, make_object<tonlib_api::init>(
|
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||||
make_object<tonlib_api::options>(nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("."))))
|
nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("testdir"))))
|
||||||
.ensure();
|
.ensure();
|
||||||
auto local_password = td::SecureString("local password");
|
auto local_password = td::SecureString("local password");
|
||||||
auto mnemonic_password = td::SecureString("mnemonic password");
|
auto mnemonic_password = td::SecureString("mnemonic password");
|
||||||
|
@ -61,15 +61,14 @@ class ExtClient {
|
|||||||
auto raw_query = ton::serialize_tl_object(&query, true);
|
auto raw_query = ton::serialize_tl_object(&query, true);
|
||||||
td::uint32 tag = td::Random::fast_uint32();
|
td::uint32 tag = td::Random::fast_uint32();
|
||||||
VLOG(lite_server) << "send query to liteserver: " << tag << " " << to_string(query);
|
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) {
|
if (seq_no >= 0) {
|
||||||
auto wait = ton::lite_api::liteServer_waitMasterchainSeqno(seq_no, 5000);
|
auto wait = ton::lite_api::liteServer_waitMasterchainSeqno(seq_no, 5000);
|
||||||
VLOG(lite_server) << " with prefix " << to_string(wait);
|
VLOG(lite_server) << " with prefix " << to_string(wait);
|
||||||
auto prefix = ton::serialize_tl_object(&wait, true);
|
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(
|
send_raw_query(
|
||||||
std::move(liteserver_query), [promise = std::move(promise), tag](td::Result<td::BufferSlice> R) mutable {
|
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()) {
|
if (r_encrypted_data.is_error()) {
|
||||||
r_encrypted_data = kv_->get(to_file_name_old(input_key.key));
|
r_encrypted_data = kv_->get(to_file_name_old(input_key.key));
|
||||||
if (r_encrypted_data.is_ok()) {
|
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);
|
<< to_file_name(input_key.key);
|
||||||
TRY_STATUS_PREFIX(kv_->set(to_file_name(input_key.key), r_encrypted_data.ok()), TonlibError::Internal());
|
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();
|
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());
|
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)),
|
EncryptedKey encrypted_key{std::move(encrypted_data), td::Ed25519::PublicKey(std::move(input_key.key.public_key)),
|
||||||
std::move(input_key.key.secret)};
|
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)),
|
TRY_RESULT_PREFIX(decrypted_key, encrypted_key.decrypt(std::move(input_key.local_password)),
|
||||||
TonlibError::KeyDecrypt());
|
TonlibError::KeyDecrypt());
|
||||||
return std::move(decrypted_key);
|
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) {
|
td::Result<KeyStorage::Key> KeyStorage::change_local_password(InputKey input_key, td::Slice new_local_password) {
|
||||||
auto new_secret =
|
auto old_name = to_file_name(input_key.key);
|
||||||
DecryptedKey::change_local_password(input_key.key.secret, input_key.local_password, new_local_password);
|
TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key)));
|
||||||
Key res;
|
return save_key(std::move(decrypted_key), new_local_password);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Result<KeyStorage::Key> KeyStorage::import_pem_key(td::Slice local_password, td::Slice key_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 {
|
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 {
|
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) {
|
td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state) {
|
||||||
return sb << td::tag("last_block", state.last_block_id.to_str())
|
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)
|
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);
|
client_.set_client(client);
|
||||||
state_.last_block_id = state_.last_key_block_id;
|
state_.last_block_id = state_.last_key_block_id;
|
||||||
|
|
||||||
VLOG(last_block) << "check_init_block: skip - FIXME before release";
|
VLOG(last_block) << "State: " << state_;
|
||||||
check_init_block_state_ = QueryState::Done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
|
void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
|
||||||
@ -87,7 +87,7 @@ void LastBlock::sync_loop() {
|
|||||||
} else {
|
} else {
|
||||||
check_init_block_state_ = QueryState::Active;
|
check_init_block_state_ = QueryState::Active;
|
||||||
check_init_block_stats_.start();
|
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";
|
VLOG(last_block) << "check_init_block: start - init_block -> last_block";
|
||||||
do_check_init_block(config_.init_block_id, state_.last_key_block_id);
|
do_check_init_block(config_.init_block_id, state_.last_key_block_id);
|
||||||
} else {
|
} else {
|
||||||
@ -162,10 +162,18 @@ void LastBlock::update_state(block::BlockProofChain& chain) {
|
|||||||
update_utime(chain.last_utime);
|
update_utime(chain.last_utime);
|
||||||
}
|
}
|
||||||
if (is_changed) {
|
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(
|
void LastBlock::on_block_proof(
|
||||||
ton::BlockIdExt from,
|
ton::BlockIdExt from,
|
||||||
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
|
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) {
|
if (chain->complete) {
|
||||||
VLOG(last_block) << "check_init_block: done\n" << check_init_block_stats_;
|
VLOG(last_block) << "check_init_block: done\n" << check_init_block_stats_;
|
||||||
check_init_block_state_ = QueryState::Done;
|
check_init_block_state_ = QueryState::Done;
|
||||||
|
if (update_init_block(config_.init_block_id)) {
|
||||||
|
save_state();
|
||||||
|
}
|
||||||
sync_loop();
|
sync_loop();
|
||||||
} else {
|
} else {
|
||||||
do_check_init_block(chain->to, to);
|
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;
|
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) {
|
void LastBlock::update_utime(td::int64 utime) {
|
||||||
if (state_.utime < utime) {
|
if (state_.utime < utime) {
|
||||||
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_block(ton::BlockIdExt mc_block_id);
|
||||||
bool update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
|
bool update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
|
||||||
void update_utime(td::int64 utime);
|
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_ok();
|
||||||
void on_sync_error(td::Status status);
|
void on_sync_error(td::Status status);
|
||||||
void on_fatal_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) {
|
void check(td::Status status) {
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
LOG(ERROR) << status;
|
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
@ -208,7 +207,7 @@ class GetRawAccountState : public td::actor::Actor {
|
|||||||
auto cell = res.info.root;
|
auto cell = res.info.root;
|
||||||
std::ostringstream outp;
|
std::ostringstream outp;
|
||||||
block::gen::t_Account.print_ref(outp, cell);
|
block::gen::t_Account.print_ref(outp, cell);
|
||||||
LOG(ERROR) << outp.str();
|
LOG(INFO) << outp.str();
|
||||||
if (cell.is_null()) {
|
if (cell.is_null()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -682,8 +681,9 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_accountState>> to_raw_accountS
|
|||||||
.as_slice()
|
.as_slice()
|
||||||
.str();
|
.str();
|
||||||
}
|
}
|
||||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(
|
return tonlib_api::make_object<tonlib_api::raw_accountState>(raw_state.balance, std::move(code), std::move(data),
|
||||||
raw_state.balance, std::move(code), std::move(data), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
|
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) {
|
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;
|
std::ostringstream outp;
|
||||||
block::gen::t_Transaction.print_ref(outp, info.transaction);
|
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);
|
auto is_just = trans.r1.in_msg->prefetch_long(1);
|
||||||
if (is_just == trans.r1.in_msg->fetch_long_eof) {
|
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()) {
|
if (raw_state.code.is_null()) {
|
||||||
return tonlib_api::make_object<tonlib_api::generic_accountStateUninited>(
|
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),
|
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();
|
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()),
|
client_.send_query(ton::lite_api::liteServer_sendMessage(vm::std_boc_serialize(message).move_as_ok()),
|
||||||
[promise = std::move(promise)](auto r_info) mutable {
|
[promise = std::move(promise)](auto r_info) mutable {
|
||||||
TRY_RESULT_PROMISE(promise, info, std::move(r_info));
|
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>());
|
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||||
});
|
});
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
@ -1042,7 +1041,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ
|
|||||||
return TonlibError::MessageTooLong();
|
return TonlibError::MessageTooLong();
|
||||||
}
|
}
|
||||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||||
account_address.bounceable = false;
|
|
||||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||||
auto address = GenericAccount::get_address(
|
auto address = GenericAccount::get_address(
|
||||||
0 /*zerochain*/, TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
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_),
|
TRY_RESULT_PREFIX(valid_until, td::narrow_cast_safe<td::uint32>(request.valid_until_),
|
||||||
TonlibError::InvalidField("valid_until", "overflow"));
|
TonlibError::InvalidField("valid_until", "overflow"));
|
||||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||||
account_address.bounceable = false;
|
|
||||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||||
auto address = GenericAccount::get_address(
|
auto address = GenericAccount::get_address(
|
||||||
0 /*zerochain*/, Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
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();
|
return TonlibError::MessageTooLong();
|
||||||
}
|
}
|
||||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
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 = TestGiver::make_a_gift_message(request.seqno_, request.amount_, request.message_, account_address);
|
||||||
auto message_hash = message->get_hash().as_slice().str();
|
auto message_hash = message->get_hash().as_slice().str();
|
||||||
td::Promise<object_ptr<tonlib_api::ok>> new_promise =
|
td::Promise<object_ptr<tonlib_api::ok>> new_promise =
|
||||||
@ -1245,7 +1241,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
|||||||
block::StdAddress source_address_;
|
block::StdAddress source_address_;
|
||||||
|
|
||||||
tonlib_api::object_ptr<tonlib_api::generic_AccountState> destination_state_;
|
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) {
|
void check(td::Status status) {
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
@ -1263,7 +1259,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
|||||||
return TonlibError::EmptyField("destination");
|
return TonlibError::EmptyField("destination");
|
||||||
}
|
}
|
||||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
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_) {
|
if (!send_grams_.source_) {
|
||||||
return TonlibError::EmptyField("destination");
|
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) {
|
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));
|
TRY_RESULT(state, std::move(r_state));
|
||||||
destination_state_ = std::move(state);
|
destination_state_ = std::move(state);
|
||||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounce_ &&
|
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounceable_) {
|
||||||
!send_grams_.allow_send_to_uninited_) {
|
//FIXME: after restoration of frozen accounts will be supported
|
||||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
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();
|
return do_loop();
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,9 @@ struct TonlibError {
|
|||||||
static td::Status NotEnoughFunds() {
|
static td::Status NotEnoughFunds() {
|
||||||
return td::Status::Error(500, "NOT_ENOUGH_FUNDS");
|
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) {
|
static td::Status LiteServer(td::int32 code, td::Slice message) {
|
||||||
auto f = [&](td::Slice code_description) { return LiteServer(code, code_description, 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())) {
|
: 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 {
|
EncryptedKey DecryptedKey::encrypt(td::Slice local_password, td::Slice old_secret) const {
|
||||||
LOG(ERROR) << "encrypt";
|
|
||||||
td::SecureString secret(32);
|
td::SecureString secret(32);
|
||||||
if (old_secret.size() == td::as_slice(secret).size()) {
|
if (old_secret.size() == td::as_slice(secret).size()) {
|
||||||
secret.as_mutable_slice().copy_from(old_secret);
|
secret.as_mutable_slice().copy_from(old_secret);
|
||||||
} else {
|
} else {
|
||||||
td::Random::secure_bytes(secret.as_mutable_slice());
|
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);
|
td::SecureString decrypted_secret(32);
|
||||||
for (size_t i = 0; i < decrypted_secret.size(); i++) {
|
hmac_sha256(secret, local_password, decrypted_secret.as_mutable_slice());
|
||||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
td::SecureString encryption_secret(64);
|
td::SecureString encryption_secret(64);
|
||||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS,
|
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS,
|
||||||
|
@ -56,8 +56,6 @@ struct DecryptedKey {
|
|||||||
std::vector<td::SecureString> mnemonic_words;
|
std::vector<td::SecureString> mnemonic_words;
|
||||||
td::Ed25519::PrivateKey private_key;
|
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;
|
EncryptedKey encrypt(td::Slice local_password, td::Slice secret = {}) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,15 +24,19 @@
|
|||||||
#include "td/utils/crypto.h"
|
#include "td/utils/crypto.h"
|
||||||
|
|
||||||
namespace tonlib {
|
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) {
|
if (secret.size() != 32) {
|
||||||
return td::Status::Error("Failed to decrypt key: invalid secret size");
|
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);
|
td::SecureString decrypted_secret(32);
|
||||||
for (size_t i = 0; i < 32; i++) {
|
if (old) {
|
||||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
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);
|
td::SecureString encryption_secret(64);
|
||||||
|
@ -32,7 +32,7 @@ struct EncryptedKey {
|
|||||||
td::Ed25519::PublicKey public_key;
|
td::Ed25519::PublicKey public_key;
|
||||||
td::SecureString secret;
|
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
|
} // namespace tonlib
|
||||||
|
@ -186,11 +186,21 @@ class TonlibCli : public td::actor::Actor {
|
|||||||
if (cmd.empty()) {
|
if (cmd.empty()) {
|
||||||
return;
|
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") {
|
if (cmd == "help") {
|
||||||
td::TerminalIO::out() << "help - show this help\n";
|
td::TerminalIO::out() << "help - show this help\n";
|
||||||
td::TerminalIO::out() << "genkey - generate new secret key\n";
|
td::TerminalIO::out() << "genkey - generate new secret key\n";
|
||||||
td::TerminalIO::out() << "keys - show all stored keys\n";
|
td::TerminalIO::out() << "keys - show all stored keys\n";
|
||||||
td::TerminalIO::out() << "unpackaddress <address> - validate and parse address\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() << "importkey - import key\n";
|
||||||
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
|
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
|
||||||
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
|
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
|
||||||
@ -214,6 +224,8 @@ class TonlibCli : public td::actor::Actor {
|
|||||||
try_stop();
|
try_stop();
|
||||||
} else if (cmd == "keys") {
|
} else if (cmd == "keys") {
|
||||||
dump_keys();
|
dump_keys();
|
||||||
|
} else if (cmd == "deletekey") {
|
||||||
|
//delete_key(parser.read_word());
|
||||||
} else if (cmd == "deletekeys") {
|
} else if (cmd == "deletekeys") {
|
||||||
delete_all_keys();
|
delete_all_keys();
|
||||||
} else if (cmd == "exportkey") {
|
} else if (cmd == "exportkey") {
|
||||||
@ -223,15 +235,6 @@ class TonlibCli : public td::actor::Actor {
|
|||||||
} else if (cmd == "setconfig") {
|
} else if (cmd == "setconfig") {
|
||||||
auto config = parser.read_word();
|
auto config = parser.read_word();
|
||||||
auto name = 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 use_callback = parser.read_word();
|
||||||
auto force = parser.read_word();
|
auto force = parser.read_word();
|
||||||
set_config(config, name, to_bool(use_callback), to_bool(force));
|
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());
|
get_hints(parser.read_word());
|
||||||
} else if (cmd == "unpackaddress") {
|
} else if (cmd == "unpackaddress") {
|
||||||
unpack_address(parser.read_word());
|
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 = {}) {
|
void generate_key(td::SecureString entropy = {}) {
|
||||||
if (entropy.size() < 20) {
|
if (entropy.size() < 20) {
|
||||||
td::TerminalIO::out() << "Enter some entropy";
|
td::TerminalIO::out() << "Enter some entropy";
|
||||||
@ -527,6 +554,25 @@ class TonlibCli : public td::actor::Actor {
|
|||||||
return std::move(res);
|
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) {
|
void export_key(td::Slice key) {
|
||||||
if (key.empty()) {
|
if (key.empty()) {
|
||||||
dump_keys();
|
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,
|
void transfer(Address from, Address to, td::uint64 grams, td::Slice password, td::Slice message,
|
||||||
bool allow_send_to_uninited) {
|
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;
|
using tonlib_api::make_object;
|
||||||
auto key = !from.secret.empty()
|
auto key = !from.secret.empty()
|
||||||
? make_object<tonlib_api::inputKey>(
|
? make_object<tonlib_api::inputKey>(
|
||||||
@ -761,7 +812,7 @@ class TonlibCli : public td::actor::Actor {
|
|||||||
: nullptr;
|
: nullptr;
|
||||||
send_query(
|
send_query(
|
||||||
make_object<tonlib_api::generic_sendGrams>(std::move(key), std::move(from.address), std::move(to.address),
|
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) {
|
[this](auto r_res) {
|
||||||
if (r_res.is_error()) {
|
if (r_res.is_error()) {
|
||||||
td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n";
|
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);
|
options.config = std::move(data);
|
||||||
return td::Status::OK();
|
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", [&]() {
|
p.add_option('n', "use-callbacks-for-network", "do not use this", [&]() {
|
||||||
options.use_callbacks_for_network = true;
|
options.use_callbacks_for_network = true;
|
||||||
return td::Status::OK();
|
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()));
|
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());
|
auto cs = vm::load_cell_slice_ref(cb.finalize());
|
||||||
state_extra.r1.block_create_stats = cs;
|
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)) {
|
if (!block::gen::t_BlockCreateStats.validate_csr(cs)) {
|
||||||
cs->print_rec(std::cerr);
|
cs->print_rec(std::cerr);
|
||||||
block::gen::t_BlockCreateStats.print(std::cerr, *cs);
|
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) {
|
int Collator::creator_count_outdated(td::ConstBitPtr key, vm::CellSlice& cs) {
|
||||||
block::DiscountedCounter mc_cnt, shard_cnt;
|
block::DiscountedCounter mc_cnt, shard_cnt;
|
||||||
if (!(block::fetch_CreatorStats(cs, mc_cnt, shard_cnt) && cs.empty_ext())) {
|
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_))) {
|
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)) {
|
if (!(mc_cnt.cnt65536 | shard_cnt.cnt65536)) {
|
||||||
LOG(DEBUG) << "removing stale CreatorStats for " << key.to_hex(256);
|
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());
|
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());
|
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)");
|
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) {
|
int cnt = block_create_stats_->filter([this](vm::CellSlice& cs, td::ConstBitPtr key, int key_len) {
|
||||||
CHECK(key_len == 256);
|
CHECK(key_len == 256);
|
||||||
return creator_count_outdated(key, cs);
|
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;
|
return cnt >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ void LiteQuery::perform_getMasterchainInfo(int mode) {
|
|||||||
}
|
}
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -230,7 +230,7 @@ void LiteQuery::perform_getBlock(BlockIdExt blkid) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -256,7 +256,7 @@ void LiteQuery::perform_getBlockHeader(BlockIdExt blkid, int mode) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -371,7 +371,7 @@ void LiteQuery::perform_getState(BlockIdExt blkid) {
|
|||||||
}
|
}
|
||||||
if (blkid.id.seqno) {
|
if (blkid.id.seqno) {
|
||||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -381,7 +381,7 @@ void LiteQuery::perform_getState(BlockIdExt blkid) {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_zero_state, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -440,7 +440,7 @@ bool LiteQuery::request_mc_block_data(BlockIdExt blkid) {
|
|||||||
++pending_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
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_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_block_proof_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load proof for "s + blkid.to_str() + " : "));
|
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_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load state for "s + blkid.to_str() + " : "));
|
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_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_shard_state_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load state for "s + blkid.to_str() + " : "));
|
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_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_block_data_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
res.move_as_error_prefix("cannot load block "s + blkid.to_str() + " : "));
|
||||||
@ -563,7 +563,7 @@ bool LiteQuery::request_proof_link(BlockIdExt blkid) {
|
|||||||
++pending_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_block_proof_link_from_db_short, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load proof link for "s + blkid.to_str() + " : "));
|
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_;
|
++pending_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_zero_state, blkid,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
td::actor::send_closure(Self, &LiteQuery::abort_query,
|
||||||
res.move_as_error_prefix("cannot load zerostate of "s + blkid.to_str() + " : "));
|
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";
|
LOG(INFO) << "sending a get_top_masterchain_state_block query to manager";
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -1067,7 +1067,7 @@ void LiteQuery::continue_getTransactions(unsigned remaining, bool exact) {
|
|||||||
<< " " << trans_lt_;
|
<< " " << trans_lt_;
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ValidatorManager::get_block_by_lt_from_db, ton::extract_addr_prefix(acc_workchain_, acc_addr_),
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, res.move_as_error(), ton::BlockIdExt{});
|
td::actor::send_closure(Self, &LiteQuery::abort_getTransactions, res.move_as_error(), ton::BlockIdExt{});
|
||||||
} else {
|
} 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) {
|
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()
|
LOG(INFO) << "started a getConfigParams(" << blkid.to_str() << ", " << mode << ", <list of " << param_list.size()
|
||||||
<< " parameters>) liteserver query";
|
<< " 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));
|
continue_getConfigParams(mode, std::move(param_list));
|
||||||
});
|
});
|
||||||
request_mc_block_data_state(blkid);
|
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
|
LOG(INFO) << "performing a lookupBlock(" << blkid.to_str() << ", " << mode << ", " << lt << ", " << utime
|
||||||
<< ") query";
|
<< ") query";
|
||||||
auto P = td::PromiseCreator::lambda(
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
@ -1446,58 +1446,83 @@ void LiteQuery::perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mode & 1) {
|
if (mode & 1) {
|
||||||
base_blk_id_ = (from.seqno() > to.seqno()) ? from : to;
|
if (mode & 0x1000) {
|
||||||
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, base_blk_id_,
|
BlockIdExt bblk = (from.seqno() > to.seqno()) ? from : to;
|
||||||
[Self = actor_id(this), from, to, mode](td::Result<Ref<ShardState>> res) {
|
td::actor::send_closure_later(manager_, &ValidatorManager::get_shard_state_from_db_short, bblk,
|
||||||
if (res.is_error()) {
|
[ Self = actor_id(this), from, to, bblk, mode ](td::Result<Ref<ShardState>> res) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
if (res.is_error()) {
|
||||||
} else {
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, to,
|
} else {
|
||||||
mode, Ref<MasterchainStateQ>(res.move_as_ok()));
|
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) {
|
} else if (mode & 2) {
|
||||||
td::actor::send_closure_later(
|
td::actor::send_closure_later(
|
||||||
manager_, &ton::validator::ValidatorManager::get_top_masterchain_state_block,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
auto pair = res.move_as_ok();
|
auto pair = res.move_as_ok();
|
||||||
td::actor::send_closure_later(Self, &LiteQuery::continue_getBlockProof, from, pair.second, mode,
|
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 {
|
} else {
|
||||||
td::actor::send_closure_later(manager_, &ton::validator::ValidatorManager::get_shard_client_state, false,
|
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()) {
|
if (res.is_error()) {
|
||||||
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
} else {
|
} else {
|
||||||
td::actor::send_closure_later(Self, &LiteQuery::perform_getBlockProof, from,
|
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) {
|
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)) {
|
if (!(mode & 1)) {
|
||||||
base_blk_id_ = to;
|
|
||||||
if (!to.is_masterchain_ext()) {
|
if (!to.is_masterchain_ext()) {
|
||||||
fatal_error("last masterchain block id "s + to.to_str() + " is invalid");
|
fatal_error("last masterchain block id "s + to.to_str() + " is invalid");
|
||||||
return;
|
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()) {
|
if (state.is_null()) {
|
||||||
fatal_error("obtained no valid masterchain state for block "s + base_blk_id_.to_str());
|
fatal_error("obtained no valid masterchain state for block "s + base_blk_id_.to_str());
|
||||||
return;
|
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);
|
mc_state0_ = Ref<MasterchainStateQ>(state);
|
||||||
if (base_blk_id_ != state->get_block_id()) {
|
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 " +
|
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()
|
LOG(INFO) << "continuing getBlockProof(" << mode << ", " << from.to_str() << ", " << to.to_str()
|
||||||
<< ") query with a state for " << base_blk_id_.to_str();
|
<< ") query with a state for " << base_blk_id_.to_str();
|
||||||
if (!state->check_old_mc_block_id(from)) {
|
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 " +
|
fatal_error("proof source masterchain block "s + from.to_str() +
|
||||||
base_blk_id_.to_str());
|
" is unknown from the perspective of reference block " + base_blk_id_.to_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!state->check_old_mc_block_id(to)) {
|
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 " +
|
fatal_error("proof destination masterchain block "s + to.to_str() +
|
||||||
base_blk_id_.to_str());
|
" is unknown from the perspective of reference block " + base_blk_id_.to_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chain_ = std::make_unique<block::BlockProofChain>(from, to, mode);
|
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_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime);
|
||||||
void perform_listBlockTransactions(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
void perform_listBlockTransactions(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
||||||
void finish_listBlockTransactions(int mode, int count);
|
void finish_listBlockTransactions(int mode, int count);
|
||||||
void perform_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode);
|
void perform_getBlockProof(BlockIdExt from, BlockIdExt to, int mode);
|
||||||
void continue_getBlockProof(ton::BlockIdExt from, ton::BlockIdExt to, int mode, Ref<MasterchainStateQ> state);
|
void continue_getBlockProof(BlockIdExt from, BlockIdExt to, int mode, BlockIdExt baseblk,
|
||||||
bool construct_proof_chain(ton::BlockIdExt id);
|
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(ton::BlockIdExt cur, ton::BlockIdExt next);
|
||||||
bool construct_proof_link_forward_cont(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);
|
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) {
|
void ValidatorManagerImpl::shard_client_update(BlockSeqno seqno) {
|
||||||
if (min_confirmed_masterchain_seqno_ < seqno) {
|
if (min_confirmed_masterchain_seqno_ < seqno) {
|
||||||
min_confirmed_masterchain_seqno_ = seqno;
|
min_confirmed_masterchain_seqno_ = seqno;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
while (shard_client_waiters_.size() > 0) {
|
while (shard_client_waiters_.size() > 0) {
|
||||||
auto it = shard_client_waiters_.begin();
|
auto it = shard_client_waiters_.begin();
|
||||||
if (it->first > seqno) {
|
if (it->first > min_confirmed_masterchain_seqno_) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (auto &y : it->second.waiting_) {
|
for (auto &y : it->second.waiting_) {
|
||||||
|
Loading…
Reference in New Issue
Block a user