1
0
mirror of https://github.com/danog/ton.git synced 2024-11-30 04:29:19 +01:00

updated tonlib

1. updated tonlib
2. fixed bug in state download
This commit is contained in:
ton 2019-09-22 10:14:09 +04:00
parent f40822b58a
commit 28df74178c
17 changed files with 362 additions and 115 deletions

View File

@ -258,6 +258,7 @@ td::Result<Transaction::Info> Transaction::validate() {
} }
Info res; Info res;
res.blkid = blkid; res.blkid = blkid;
res.now = trans.now;
res.prev_trans_lt = trans.prev_trans_lt; res.prev_trans_lt = trans.prev_trans_lt;
res.prev_trans_hash = trans.prev_trans_hash; res.prev_trans_hash = trans.prev_trans_hash;
res.transaction = root; res.transaction = root;
@ -281,6 +282,8 @@ td::Result<TransactionList::Info> TransactionList::validate() const {
Info res; Info res;
auto current_lt = lt; auto current_lt = lt;
auto current_hash = hash; auto current_hash = hash;
res.lt = lt;
res.hash = hash;
for (auto& root : list) { for (auto& root : list) {
const auto& blkid = blkids[c++]; const auto& blkid = blkids[c++];
Transaction transaction; Transaction transaction;

View File

@ -60,6 +60,7 @@ struct Transaction {
struct Info { struct Info {
ton::BlockIdExt blkid; ton::BlockIdExt blkid;
td::uint32 now;
ton::LogicalTime prev_trans_lt; ton::LogicalTime prev_trans_lt;
ton::Bits256 prev_trans_hash; ton::Bits256 prev_trans_hash;
td::Ref<vm::Cell> transaction; td::Ref<vm::Cell> transaction;
@ -74,21 +75,12 @@ struct TransactionList {
td::BufferSlice transactions_boc; td::BufferSlice transactions_boc;
struct Info { struct Info {
ton::LogicalTime lt;
ton::Bits256 hash;
std::vector<Transaction::Info> transactions; std::vector<Transaction::Info> transactions;
}; };
td::Result<Info> validate() const; 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 } // namespace block

View File

@ -53,17 +53,20 @@ SecureString create_empty<SecureString>(size_t size) {
template <class T> template <class T>
Result<T> read_file_impl(CSlice path, int64 size, int64 offset) { Result<T> read_file_impl(CSlice path, int64 size, int64 offset) {
TRY_RESULT(from_file, FileFd::open(path, FileFd::Read)); TRY_RESULT(from_file, FileFd::open(path, FileFd::Read));
TRY_RESULT(file_size, from_file.get_size());
if (offset < 0 || offset > file_size) {
return Status::Error("Failed to read file: invalid offset");
}
if (size == -1) { if (size == -1) {
TRY_RESULT(file_size, from_file.get_size()); size = file_size - offset;
size = file_size; } else if (size >= 0) {
if (size + offset > file_size) {
size = file_size - offset;
}
} }
if (size < 0) { if (size < 0) {
return Status::Error("Failed to read file: invalid size"); 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)); auto content = create_empty<T>(narrow_cast<size_t>(size));
TRY_RESULT(got_size, from_file.pread(as_mutable_slice(content), offset)); TRY_RESULT(got_size, from_file.pread(as_mutable_slice(content), offset));
if (got_size != static_cast<size_t>(size)) { if (got_size != static_cast<size_t>(size)) {

View File

@ -3,5 +3,5 @@ cmake_minimum_required(VERSION 2.8)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_library(wingetopt src/getopt.c src/getopt.h) 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>)

View File

@ -16,7 +16,7 @@ vector {t:Type} # [ t ] = Vector t;
error code:int32 message:string = Error; error code:int32 message:string = Error;
ok = Ok; 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; key public_key:string secret:secureBytes = Key;
inputKey key:key local_password:secureBytes = InputKey; inputKey key:key local_password:secureBytes = InputKey;
@ -31,17 +31,17 @@ accountAddress account_address:string = AccountAddress;
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 = 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.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.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> = raw.Transactions; raw.transactions transactions:vector<raw.Transaction> previous_transaction_id:internal.transactionId = raw.Transactions;
testWallet.initialAccountState public_key:string = testWallet.InitialAccountState; 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.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;
@ -51,6 +51,8 @@ generic.accountStateTestWallet account_state:testWallet.accountState = generic.A
generic.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState; generic.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState;
generic.accountStateUninited account_state:uninited.accountState = generic.AccountState; generic.accountStateUninited account_state:uninited.accountState = generic.AccountState;
updateSendLiteServerQuery id:int64 data:bytes = Update;
---functions--- ---functions---
init options:options = Ok; 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.getAccountState account_address:accountAddress = generic.AccountState;
generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 = Ok; 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.

View File

@ -9,6 +9,7 @@ set(TONLIB_SOURCE
tonlib/Config.cpp tonlib/Config.cpp
tonlib/ExtClient.cpp tonlib/ExtClient.cpp
tonlib/ExtClientLazy.cpp tonlib/ExtClientLazy.cpp
tonlib/ExtClientOutbound.cpp
tonlib/GenericAccount.cpp tonlib/GenericAccount.cpp
tonlib/KeyStorage.cpp tonlib/KeyStorage.cpp
tonlib/LastBlock.cpp tonlib/LastBlock.cpp
@ -21,6 +22,7 @@ set(TONLIB_SOURCE
tonlib/Config.h tonlib/Config.h
tonlib/ExtClient.h tonlib/ExtClient.h
tonlib/ExtClientLazy.h tonlib/ExtClientLazy.h
tonlib/ExtClientOutbound.h
tonlib/GenericAccount.h tonlib/GenericAccount.h
tonlib/KeyStorage.h tonlib/KeyStorage.h
tonlib/LastBlock.h tonlib/LastBlock.h

View File

@ -172,16 +172,17 @@ TEST(Tonlib, InitClose) {
{ {
Client client; Client client;
sync_send(client, make_object<tonlib_api::close>()).ensure(); 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; Client client;
sync_send(client, make_object<tonlib_api::init>(nullptr)).ensure_error(); 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(); .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>("", "fdhskfds", false)))
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", "."))).ensure(); .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();
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>("", ".", false))).ensure_error();
td::Slice bad_config = R"abc( 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::testGiver_getAccountState>()).ensure_error();
sync_send(client, make_object<tonlib_api::close>()).ensure(); 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::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; Client client;
// init // 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 local_password = td::SecureString("local password");
auto mnemonic_password = td::SecureString("mnemonic password"); auto mnemonic_password = td::SecureString("mnemonic password");
{ {

View File

@ -170,12 +170,12 @@ void dump_transaction_history(Client& client, std::string address) {
make_object<tonlib_api::accountAddress>(address), std::move(tid))) make_object<tonlib_api::accountAddress>(address), std::move(tid)))
.move_as_ok(); .move_as_ok();
CHECK(got_transactions->transactions_.size() > 0); 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_) { for (auto& txn : got_transactions->transactions_) {
LOG(ERROR) << to_string(txn); LOG(ERROR) << to_string(txn);
cnt++; cnt++;
} }
tid = std::move(got_transactions->transactions_.back()->previous_transaction_id_); tid = std::move(got_transactions->previous_transaction_id_);
} }
LOG(ERROR) << cnt; LOG(ERROR) << cnt;
} }
@ -196,7 +196,8 @@ int main(int argc, char* argv[]) {
Client client; 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)); //dump_transaction_history(client, get_test_giver_address(client));
auto wallet_a = create_wallet(client); auto wallet_a = create_wallet(client);
@ -208,7 +209,8 @@ int main(int argc, char* argv[]) {
return 0; return 0;
{ {
// init // 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>( auto key = sync_send(client, make_object<tonlib_api::createNewKey>(
td::SecureString("local"), td::SecureString("mnemonic"), td::SecureString())) td::SecureString("local"), td::SecureString("mnemonic"), td::SecureString()))

View File

@ -21,10 +21,10 @@
#include "tonlib/LastBlock.h" #include "tonlib/LastBlock.h"
namespace tonlib { 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)); auto query_id = last_block_queries_.create(std::move(promise));
td::Promise<ton::BlockIdExt> P = [query_id, self = this, td::Promise<LastBlockInfo> P = [query_id, self = this,
actor_id = td::actor::actor_id()](td::Result<ton::BlockIdExt> result) { actor_id = td::actor::actor_id()](td::Result<LastBlockInfo> result) {
send_lambda(actor_id, [self, query_id, result = std::move(result)]() mutable { send_lambda(actor_id, [self, query_id, result = std::move(result)]() mutable {
self->last_block_queries_.extract(query_id).set_result(std::move(result)); self->last_block_queries_.extract(query_id).set_result(std::move(result));
}); });

View File

@ -29,6 +29,7 @@
namespace tonlib { namespace tonlib {
class LastBlock; class LastBlock;
struct LastBlockInfo;
struct ExtClientRef { struct ExtClientRef {
td::actor::ActorId<ton::adnl::AdnlExtClient> andl_ext_client_; td::actor::ActorId<ton::adnl::AdnlExtClient> andl_ext_client_;
td::actor::ActorId<LastBlock> last_block_actor_; td::actor::ActorId<LastBlock> last_block_actor_;
@ -49,7 +50,7 @@ class ExtClient {
return client_; return client_;
} }
void with_last_block(td::Promise<ton::BlockIdExt> promise); void with_last_block(td::Promise<LastBlockInfo> promise);
template <class QueryT> template <class QueryT>
void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise) { void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise) {
@ -74,7 +75,7 @@ class ExtClient {
private: private:
ExtClientRef client_; ExtClientRef client_;
td::Container<td::Promise<td::BufferSlice>> queries_; 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); void send_raw_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise);
}; };

View File

@ -23,15 +23,12 @@
#include "lite-client/lite-client-common.h" #include "lite-client/lite-client-common.h"
namespace tonlib { namespace tonlib {
LastBlock::LastBlock(ExtClientRef client, ton::ZeroStateIdExt zero_state_id, ton::BlockIdExt last_block_id, LastBlock::LastBlock(ExtClientRef client, State state, td::unique_ptr<Callback> callback)
td::actor::ActorShared<> parent) { : state_(std::move(state)), callback_(std::move(callback)) {
zero_state_id_ = std::move(zero_state_id);
mc_last_block_id_ = std::move(last_block_id);
client_.set_client(client); 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()) { if (promises_.empty()) {
do_get_last_block(); do_get_last_block();
} }
@ -39,13 +36,16 @@ void LastBlock::get_last_block(td::Promise<ton::BlockIdExt> promise) {
} }
void LastBlock::do_get_last_block() { void LastBlock::do_get_last_block() {
client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(), //client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
[this](auto r_info) { this->on_masterchain_info(std::move(r_info)); }); //[this](auto r_info) { this->on_masterchain_info(std::move(r_info)); });
return; //return;
//liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof; //liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
client_.send_query( client_.send_query(
ton::lite_api::liteServer_getBlockProof(0, create_tl_lite_block_id(mc_last_block_id_), nullptr), ton::lite_api::liteServer_getBlockProof(0, create_tl_lite_block_id(state_.last_key_block_id), nullptr),
[this, from = mc_last_block_id_](auto r_block_proof) { this->on_block_proof(from, std::move(r_block_proof)); }); [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( td::Result<bool> LastBlock::process_block_proof(
@ -60,6 +60,12 @@ td::Result<bool> LastBlock::process_block_proof(
} }
TRY_STATUS(chain->validate()); TRY_STATUS(chain->validate());
update_mc_last_block(chain->to); 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; 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) { 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)); auto r_is_ready = process_block_proof(from, std::move(r_block_proof));
if (r_is_ready.is_error()) { 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; return;
} }
auto is_ready = r_is_ready.move_as_ok(); auto is_ready = r_is_ready.move_as_ok();
if (is_ready) { if (is_ready) {
for (auto& promise : promises_) { for (auto& promise : promises_) {
auto copy = mc_last_block_id_; LastBlockInfo res;
promise.set_value(std::move(copy)); res.id = state_.last_block_id;
res.utime = state_.utime;
promise.set_value(std::move(res));
} }
promises_.clear(); promises_.clear();
} else { } else {
@ -93,8 +101,10 @@ void LastBlock::on_masterchain_info(
LOG(WARNING) << "Failed liteServer_getMasterchainInfo " << r_info.error(); LOG(WARNING) << "Failed liteServer_getMasterchainInfo " << r_info.error();
} }
for (auto& promise : promises_) { for (auto& promise : promises_) {
auto copy = mc_last_block_id_; LastBlockInfo res;
promise.set_value(std::move(copy)); res.id = state_.last_block_id;
res.utime = state_.utime;
promise.set_value(std::move(res));
} }
promises_.clear(); promises_.clear();
} }
@ -105,17 +115,17 @@ void LastBlock::update_zero_state(ton::ZeroStateIdExt zero_state_id) {
return; return;
} }
if (!zero_state_id_.is_valid()) { if (!state_.zero_state_id.is_valid()) {
LOG(INFO) << "Init zerostate: " << zero_state_id.to_str(); 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; return;
} }
if (zero_state_id_ == zero_state_id_) { if (state_.zero_state_id == state_.zero_state_id) {
return; 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(); << zero_state_id.to_str();
// TODO: all other updates will be inconsitent. // TODO: all other updates will be inconsitent.
// One will have to restart ton client // 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"; LOG(ERROR) << "Ignore invalid masterchain block";
return; return;
} }
if (!mc_last_block_id_.is_valid() || mc_last_block_id_.id.seqno < mc_block_id.id.seqno) { if (!state_.last_block_id.is_valid() || state_.last_block_id.id.seqno < mc_block_id.id.seqno) {
mc_last_block_id_ = mc_block_id; state_.last_block_id = mc_block_id;
LOG(INFO) << "Update masterchain block id: " << mc_last_block_id_.to_str(); 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 } // namespace tonlib

View File

@ -22,21 +22,35 @@
#include "tonlib/ExtClient.h" #include "tonlib/ExtClient.h"
namespace tonlib { namespace tonlib {
struct LastBlockInfo {
ton::BlockIdExt id;
td::int64 utime{0};
};
class LastBlock : public td::actor::Actor { class LastBlock : public td::actor::Actor {
public: public:
explicit LastBlock(ExtClientRef client, ton::ZeroStateIdExt zero_state_id, ton::BlockIdExt last_block_id, struct State {
td::actor::ActorShared<> parent); 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: private:
ExtClient client_; ExtClient client_;
ton::ZeroStateIdExt zero_state_id_; State state_;
ton::BlockIdExt mc_last_block_id_; td::unique_ptr<Callback> callback_;
std::vector<td::Promise<ton::BlockIdExt>> promises_; std::vector<td::Promise<LastBlockInfo>> promises_;
td::actor::ActorShared<> parent_;
void do_get_last_block(); void do_get_last_block();
void on_masterchain_info(td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_masterchainInfo>> r_info); 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_zero_state(ton::ZeroStateIdExt zero_state_id);
void update_mc_last_block(ton::BlockIdExt mc_block_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 } // namespace tonlib

View File

@ -19,6 +19,7 @@
#include "TonlibClient.h" #include "TonlibClient.h"
#include "tonlib/ExtClientLazy.h" #include "tonlib/ExtClientLazy.h"
#include "tonlib/ExtClientOutbound.h"
#include "tonlib/GenericAccount.h" #include "tonlib/GenericAccount.h"
#include "tonlib/LastBlock.h" #include "tonlib/LastBlock.h"
#include "tonlib/TestWallet.h" #include "tonlib/TestWallet.h"
@ -73,6 +74,7 @@ struct RawAccountState {
td::Ref<vm::CellSlice> code; td::Ref<vm::CellSlice> code;
td::Ref<vm::CellSlice> data; td::Ref<vm::CellSlice> data;
block::AccountState::Info info; block::AccountState::Info info;
td::int64 sync_utime = 0;
}; };
td::Result<td::int64> to_balance_or_throw(td::Ref<vm::CellSlice> balance_ref) { 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_; block::StdAddress address_;
td::Promise<RawAccountState> promise_; td::Promise<RawAccountState> promise_;
ExtClient client_; 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) { 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)))); 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) { td::Result<ton::tl_object_ptr<ton::lite_api::liteServer_accountState>> r_account_state) {
TRY_RESULT(raw_account_state, std::move(r_account_state)); TRY_RESULT(raw_account_state, std::move(r_account_state));
auto account_state = create_account_state(std::move(raw_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(); auto serialized_state = account_state.state.clone();
RawAccountState res; RawAccountState res;
res.info = std::move(info); res.info = std::move(info);
res.sync_utime = last_block_.utime;
auto cell = res.info.root; auto cell = res.info.root;
if (cell.is_null()) { if (cell.is_null()) {
return res; return res;
@ -222,14 +225,14 @@ class GetRawAccountState : public td::actor::Actor {
} }
void start_up() override { 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()) { if (r_last_block.is_error()) {
return self->check(r_last_block.move_as_error()); return self->check(r_last_block.move_as_error());
} }
self->last_block_ = r_last_block.move_as_ok(); self->last_block_ = r_last_block.move_as_ok();
self->client_.send_query( 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>( ton::create_tl_object<ton::lite_api::liteServer_accountId>(
self->address_.workchain, self->address_.addr)), self->address_.workchain, self->address_.addr)),
[self](auto r_state) { self->with_account_state(std::move(r_state)); }); [self](auto r_state) { self->with_account_state(std::move(r_state)); });
@ -263,28 +266,68 @@ ExtClientRef TonlibClient::get_client_ref() {
return 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() { void TonlibClient::init_ext_client() {
auto lite_clients_size = config_.lite_clients.size(); if (use_callbacks_for_network_) {
CHECK(lite_clients_size != 0); class Callback : public ExtClientOutbound::Callback {
auto lite_client_id = td::Random::fast(0, td::narrow_cast<int>(lite_clients_size) - 1); public:
auto& lite_client = config_.lite_clients[lite_client_id]; explicit Callback(td::actor::ActorShared<TonlibClient> parent) : parent_(std::move(parent)) {
class Callback : public ExtClientLazy::Callback { }
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);
auto& lite_client = config_.lite_clients[lite_client_id];
class Callback : public ExtClientLazy::Callback {
public:
explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) {
}
private:
td::actor::ActorShared<> parent_;
};
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_++;
class Callback : public LastBlock::Callback {
public: public:
explicit Callback(td::actor::ActorShared<> parent) : parent_(std::move(parent)) { Callback(td::actor::ActorShared<TonlibClient> client) : client_(std::move(client)) {
}
void on_state_changes(LastBlock::State state) override {
//TODO
} }
private: private:
td::actor::ActorShared<> parent_; td::actor::ActorShared<TonlibClient> client_;
}; };
ref_cnt_++; LastBlock::State state;
raw_client_ = ExtClientLazy::create(lite_client.adnl_id, lite_client.address, //state.zero_state_id = ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash,
td::make_unique<Callback>(td::actor::actor_shared())); //config_.zero_state_id.file_hash),
ref_cnt_++; state.last_block_id = config_.zero_state_id;
raw_last_block_ = td::actor::create_actor<LastBlock>( state.last_key_block_id = config_.zero_state_id;
"LastBlock", get_client_ref(),
ton::ZeroStateIdExt(config_.zero_state_id.id.workchain, config_.zero_state_id.root_hash, raw_last_block_ = td::actor::create_actor<LastBlock>("LastBlock", get_client_ref(), std::move(state),
config_.zero_state_id.file_hash), td::make_unique<Callback>(td::actor::actor_shared(this)));
config_.zero_state_id, td::actor::actor_shared());
client_.set_client(get_client_ref()); 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"); return td::Status::Error(400, "Field options must not be empty");
} }
TRY_STATUS(key_storage_.set_directory(request.options_->keystore_directory_)); 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()) { if (!request.options_->config_.empty()) {
TRY_STATUS(set_config(std::move(request.options_->config_))); 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); config_ = std::move(new_config);
init_ext_client(); init_ext_client();
init_last_block();
return td::Status::OK(); 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>()); promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
return td::Status::OK(); return td::Status::OK();
} }
td::Status TonlibClient::do_request(const tonlib_api::options_setConfig& request, td::Status TonlibClient::do_request(const tonlib_api::options_setConfig& request,
td::Promise<object_ptr<tonlib_api::ok>>&& promise) { td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
TRY_STATUS(set_config(request.config_)); 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(); 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) { 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, return tonlib_api::make_object<tonlib_api::internal_transactionId>(info.last_trans_lt,
info.last_trans_hash.as_slice().str()); 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(); .str();
} }
return tonlib_api::make_object<tonlib_api::raw_accountState>(raw_state.balance, std::move(code), std::move(data), 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) { 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>( 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, tonlib_api::make_object<tonlib_api::internal_transactionId>(info.prev_trans_lt,
info.prev_trans_hash.as_slice().str()), info.prev_trans_hash.as_slice().str()),
fees, std::move(in_msg), std::move(out_msgs)); 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))); TRY_RESULT(raw_transaction, to_raw_transaction(std::move(transaction)));
transactions.push_back(std::move(raw_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( 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) { if (seqno == cs.fetch_ulong_eof) {
return td::Status::Error("Failed to parse seq_no"); 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), return tonlib_api::make_object<tonlib_api::testWallet_accountState>(
to_transaction_id(raw_state.info)); 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( 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) { if (seqno == cs.fetch_ulong_eof) {
return td::Status::Error("Failed to parse seq_no"); 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), return tonlib_api::make_object<tonlib_api::testGiver_accountState>(
to_transaction_id(raw_state.info)); 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( td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_accountState(
RawAccountState&& raw_state) { RawAccountState&& raw_state) {
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)); 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(); 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(); 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 } // namespace tonlib

View File

@ -22,6 +22,7 @@
#include "tonlib/Config.h" #include "tonlib/Config.h"
#include "tonlib/ExtClient.h" #include "tonlib/ExtClient.h"
#include "tonlib/ExtClientOutbound.h"
#include "tonlib/KeyStorage.h" #include "tonlib/KeyStorage.h"
#include "td/actor/actor.h" #include "td/actor/actor.h"
@ -44,6 +45,9 @@ class TonlibClient : public td::actor::Actor {
td::unique_ptr<TonlibCallback> callback_; td::unique_ptr<TonlibCallback> callback_;
Config config_; Config config_;
bool use_callbacks_for_network_{false};
td::actor::ActorId<ExtClientOutbound> ext_client_outbound_;
// KeyStorage // KeyStorage
KeyStorage key_storage_; KeyStorage key_storage_;
@ -54,6 +58,7 @@ class TonlibClient : public td::actor::Actor {
ExtClientRef get_client_ref(); ExtClientRef get_client_ref();
void init_ext_client(); void init_ext_client();
void init_last_block();
bool is_closing_{false}; bool is_closing_{false};
td::uint32 ref_cnt_{1}; 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::Status do_request(const tonlib_api::changeLocalPassword& request,
td::Promise<object_ptr<tonlib_api::key>>&& promise); 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 } // namespace tonlib

View File

@ -5,12 +5,17 @@
#include "td/utils/Parser.h" #include "td/utils/Parser.h"
#include "td/utils/port/signals.h" #include "td/utils/port/signals.h"
#include "td/utils/port/path.h" #include "td/utils/port/path.h"
#include "td/utils/Random.h"
#include "terminal/terminal.h" #include "terminal/terminal.h"
#include "tonlib/TonlibClient.h" #include "tonlib/TonlibClient.h"
#include "tonlib/TonlibCallback.h" #include "tonlib/TonlibCallback.h"
#include "tonlib/ExtClientLazy.h"
#include "auto/tl/tonlib_api.hpp"
#include <iostream> #include <iostream>
#include <map> #include <map>
@ -20,6 +25,7 @@ class TonlibCli : public td::actor::Actor {
bool enable_readline{true}; bool enable_readline{true};
std::string config; std::string config;
std::string key_dir{"."}; std::string key_dir{"."};
bool use_callbacks_for_network{false};
}; };
TonlibCli(Options options) : options_(std::move(options)) { 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_; 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}; bool is_closing_{false};
td::uint32 ref_cnt_{1}; td::uint32 ref_cnt_{1};
@ -79,8 +87,28 @@ class TonlibCli : public td::actor::Actor {
load_keys(); 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; 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) { [](auto r_ok) {
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error(); LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
td::TerminalIO::out() << "Tonlib is inited\n"; 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() << "exportkey [key_id] - export key\n";
td::TerminalIO::out() << "setconfig <path> - set lite server config\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() << "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() << "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 " td::TerminalIO::out() << "transfer <from_key_id> <to_key_id> <amount> - transfer <amount> of grams from "
"<from_key_id> to <to_key_id>.\n" "<from_key_id> to <to_key_id>.\n"
@ -145,6 +175,8 @@ class TonlibCli : public td::actor::Actor {
set_config(parser.read_word()); set_config(parser.read_word());
} else if (cmd == "getstate") { } else if (cmd == "getstate") {
get_state(parser.read_word()); get_state(parser.read_word());
} else if (cmd == "gethistory") {
get_history(parser.read_word());
} else if (cmd == "init") { } else if (cmd == "init") {
init_simple_wallet(parser.read_word()); init_simple_wallet(parser.read_word());
} else if (cmd == "transfer") { } 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) { 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); auto it = query_handlers_.find(id);
if (it == query_handlers_.end()) { if (it == query_handlers_.end()) {
return; return;
@ -468,6 +524,53 @@ class TonlibCli : public td::actor::Actor {
td::TerminalIO::out() << to_string(r_res.ok()); 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) { void transfer(td::Slice from, td::Slice to, td::Slice grams) {
auto r_from_address = to_account_address(from, true); auto r_from_address = to_account_address(from, true);
@ -591,6 +694,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('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); auto S = p.run(argc, argv);
if (S.is_error()) { if (S.is_error()) {

View File

@ -151,19 +151,13 @@ void FileDb::load_file_slice(RefId ref_id, td::int64 offset, td::int64 max_size,
auto v = R.move_as_ok(); auto v = R.move_as_ok();
auto P = td::PromiseCreator::lambda( auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
[promise = std::move(promise), file_hash = v.file_hash](td::Result<td::BufferSlice> R) mutable { if (R.is_error()) {
if (R.is_error()) { promise.set_error(R.move_as_error());
promise.set_error(R.move_as_error()); } else {
} else { promise.set_value(R.move_as_ok());
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));
}
}
});
td::actor::create_actor<db::ReadFile>("readfile", get_file_name(ref_id, false), offset, max_size, std::move(P)) td::actor::create_actor<db::ReadFile>("readfile", get_file_name(ref_id, false), offset, max_size, std::move(P))
.release(); .release();