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:
parent
f40822b58a
commit
28df74178c
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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)) {
|
||||||
|
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_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>)
|
||||||
|
|
||||||
|
@ -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.
@ -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
|
||||||
|
@ -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");
|
||||||
{
|
{
|
||||||
|
@ -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()))
|
||||||
|
@ -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));
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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()) {
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user