mirror of
https://github.com/danog/ton.git
synced 2024-11-29 20:19:16 +01:00
updated tonlib
1. updated tonlib 2. fixed bug in state download
This commit is contained in:
parent
f40822b58a
commit
28df74178c
@ -258,6 +258,7 @@ td::Result<Transaction::Info> Transaction::validate() {
|
||||
}
|
||||
Info res;
|
||||
res.blkid = blkid;
|
||||
res.now = trans.now;
|
||||
res.prev_trans_lt = trans.prev_trans_lt;
|
||||
res.prev_trans_hash = trans.prev_trans_hash;
|
||||
res.transaction = root;
|
||||
@ -281,6 +282,8 @@ td::Result<TransactionList::Info> TransactionList::validate() const {
|
||||
Info res;
|
||||
auto current_lt = lt;
|
||||
auto current_hash = hash;
|
||||
res.lt = lt;
|
||||
res.hash = hash;
|
||||
for (auto& root : list) {
|
||||
const auto& blkid = blkids[c++];
|
||||
Transaction transaction;
|
||||
|
@ -60,6 +60,7 @@ struct Transaction {
|
||||
|
||||
struct Info {
|
||||
ton::BlockIdExt blkid;
|
||||
td::uint32 now;
|
||||
ton::LogicalTime prev_trans_lt;
|
||||
ton::Bits256 prev_trans_hash;
|
||||
td::Ref<vm::Cell> transaction;
|
||||
@ -74,21 +75,12 @@ struct TransactionList {
|
||||
td::BufferSlice transactions_boc;
|
||||
|
||||
struct Info {
|
||||
ton::LogicalTime lt;
|
||||
ton::Bits256 hash;
|
||||
std::vector<Transaction::Info> transactions;
|
||||
};
|
||||
|
||||
td::Result<Info> validate() const;
|
||||
};
|
||||
|
||||
struct BlockChain {
|
||||
ton::BlockIdExt from;
|
||||
ton::BlockIdExt to;
|
||||
td::int32 mode;
|
||||
td::BufferSlice proof;
|
||||
|
||||
using Info = std::unique_ptr<block::BlockProofChain>;
|
||||
|
||||
td::Result<Info> validate() const;
|
||||
};
|
||||
|
||||
} // namespace block
|
||||
|
@ -53,17 +53,20 @@ SecureString create_empty<SecureString>(size_t size) {
|
||||
template <class T>
|
||||
Result<T> read_file_impl(CSlice path, int64 size, int64 offset) {
|
||||
TRY_RESULT(from_file, FileFd::open(path, FileFd::Read));
|
||||
if (size == -1) {
|
||||
TRY_RESULT(file_size, from_file.get_size());
|
||||
size = file_size;
|
||||
if (offset < 0 || offset > file_size) {
|
||||
return Status::Error("Failed to read file: invalid offset");
|
||||
}
|
||||
if (size == -1) {
|
||||
size = file_size - offset;
|
||||
} else if (size >= 0) {
|
||||
if (size + offset > file_size) {
|
||||
size = file_size - offset;
|
||||
}
|
||||
}
|
||||
if (size < 0) {
|
||||
return Status::Error("Failed to read file: invalid size");
|
||||
}
|
||||
if (offset < 0 || offset > size) {
|
||||
return Status::Error("Failed to read file: invalid offset");
|
||||
}
|
||||
size -= offset;
|
||||
auto content = create_empty<T>(narrow_cast<size_t>(size));
|
||||
TRY_RESULT(got_size, from_file.pread(as_mutable_slice(content), offset));
|
||||
if (got_size != static_cast<size_t>(size)) {
|
||||
|
2
third-party/wingetopt/CMakeLists.txt
vendored
2
third-party/wingetopt/CMakeLists.txt
vendored
@ -3,5 +3,5 @@ cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_library(wingetopt src/getopt.c src/getopt.h)
|
||||
target_include_directories(wingetopt PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
target_include_directories(wingetopt PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
|
||||
|
||||
|
@ -16,7 +16,7 @@ vector {t:Type} # [ t ] = Vector t;
|
||||
error code:int32 message:string = Error;
|
||||
ok = Ok;
|
||||
|
||||
options config:string keystore_directory:string = Options;
|
||||
options config:string keystore_directory:string use_callbacks_for_network:Bool = Options;
|
||||
|
||||
key public_key:string secret:secureBytes = Key;
|
||||
inputKey key:key local_password:secureBytes = InputKey;
|
||||
@ -31,17 +31,17 @@ accountAddress account_address:string = AccountAddress;
|
||||
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 = raw.AccountState;
|
||||
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId sync_utime:int53 = raw.AccountState;
|
||||
raw.message source:string destination:string value:int64 = raw.Message;
|
||||
raw.transaction data:bytes previous_transaction_id:internal.transactionId fee:int64 in_msg:raw.message out_msgs:vector<raw.message> = raw.Transaction;
|
||||
raw.transactions transactions:vector<raw.Transaction> = raw.Transactions;
|
||||
raw.transaction utime:int53 data:bytes transaction_id:internal.transactionId 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;
|
||||
|
||||
testWallet.initialAccountState public_key:string = testWallet.InitialAccountState;
|
||||
testWallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId = testWallet.AccountState;
|
||||
testWallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = testWallet.AccountState;
|
||||
|
||||
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId = testGiver.AccountState;
|
||||
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53= testGiver.AccountState;
|
||||
|
||||
uninited.accountState balance:int64 = uninited.AccountState;
|
||||
uninited.accountState balance:int64 last_transaction_id:internal.transactionId sync_utime:int53 = uninited.AccountState;
|
||||
|
||||
generic.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState;
|
||||
generic.initialAccountStateTestWallet initital_account_state:testWallet.initialAccountState = generic.InitialAccountState;
|
||||
@ -51,6 +51,8 @@ generic.accountStateTestWallet account_state:testWallet.accountState = generic.A
|
||||
generic.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState;
|
||||
generic.accountStateUninited account_state:uninited.accountState = generic.AccountState;
|
||||
|
||||
updateSendLiteServerQuery id:int64 data:bytes = Update;
|
||||
|
||||
---functions---
|
||||
|
||||
init options:options = Ok;
|
||||
@ -89,5 +91,7 @@ testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 = Ok;
|
||||
generic.getAccountState account_address:accountAddress = generic.AccountState;
|
||||
generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 = Ok;
|
||||
|
||||
runTests dir:string = Ok;
|
||||
onLiteServerQueryResult id:int64 bytes:bytes = Ok;
|
||||
onLiteServerQueryError id:int64 error:error = Ok;
|
||||
|
||||
runTests dir:string = Ok;
|
||||
|
Binary file not shown.
@ -9,6 +9,7 @@ set(TONLIB_SOURCE
|
||||
tonlib/Config.cpp
|
||||
tonlib/ExtClient.cpp
|
||||
tonlib/ExtClientLazy.cpp
|
||||
tonlib/ExtClientOutbound.cpp
|
||||
tonlib/GenericAccount.cpp
|
||||
tonlib/KeyStorage.cpp
|
||||
tonlib/LastBlock.cpp
|
||||
@ -21,6 +22,7 @@ set(TONLIB_SOURCE
|
||||
tonlib/Config.h
|
||||
tonlib/ExtClient.h
|
||||
tonlib/ExtClientLazy.h
|
||||
tonlib/ExtClientOutbound.h
|
||||
tonlib/GenericAccount.h
|
||||
tonlib/KeyStorage.h
|
||||
tonlib/LastBlock.h
|
||||
|
@ -172,16 +172,17 @@ TEST(Tonlib, InitClose) {
|
||||
{
|
||||
Client client;
|
||||
sync_send(client, make_object<tonlib_api::close>()).ensure();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "."))).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", ".", false))).ensure_error();
|
||||
}
|
||||
{
|
||||
Client client;
|
||||
sync_send(client, make_object<tonlib_api::init>(nullptr)).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("fdajkfldsjkafld", ".")))
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("fdajkfldsjkafld", ".", false)))
|
||||
.ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "fdhskfds"))).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "."))).ensure();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "."))).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "fdhskfds", false)))
|
||||
.ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", ".", false))).ensure();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", ".", false))).ensure_error();
|
||||
|
||||
td::Slice bad_config = R"abc(
|
||||
{
|
||||
@ -194,7 +195,7 @@ TEST(Tonlib, InitClose) {
|
||||
sync_send(client, make_object<tonlib_api::testGiver_getAccountState>()).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::close>()).ensure();
|
||||
sync_send(client, make_object<tonlib_api::close>()).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "."))).ensure_error();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", ".", false))).ensure_error();
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,7 +290,7 @@ TEST(Tonlib, KeysApi) {
|
||||
Client client;
|
||||
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "."))).ensure();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", ".", false))).ensure();
|
||||
auto local_password = td::SecureString("local password");
|
||||
auto mnemonic_password = td::SecureString("mnemonic password");
|
||||
{
|
||||
|
@ -170,12 +170,12 @@ void dump_transaction_history(Client& client, std::string address) {
|
||||
make_object<tonlib_api::accountAddress>(address), std::move(tid)))
|
||||
.move_as_ok();
|
||||
CHECK(got_transactions->transactions_.size() > 0);
|
||||
CHECK(got_transactions->transactions_[0]->previous_transaction_id_->lt_ < lt);
|
||||
CHECK(got_transactions->previous_transaction_id_->lt_ < lt);
|
||||
for (auto& txn : got_transactions->transactions_) {
|
||||
LOG(ERROR) << to_string(txn);
|
||||
cnt++;
|
||||
}
|
||||
tid = std::move(got_transactions->transactions_.back()->previous_transaction_id_);
|
||||
tid = std::move(got_transactions->previous_transaction_id_);
|
||||
}
|
||||
LOG(ERROR) << cnt;
|
||||
}
|
||||
@ -196,7 +196,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
Client client;
|
||||
{
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(global_config_str, "."))).ensure();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(global_config_str, ".", false)))
|
||||
.ensure();
|
||||
}
|
||||
//dump_transaction_history(client, get_test_giver_address(client));
|
||||
auto wallet_a = create_wallet(client);
|
||||
@ -208,7 +209,8 @@ int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
{
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(global_config_str, "."))).ensure();
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(global_config_str, ".", false)))
|
||||
.ensure();
|
||||
|
||||
auto key = sync_send(client, make_object<tonlib_api::createNewKey>(
|
||||
td::SecureString("local"), td::SecureString("mnemonic"), td::SecureString()))
|
||||
|
@ -21,10 +21,10 @@
|
||||
#include "tonlib/LastBlock.h"
|
||||
|
||||
namespace tonlib {
|
||||
void ExtClient::with_last_block(td::Promise<ton::BlockIdExt> promise) {
|
||||
void ExtClient::with_last_block(td::Promise<LastBlockInfo> promise) {
|
||||
auto query_id = last_block_queries_.create(std::move(promise));
|
||||
td::Promise<ton::BlockIdExt> P = [query_id, self = this,
|
||||
actor_id = td::actor::actor_id()](td::Result<ton::BlockIdExt> result) {
|
||||
td::Promise<LastBlockInfo> P = [query_id, self = this,
|
||||
actor_id = td::actor::actor_id()](td::Result<LastBlockInfo> result) {
|
||||
send_lambda(actor_id, [self, query_id, result = std::move(result)]() mutable {
|
||||
self->last_block_queries_.extract(query_id).set_result(std::move(result));
|
||||
});
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
namespace tonlib {
|
||||
class LastBlock;
|
||||
struct LastBlockInfo;
|
||||
struct ExtClientRef {
|
||||
td::actor::ActorId<ton::adnl::AdnlExtClient> andl_ext_client_;
|
||||
td::actor::ActorId<LastBlock> last_block_actor_;
|
||||
@ -49,7 +50,7 @@ class ExtClient {
|
||||
return client_;
|
||||
}
|
||||
|
||||
void with_last_block(td::Promise<ton::BlockIdExt> promise);
|
||||
void with_last_block(td::Promise<LastBlockInfo> promise);
|
||||
|
||||
template <class QueryT>
|
||||
void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise) {
|
||||
@ -74,7 +75,7 @@ class ExtClient {
|
||||
private:
|
||||
ExtClientRef client_;
|
||||
td::Container<td::Promise<td::BufferSlice>> queries_;
|
||||
td::Container<td::Promise<ton::BlockIdExt>> last_block_queries_;
|
||||
td::Container<td::Promise<LastBlockInfo>> last_block_queries_;
|
||||
|
||||
void send_raw_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise);
|
||||
};
|
||||
|
@ -23,15 +23,12 @@
|
||||
#include "lite-client/lite-client-common.h"
|
||||
|
||||
namespace tonlib {
|
||||
LastBlock::LastBlock(ExtClientRef client, ton::ZeroStateIdExt zero_state_id, ton::BlockIdExt last_block_id,
|
||||
td::actor::ActorShared<> parent) {
|
||||
zero_state_id_ = std::move(zero_state_id);
|
||||
mc_last_block_id_ = std::move(last_block_id);
|
||||
LastBlock::LastBlock(ExtClientRef client, State state, td::unique_ptr<Callback> callback)
|
||||
: state_(std::move(state)), callback_(std::move(callback)) {
|
||||
client_.set_client(client);
|
||||
parent_ = std::move(parent);
|
||||
}
|
||||
|
||||
void LastBlock::get_last_block(td::Promise<ton::BlockIdExt> promise) {
|
||||
void LastBlock::get_last_block(td::Promise<LastBlockInfo> promise) {
|
||||
if (promises_.empty()) {
|
||||
do_get_last_block();
|
||||
}
|
||||
@ -39,13 +36,16 @@ void LastBlock::get_last_block(td::Promise<ton::BlockIdExt> promise) {
|
||||
}
|
||||
|
||||
void LastBlock::do_get_last_block() {
|
||||
client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
|
||||
[this](auto r_info) { this->on_masterchain_info(std::move(r_info)); });
|
||||
return;
|
||||
//client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
|
||||
//[this](auto r_info) { this->on_masterchain_info(std::move(r_info)); });
|
||||
//return;
|
||||
|
||||
//liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
|
||||
client_.send_query(
|
||||
ton::lite_api::liteServer_getBlockProof(0, create_tl_lite_block_id(mc_last_block_id_), nullptr),
|
||||
[this, from = mc_last_block_id_](auto r_block_proof) { this->on_block_proof(from, std::move(r_block_proof)); });
|
||||
ton::lite_api::liteServer_getBlockProof(0, create_tl_lite_block_id(state_.last_key_block_id), nullptr),
|
||||
[this, from = state_.last_key_block_id](auto r_block_proof) {
|
||||
this->on_block_proof(from, std::move(r_block_proof));
|
||||
});
|
||||
}
|
||||
|
||||
td::Result<bool> LastBlock::process_block_proof(
|
||||
@ -60,6 +60,12 @@ td::Result<bool> LastBlock::process_block_proof(
|
||||
}
|
||||
TRY_STATUS(chain->validate());
|
||||
update_mc_last_block(chain->to);
|
||||
if (chain->has_key_block) {
|
||||
update_mc_last_key_block(chain->key_blkid);
|
||||
}
|
||||
if (chain->has_utime) {
|
||||
update_utime(chain->last_utime);
|
||||
}
|
||||
return chain->complete;
|
||||
}
|
||||
|
||||
@ -68,14 +74,16 @@ void LastBlock::on_block_proof(
|
||||
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
|
||||
auto r_is_ready = process_block_proof(from, std::move(r_block_proof));
|
||||
if (r_is_ready.is_error()) {
|
||||
LOG(WARNING) << "Failed liteServer_getBlockProof " << r_block_proof.error();
|
||||
LOG(WARNING) << "Failed liteServer_getBlockProof " << r_is_ready.error();
|
||||
return;
|
||||
}
|
||||
auto is_ready = r_is_ready.move_as_ok();
|
||||
if (is_ready) {
|
||||
for (auto& promise : promises_) {
|
||||
auto copy = mc_last_block_id_;
|
||||
promise.set_value(std::move(copy));
|
||||
LastBlockInfo res;
|
||||
res.id = state_.last_block_id;
|
||||
res.utime = state_.utime;
|
||||
promise.set_value(std::move(res));
|
||||
}
|
||||
promises_.clear();
|
||||
} else {
|
||||
@ -93,8 +101,10 @@ void LastBlock::on_masterchain_info(
|
||||
LOG(WARNING) << "Failed liteServer_getMasterchainInfo " << r_info.error();
|
||||
}
|
||||
for (auto& promise : promises_) {
|
||||
auto copy = mc_last_block_id_;
|
||||
promise.set_value(std::move(copy));
|
||||
LastBlockInfo res;
|
||||
res.id = state_.last_block_id;
|
||||
res.utime = state_.utime;
|
||||
promise.set_value(std::move(res));
|
||||
}
|
||||
promises_.clear();
|
||||
}
|
||||
@ -105,17 +115,17 @@ void LastBlock::update_zero_state(ton::ZeroStateIdExt zero_state_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zero_state_id_.is_valid()) {
|
||||
if (!state_.zero_state_id.is_valid()) {
|
||||
LOG(INFO) << "Init zerostate: " << zero_state_id.to_str();
|
||||
zero_state_id_ = std::move(zero_state_id);
|
||||
state_.zero_state_id = std::move(zero_state_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (zero_state_id_ == zero_state_id_) {
|
||||
if (state_.zero_state_id == state_.zero_state_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(FATAL) << "Masterchain zerostate mismatch: expected: " << zero_state_id_.to_str() << ", found "
|
||||
LOG(FATAL) << "Masterchain zerostate mismatch: expected: " << state_.zero_state_id.to_str() << ", found "
|
||||
<< zero_state_id.to_str();
|
||||
// TODO: all other updates will be inconsitent.
|
||||
// One will have to restart ton client
|
||||
@ -126,9 +136,25 @@ void LastBlock::update_mc_last_block(ton::BlockIdExt mc_block_id) {
|
||||
LOG(ERROR) << "Ignore invalid masterchain block";
|
||||
return;
|
||||
}
|
||||
if (!mc_last_block_id_.is_valid() || mc_last_block_id_.id.seqno < mc_block_id.id.seqno) {
|
||||
mc_last_block_id_ = mc_block_id;
|
||||
LOG(INFO) << "Update masterchain block id: " << mc_last_block_id_.to_str();
|
||||
if (!state_.last_block_id.is_valid() || state_.last_block_id.id.seqno < mc_block_id.id.seqno) {
|
||||
state_.last_block_id = mc_block_id;
|
||||
LOG(INFO) << "Update masterchain block id: " << state_.last_block_id.to_str();
|
||||
}
|
||||
}
|
||||
void LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) {
|
||||
if (!mc_key_block_id.is_valid()) {
|
||||
LOG(ERROR) << "Ignore invalid masterchain block";
|
||||
return;
|
||||
}
|
||||
if (!state_.last_key_block_id.is_valid() || state_.last_key_block_id.id.seqno < mc_key_block_id.id.seqno) {
|
||||
state_.last_key_block_id = mc_key_block_id;
|
||||
LOG(INFO) << "Update masterchain key block id: " << state_.last_key_block_id.to_str();
|
||||
}
|
||||
}
|
||||
|
||||
void LastBlock::update_utime(td::int64 utime) {
|
||||
if (state_.utime < utime) {
|
||||
state_.utime = utime;
|
||||
}
|
||||
}
|
||||
} // namespace tonlib
|
||||
|
@ -22,21 +22,35 @@
|
||||
#include "tonlib/ExtClient.h"
|
||||
|
||||
namespace tonlib {
|
||||
struct LastBlockInfo {
|
||||
ton::BlockIdExt id;
|
||||
td::int64 utime{0};
|
||||
};
|
||||
class LastBlock : public td::actor::Actor {
|
||||
public:
|
||||
explicit LastBlock(ExtClientRef client, ton::ZeroStateIdExt zero_state_id, ton::BlockIdExt last_block_id,
|
||||
td::actor::ActorShared<> parent);
|
||||
struct State {
|
||||
ton::ZeroStateIdExt zero_state_id;
|
||||
ton::BlockIdExt last_key_block_id;
|
||||
ton::BlockIdExt last_block_id;
|
||||
td::int64 utime{0};
|
||||
};
|
||||
|
||||
void get_last_block(td::Promise<ton::BlockIdExt> promise);
|
||||
class Callback {
|
||||
public:
|
||||
virtual ~Callback() {
|
||||
}
|
||||
virtual void on_state_changes(State state) = 0;
|
||||
};
|
||||
|
||||
explicit LastBlock(ExtClientRef client, State state, td::unique_ptr<Callback> callback);
|
||||
void get_last_block(td::Promise<LastBlockInfo> promise);
|
||||
|
||||
private:
|
||||
ExtClient client_;
|
||||
ton::ZeroStateIdExt zero_state_id_;
|
||||
ton::BlockIdExt mc_last_block_id_;
|
||||
State state_;
|
||||
td::unique_ptr<Callback> callback_;
|
||||
|
||||
std::vector<td::Promise<ton::BlockIdExt>> promises_;
|
||||
|
||||
td::actor::ActorShared<> parent_;
|
||||
std::vector<td::Promise<LastBlockInfo>> promises_;
|
||||
|
||||
void do_get_last_block();
|
||||
void on_masterchain_info(td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_masterchainInfo>> r_info);
|
||||
@ -49,5 +63,7 @@ class LastBlock : public td::actor::Actor {
|
||||
void update_zero_state(ton::ZeroStateIdExt zero_state_id);
|
||||
|
||||
void update_mc_last_block(ton::BlockIdExt mc_block_id);
|
||||
void update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
|
||||
void update_utime(td::int64 utime);
|
||||
};
|
||||
} // namespace tonlib
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "TonlibClient.h"
|
||||
|
||||
#include "tonlib/ExtClientLazy.h"
|
||||
#include "tonlib/ExtClientOutbound.h"
|
||||
#include "tonlib/GenericAccount.h"
|
||||
#include "tonlib/LastBlock.h"
|
||||
#include "tonlib/TestWallet.h"
|
||||
@ -73,6 +74,7 @@ struct RawAccountState {
|
||||
td::Ref<vm::CellSlice> code;
|
||||
td::Ref<vm::CellSlice> data;
|
||||
block::AccountState::Info info;
|
||||
td::int64 sync_utime = 0;
|
||||
};
|
||||
|
||||
td::Result<td::int64> to_balance_or_throw(td::Ref<vm::CellSlice> balance_ref) {
|
||||
@ -169,7 +171,7 @@ class GetRawAccountState : public td::actor::Actor {
|
||||
block::StdAddress address_;
|
||||
td::Promise<RawAccountState> promise_;
|
||||
ExtClient client_;
|
||||
ton::BlockIdExt last_block_;
|
||||
LastBlockInfo last_block_;
|
||||
|
||||
void with_account_state(td::Result<ton::tl_object_ptr<ton::lite_api::liteServer_accountState>> r_account_state) {
|
||||
promise_.set_result(TRY_VM(do_with_account_state(std::move(r_account_state))));
|
||||
@ -180,10 +182,11 @@ class GetRawAccountState : public td::actor::Actor {
|
||||
td::Result<ton::tl_object_ptr<ton::lite_api::liteServer_accountState>> r_account_state) {
|
||||
TRY_RESULT(raw_account_state, std::move(r_account_state));
|
||||
auto account_state = create_account_state(std::move(raw_account_state));
|
||||
TRY_RESULT(info, account_state.validate(last_block_, address_));
|
||||
TRY_RESULT(info, account_state.validate(last_block_.id, address_));
|
||||
auto serialized_state = account_state.state.clone();
|
||||
RawAccountState res;
|
||||
res.info = std::move(info);
|
||||
res.sync_utime = last_block_.utime;
|
||||
auto cell = res.info.root;
|
||||
if (cell.is_null()) {
|
||||
return res;
|
||||
@ -222,14 +225,14 @@ class GetRawAccountState : public td::actor::Actor {
|
||||
}
|
||||
|
||||
void start_up() override {
|
||||
client_.with_last_block([self = this](td::Result<ton::BlockIdExt> r_last_block) {
|
||||
client_.with_last_block([self = this](td::Result<LastBlockInfo> r_last_block) {
|
||||
if (r_last_block.is_error()) {
|
||||
return self->check(r_last_block.move_as_error());
|
||||
}
|
||||
self->last_block_ = r_last_block.move_as_ok();
|
||||
|
||||
self->client_.send_query(
|
||||
ton::lite_api::liteServer_getAccountState(ton::create_tl_lite_block_id(self->last_block_),
|
||||
ton::lite_api::liteServer_getAccountState(ton::create_tl_lite_block_id(self->last_block_.id),
|
||||
ton::create_tl_object<ton::lite_api::liteServer_accountId>(
|
||||
self->address_.workchain, self->address_.addr)),
|
||||
[self](auto r_state) { self->with_account_state(std::move(r_state)); });
|
||||
@ -263,7 +266,30 @@ ExtClientRef TonlibClient::get_client_ref() {
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
void TonlibClient::proxy_request(td::int64 query_id, std::string data) {
|
||||
callback_->on_result(0, tonlib_api::make_object<tonlib_api::updateSendLiteServerQuery>(query_id, data));
|
||||
}
|
||||
|
||||
void TonlibClient::init_ext_client() {
|
||||
if (use_callbacks_for_network_) {
|
||||
class Callback : public ExtClientOutbound::Callback {
|
||||
public:
|
||||
explicit Callback(td::actor::ActorShared<TonlibClient> parent) : parent_(std::move(parent)) {
|
||||
}
|
||||
|
||||
void request(td::int64 id, std::string data) override {
|
||||
send_closure(parent_, &TonlibClient::proxy_request, id, std::move(data));
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorShared<TonlibClient> parent_;
|
||||
};
|
||||
ref_cnt_++;
|
||||
auto client = ExtClientOutbound::create(td::make_unique<Callback>(td::actor::actor_shared(this)));
|
||||
ext_client_outbound_ = client.get();
|
||||
raw_client_ = std::move(client);
|
||||
} else {
|
||||
auto lite_clients_size = config_.lite_clients.size();
|
||||
CHECK(lite_clients_size != 0);
|
||||
auto lite_client_id = td::Random::fast(0, td::narrow_cast<int>(lite_clients_size) - 1);
|
||||
@ -279,12 +305,29 @@ void TonlibClient::init_ext_client() {
|
||||
ref_cnt_++;
|
||||
raw_client_ = ExtClientLazy::create(lite_client.adnl_id, lite_client.address,
|
||||
td::make_unique<Callback>(td::actor::actor_shared()));
|
||||
}
|
||||
}
|
||||
void TonlibClient::init_last_block() {
|
||||
ref_cnt_++;
|
||||
raw_last_block_ = td::actor::create_actor<LastBlock>(
|
||||
"LastBlock", get_client_ref(),
|
||||
ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
|
||||
config_.zero_state_id.file_hash),
|
||||
config_.zero_state_id, td::actor::actor_shared());
|
||||
class Callback : public LastBlock::Callback {
|
||||
public:
|
||||
Callback(td::actor::ActorShared<TonlibClient> client) : client_(std::move(client)) {
|
||||
}
|
||||
void on_state_changes(LastBlock::State state) override {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorShared<TonlibClient> client_;
|
||||
};
|
||||
LastBlock::State state;
|
||||
//state.zero_state_id = ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
|
||||
//config_.zero_state_id.file_hash),
|
||||
state.last_block_id = config_.zero_state_id;
|
||||
state.last_key_block_id = config_.zero_state_id;
|
||||
|
||||
raw_last_block_ = td::actor::create_actor<LastBlock>("LastBlock", get_client_ref(), std::move(state),
|
||||
td::make_unique<Callback>(td::actor::actor_shared(this)));
|
||||
client_.set_client(get_client_ref());
|
||||
}
|
||||
|
||||
@ -426,6 +469,7 @@ td::Status TonlibClient::do_request(const tonlib_api::init& request,
|
||||
return td::Status::Error(400, "Field options must not be empty");
|
||||
}
|
||||
TRY_STATUS(key_storage_.set_directory(request.options_->keystore_directory_));
|
||||
use_callbacks_for_network_ = request.options_->use_callbacks_for_network_;
|
||||
if (!request.options_->config_.empty()) {
|
||||
TRY_STATUS(set_config(std::move(request.options_->config_)));
|
||||
}
|
||||
@ -444,6 +488,7 @@ td::Status TonlibClient::set_config(std::string config) {
|
||||
}
|
||||
config_ = std::move(new_config);
|
||||
init_ext_client();
|
||||
init_last_block();
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
@ -454,6 +499,7 @@ td::Status TonlibClient::do_request(const tonlib_api::close& request,
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::options_setConfig& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
TRY_STATUS(set_config(request.config_));
|
||||
@ -461,6 +507,10 @@ td::Status TonlibClient::do_request(const tonlib_api::options_setConfig& request
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::internal_transactionId> empty_transaction_id() {
|
||||
return tonlib_api::make_object<tonlib_api::internal_transactionId>(0, std::string(32, 0));
|
||||
}
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::internal_transactionId> to_transaction_id(const block::AccountState::Info& info) {
|
||||
return tonlib_api::make_object<tonlib_api::internal_transactionId>(info.last_trans_lt,
|
||||
info.last_trans_hash.as_slice().str());
|
||||
@ -482,7 +532,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_accountState>> to_raw_accountS
|
||||
.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));
|
||||
to_transaction_id(raw_state.info), raw_state.sync_utime);
|
||||
}
|
||||
|
||||
td::Result<std::string> to_std_address_or_throw(td::Ref<vm::CellSlice> cs) {
|
||||
@ -591,7 +641,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_transaction>> to_raw_transacti
|
||||
}
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::raw_transaction>(
|
||||
data,
|
||||
info.now, data,
|
||||
tonlib_api::make_object<tonlib_api::internal_transactionId>(info.prev_trans_lt,
|
||||
info.prev_trans_hash.as_slice().str()),
|
||||
fees, std::move(in_msg), std::move(out_msgs));
|
||||
@ -608,7 +658,14 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_transactions>> to_raw_transact
|
||||
TRY_RESULT(raw_transaction, to_raw_transaction(std::move(transaction)));
|
||||
transactions.push_back(std::move(raw_transaction));
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::raw_transactions>(std::move(transactions));
|
||||
|
||||
auto transaction_id =
|
||||
tonlib_api::make_object<tonlib_api::internal_transactionId>(info.lt, info.hash.as_slice().str());
|
||||
for (auto& transaction : transactions) {
|
||||
std::swap(transaction->transaction_id_, transaction_id);
|
||||
}
|
||||
|
||||
return tonlib_api::make_object<tonlib_api::raw_transactions>(std::move(transactions), std::move(transaction_id));
|
||||
}
|
||||
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::testWallet_accountState>> to_testWallet_accountState(
|
||||
@ -622,8 +679,8 @@ td::Result<tonlib_api::object_ptr<tonlib_api::testWallet_accountState>> to_testW
|
||||
if (seqno == cs.fetch_ulong_eof) {
|
||||
return td::Status::Error("Failed to parse seq_no");
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::testWallet_accountState>(raw_state.balance, static_cast<td::uint32>(seqno),
|
||||
to_transaction_id(raw_state.info));
|
||||
return tonlib_api::make_object<tonlib_api::testWallet_accountState>(
|
||||
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.sync_utime);
|
||||
}
|
||||
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGiver_accountState(
|
||||
@ -637,15 +694,16 @@ td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGi
|
||||
if (seqno == cs.fetch_ulong_eof) {
|
||||
return td::Status::Error("Failed to parse seq_no");
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::testGiver_accountState>(raw_state.balance, static_cast<td::uint32>(seqno),
|
||||
to_transaction_id(raw_state.info));
|
||||
return tonlib_api::make_object<tonlib_api::testGiver_accountState>(
|
||||
raw_state.balance, static_cast<td::uint32>(seqno), to_transaction_id(raw_state.info), raw_state.sync_utime);
|
||||
}
|
||||
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_accountState(
|
||||
RawAccountState&& raw_state) {
|
||||
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));
|
||||
tonlib_api::make_object<tonlib_api::uninited_accountState>(raw_state.balance, empty_transaction_id(),
|
||||
raw_state.sync_utime));
|
||||
}
|
||||
|
||||
auto code_hash = raw_state.code->prefetch_ref()->get_hash();
|
||||
@ -1019,4 +1077,30 @@ td::Status TonlibClient::do_request(const tonlib_api::changeLocalPassword& reque
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryResult& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_, td::BufferSlice(request.bytes_),
|
||||
[promise = std::move(promise)](td::Result<td::Unit> res) mutable {
|
||||
if (res.is_ok()) {
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
} else {
|
||||
promise.set_error(res.move_as_error());
|
||||
}
|
||||
});
|
||||
return td::Status::OK();
|
||||
}
|
||||
td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryError& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||
send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_,
|
||||
td::Status::Error(request.error_->code_, request.error_->message_),
|
||||
[promise = std::move(promise)](td::Result<td::Unit> res) mutable {
|
||||
if (res.is_ok()) {
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
} else {
|
||||
promise.set_error(res.move_as_error());
|
||||
}
|
||||
});
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
} // namespace tonlib
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "tonlib/Config.h"
|
||||
#include "tonlib/ExtClient.h"
|
||||
#include "tonlib/ExtClientOutbound.h"
|
||||
#include "tonlib/KeyStorage.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
@ -44,6 +45,9 @@ class TonlibClient : public td::actor::Actor {
|
||||
td::unique_ptr<TonlibCallback> callback_;
|
||||
Config config_;
|
||||
|
||||
bool use_callbacks_for_network_{false};
|
||||
td::actor::ActorId<ExtClientOutbound> ext_client_outbound_;
|
||||
|
||||
// KeyStorage
|
||||
KeyStorage key_storage_;
|
||||
|
||||
@ -54,6 +58,7 @@ class TonlibClient : public td::actor::Actor {
|
||||
|
||||
ExtClientRef get_client_ref();
|
||||
void init_ext_client();
|
||||
void init_last_block();
|
||||
|
||||
bool is_closing_{false};
|
||||
td::uint32 ref_cnt_{1};
|
||||
@ -130,5 +135,12 @@ class TonlibClient : public td::actor::Actor {
|
||||
|
||||
td::Status do_request(const tonlib_api::changeLocalPassword& request,
|
||||
td::Promise<object_ptr<tonlib_api::key>>&& promise);
|
||||
|
||||
td::Status do_request(const tonlib_api::onLiteServerQueryResult& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
td::Status do_request(const tonlib_api::onLiteServerQueryError& request,
|
||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||
|
||||
void proxy_request(td::int64 query_id, std::string data);
|
||||
};
|
||||
} // namespace tonlib
|
||||
|
@ -5,12 +5,17 @@
|
||||
#include "td/utils/Parser.h"
|
||||
#include "td/utils/port/signals.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
#include "terminal/terminal.h"
|
||||
|
||||
#include "tonlib/TonlibClient.h"
|
||||
#include "tonlib/TonlibCallback.h"
|
||||
|
||||
#include "tonlib/ExtClientLazy.h"
|
||||
|
||||
#include "auto/tl/tonlib_api.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
@ -20,6 +25,7 @@ class TonlibCli : public td::actor::Actor {
|
||||
bool enable_readline{true};
|
||||
std::string config;
|
||||
std::string key_dir{"."};
|
||||
bool use_callbacks_for_network{false};
|
||||
};
|
||||
TonlibCli(Options options) : options_(std::move(options)) {
|
||||
}
|
||||
@ -39,6 +45,8 @@ class TonlibCli : public td::actor::Actor {
|
||||
|
||||
std::map<std::uint64_t, td::Promise<tonlib_api::object_ptr<tonlib_api::Object>>> query_handlers_;
|
||||
|
||||
td::actor::ActorOwn<ton::adnl::AdnlExtClient> raw_client_;
|
||||
|
||||
bool is_closing_{false};
|
||||
td::uint32 ref_cnt_{1};
|
||||
|
||||
@ -79,8 +87,28 @@ class TonlibCli : public td::actor::Actor {
|
||||
|
||||
load_keys();
|
||||
|
||||
if (options_.use_callbacks_for_network) {
|
||||
auto config = tonlib::Config::parse(options_.config).move_as_ok();
|
||||
auto lite_clients_size = config.lite_clients.size();
|
||||
CHECK(lite_clients_size != 0);
|
||||
auto lite_client_id = td::Random::fast(0, td::narrow_cast<int>(lite_clients_size) - 1);
|
||||
auto& lite_client = config.lite_clients[lite_client_id];
|
||||
class Callback : public tonlib::ExtClientLazy::Callback {
|
||||
public:
|
||||
explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorShared<> parent_;
|
||||
};
|
||||
ref_cnt_++;
|
||||
raw_client_ = tonlib::ExtClientLazy::create(lite_client.adnl_id, lite_client.address,
|
||||
td::make_unique<Callback>(td::actor::actor_shared()));
|
||||
}
|
||||
|
||||
using tonlib_api::make_object;
|
||||
send_query(make_object<tonlib_api::init>(make_object<tonlib_api::options>(options_.config, options_.key_dir)),
|
||||
send_query(make_object<tonlib_api::init>(make_object<tonlib_api::options>(options_.config, options_.key_dir,
|
||||
options_.use_callbacks_for_network)),
|
||||
[](auto r_ok) {
|
||||
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
|
||||
td::TerminalIO::out() << "Tonlib is inited\n";
|
||||
@ -121,6 +149,8 @@ class TonlibCli : public td::actor::Actor {
|
||||
td::TerminalIO::out() << "exportkey [key_id] - export key\n";
|
||||
td::TerminalIO::out() << "setconfig <path> - set lite server config\n";
|
||||
td::TerminalIO::out() << "getstate <key_id> - get state of simple wallet with requested key\n";
|
||||
td::TerminalIO::out()
|
||||
<< "gethistory <key_id> - get history fo simple wallet with requested key (last 10 transactions)\n";
|
||||
td::TerminalIO::out() << "init <key_id> - init simple wallet with requested key\n";
|
||||
td::TerminalIO::out() << "transfer <from_key_id> <to_key_id> <amount> - transfer <amount> of grams from "
|
||||
"<from_key_id> to <to_key_id>.\n"
|
||||
@ -145,6 +175,8 @@ class TonlibCli : public td::actor::Actor {
|
||||
set_config(parser.read_word());
|
||||
} else if (cmd == "getstate") {
|
||||
get_state(parser.read_word());
|
||||
} else if (cmd == "gethistory") {
|
||||
get_history(parser.read_word());
|
||||
} else if (cmd == "init") {
|
||||
init_simple_wallet(parser.read_word());
|
||||
} else if (cmd == "transfer") {
|
||||
@ -157,7 +189,31 @@ class TonlibCli : public td::actor::Actor {
|
||||
}
|
||||
}
|
||||
|
||||
void on_adnl_result(td::uint64 id, td::Result<td::BufferSlice> res) {
|
||||
using tonlib_api::make_object;
|
||||
if (res.is_ok()) {
|
||||
send_query(make_object<tonlib_api::onLiteServerQueryResult>(id, res.move_as_ok().as_slice().str()),
|
||||
[](auto r_ok) { LOG_IF(ERROR, r_ok.is_error()) << r_ok.error(); });
|
||||
LOG(ERROR) << "!!!";
|
||||
} else {
|
||||
send_query(make_object<tonlib_api::onLiteServerQueryError>(
|
||||
id, make_object<tonlib_api::error>(res.error().code(), res.error().message().str())),
|
||||
[](auto r_ok) { LOG_IF(ERROR, r_ok.is_error()) << r_ok.error(); });
|
||||
}
|
||||
}
|
||||
|
||||
void on_tonlib_result(std::uint64_t id, tonlib_api::object_ptr<tonlib_api::Object> result) {
|
||||
if (id == 0) {
|
||||
if (result->get_id() == tonlib_api::updateSendLiteServerQuery::ID) {
|
||||
auto update = tonlib_api::move_object_as<tonlib_api::updateSendLiteServerQuery>(std::move(result));
|
||||
CHECK(!raw_client_.empty());
|
||||
send_closure(raw_client_, &ton::adnl::AdnlExtClient::send_query, "query", td::BufferSlice(update->data_),
|
||||
td::Timestamp::in(5),
|
||||
[actor_id = actor_id(this), id = update->id_](td::Result<td::BufferSlice> res) {
|
||||
send_closure(actor_id, &TonlibCli::on_adnl_result, id, std::move(res));
|
||||
});
|
||||
}
|
||||
}
|
||||
auto it = query_handlers_.find(id);
|
||||
if (it == query_handlers_.end()) {
|
||||
return;
|
||||
@ -468,6 +524,53 @@ class TonlibCli : public td::actor::Actor {
|
||||
td::TerminalIO::out() << to_string(r_res.ok());
|
||||
});
|
||||
}
|
||||
void get_history(td::Slice key) {
|
||||
if (key.empty()) {
|
||||
dump_keys();
|
||||
td::TerminalIO::out() << "Choose public key (hex prefix or #N)";
|
||||
cont_ = [this](td::Slice key) { this->get_state(key); };
|
||||
return;
|
||||
}
|
||||
auto r_address = to_account_address(key, false);
|
||||
if (r_address.is_error()) {
|
||||
td::TerminalIO::out() << "Unknown key id: [" << key << "]\n";
|
||||
return;
|
||||
}
|
||||
auto address = r_address.move_as_ok();
|
||||
using tonlib_api::make_object;
|
||||
send_query(make_object<tonlib_api::generic_getAccountState>(
|
||||
ton::move_tl_object_as<tonlib_api::accountAddress>(std::move(address.address))),
|
||||
[this, key = key.str()](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't get state: " << r_res.error() << "\n";
|
||||
return;
|
||||
}
|
||||
this->get_history(key, *r_res.move_as_ok());
|
||||
});
|
||||
}
|
||||
|
||||
void get_history(td::Slice key, tonlib_api::generic_AccountState& state) {
|
||||
auto r_address = to_account_address(key, false);
|
||||
if (r_address.is_error()) {
|
||||
td::TerminalIO::out() << "Unknown key id: [" << key << "]\n";
|
||||
return;
|
||||
}
|
||||
auto address = r_address.move_as_ok();
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::internal_transactionId> transaction_id;
|
||||
downcast_call(state, [&](auto& state) { transaction_id = std::move(state.account_state_->last_transaction_id_); });
|
||||
|
||||
send_query(
|
||||
tonlib_api::make_object<tonlib_api::raw_getTransactions>(
|
||||
ton::move_tl_object_as<tonlib_api::accountAddress>(std::move(address.address)), std::move(transaction_id)),
|
||||
[](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't get transactions: " << r_res.error() << "\n";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << to_string(r_res.move_as_ok()) << "\n";
|
||||
});
|
||||
}
|
||||
|
||||
void transfer(td::Slice from, td::Slice to, td::Slice grams) {
|
||||
auto r_from_address = to_account_address(from, true);
|
||||
@ -591,6 +694,10 @@ int main(int argc, char* argv[]) {
|
||||
options.config = std::move(data);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('c', "use_callbacks_for_network (for debug)", "do not use this", [&]() {
|
||||
options.use_callbacks_for_network = true;
|
||||
return td::Status::OK();
|
||||
});
|
||||
|
||||
auto S = p.run(argc, argv);
|
||||
if (S.is_error()) {
|
||||
|
@ -151,17 +151,11 @@ void FileDb::load_file_slice(RefId ref_id, td::int64 offset, td::int64 max_size,
|
||||
|
||||
auto v = R.move_as_ok();
|
||||
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise), file_hash = v.file_hash](td::Result<td::BufferSlice> R) mutable {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
auto data = R.move_as_ok();
|
||||
if (file_hash != sha256_bits256(data.as_slice())) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::protoviolation, PSTRING() << "db error: bad file hash"));
|
||||
} else {
|
||||
promise.set_value(std::move(data));
|
||||
}
|
||||
promise.set_value(R.move_as_ok());
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user