1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

updated tonlib

This commit is contained in:
ton 2019-10-31 22:14:52 +04:00
parent 3002321eb7
commit 11bd640ee0
12 changed files with 455 additions and 22 deletions

View file

@ -133,9 +133,11 @@ void sync(Client& client) {
sync_send(client, make_object<tonlib_api::sync>()).ensure();
}
static td::uint32 default_wallet_id{0};
std::string wallet_address(Client& client, const Key& key) {
return sync_send(client, make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(key.public_key)))
return sync_send(client,
make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(key.public_key, default_wallet_id)))
.move_as_ok()
->account_address_;
}
@ -171,6 +173,7 @@ AccountState get_account_state(Client& client, std::string address) {
case tonlib_api::generic_accountStateUninited::ID:
res.type = AccountState::Empty;
break;
case tonlib_api::generic_accountStateWalletV3::ID:
case tonlib_api::generic_accountStateWallet::ID:
res.type = AccountState::Wallet;
break;
@ -358,8 +361,9 @@ Wallet create_empty_wallet(Client& client) {
Wallet wallet{"", {key->public_key_, std::move(key->secret_)}};
auto account_address =
sync_send(client, make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(wallet.key.public_key)))
sync_send(client,
make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(wallet.key.public_key, default_wallet_id)))
.move_as_ok();
wallet.address = account_address->account_address_;
@ -529,6 +533,10 @@ int main(int argc, char* argv[]) {
Client client;
{
auto info = sync_send(client, make_object<tonlib_api::options_validateConfig>(
make_object<tonlib_api::config>(global_config_str, "", false, false)))
.move_as_ok();
default_wallet_id = static_cast<td::uint32>(info->default_wallet_id_);
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
make_object<tonlib_api::config>(global_config_str, "", false, false),
make_object<tonlib_api::keyStoreTypeDirectory>(keystore_dir))))

View file

@ -31,6 +31,7 @@
#include "smc-envelope/GenericAccount.h"
#include "smc-envelope/TestWallet.h"
#include "smc-envelope/Wallet.h"
#include "smc-envelope/WalletV3.h"
#include "smc-envelope/TestGiver.h"
#include "auto/tl/tonlib_api.hpp"
@ -41,6 +42,7 @@
#include "vm/boc.h"
#include "td/utils/as.h"
#include "td/utils/Random.h"
#include "td/utils/optional.h"
#include "td/utils/overloaded.h"
@ -121,7 +123,8 @@ std::string to_bytes(td::Ref<vm::Cell> cell) {
class AccountState {
public:
AccountState(block::StdAddress address, RawAccountState&& raw) : address_(std::move(address)), raw_(std::move(raw)) {
AccountState(block::StdAddress address, RawAccountState&& raw, td::uint32 wallet_id)
: address_(std::move(address)), raw_(std::move(raw)), wallet_id_(wallet_id) {
wallet_type_ = guess_type();
}
@ -162,6 +165,17 @@ class AccountState {
return tonlib_api::make_object<tonlib_api::wallet_accountState>(get_balance(), static_cast<td::uint32>(seqno),
to_transaction_id(raw().info), get_sync_time());
}
td::Result<tonlib_api::object_ptr<tonlib_api::wallet_v3_accountState>> to_wallet_v3_accountState() const {
if (wallet_type_ != WalletV3) {
return TonlibError::AccountTypeUnexpected("WalletV3");
}
auto wallet = ton::WalletV3(get_smc_state());
TRY_RESULT(seqno, wallet.get_seqno());
TRY_RESULT(wallet_id, wallet.get_wallet_id());
return tonlib_api::make_object<tonlib_api::wallet_v3_accountState>(
get_balance(), static_cast<td::uint32>(wallet_id), static_cast<td::uint32>(seqno),
to_transaction_id(raw().info), get_sync_time());
}
td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGiver_accountState() const {
if (wallet_type_ != Giver) {
@ -191,11 +205,15 @@ class AccountState {
TRY_RESULT(res, to_wallet_accountState());
return tonlib_api::make_object<tonlib_api::generic_accountStateWallet>(std::move(res));
}
case WalletV3: {
TRY_RESULT(res, to_wallet_v3_accountState());
return tonlib_api::make_object<tonlib_api::generic_accountStateWalletV3>(std::move(res));
}
}
UNREACHABLE();
}
enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet };
enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet, WalletV3 };
WalletType get_wallet_type() const {
return wallet_type_;
}
@ -235,6 +253,10 @@ class AccountState {
address_.addr) {
set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)});
wallet_type_ = WalletType::Wallet;
} else if (ton::GenericAccount::get_address(address_.workchain, ton::WalletV3::get_init_state(key, wallet_id_))
.addr == address_.addr) {
set_new_state({ton::WalletV3::get_init_code(), ton::WalletV3::get_init_data(key, wallet_id_)});
wallet_type_ = WalletType::WalletV3;
}
return wallet_type_;
}
@ -243,8 +265,8 @@ class AccountState {
if (wallet_type_ != WalletType::Empty) {
return wallet_type_;
}
set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)});
wallet_type_ = WalletType::Wallet;
set_new_state({ton::WalletV3::get_init_code(), ton::WalletV3::get_init_data(key, wallet_id_)});
wallet_type_ = WalletType::WalletV3;
return wallet_type_;
}
@ -274,6 +296,7 @@ class AccountState {
block::StdAddress address_;
RawAccountState raw_;
WalletType wallet_type_{Unknown};
td::uint32 wallet_id_{0};
bool has_new_state_{false};
WalletType guess_type() const {
@ -290,6 +313,9 @@ class AccountState {
if (code_hash == ton::Wallet::get_init_code_hash()) {
return WalletType::Wallet;
}
if (code_hash == ton::WalletV3::get_init_code_hash()) {
return WalletType::WalletV3;
}
LOG(WARNING) << "Unknown code hash: " << td::base64_encode(code_hash.as_slice());
return WalletType::Unknown;
}
@ -999,6 +1025,7 @@ bool TonlibClient::is_static_request(td::int32 id) {
case tonlib_api::raw_getAccountAddress::ID:
case tonlib_api::testWallet_getAccountAddress::ID:
case tonlib_api::wallet_getAccountAddress::ID:
case tonlib_api::wallet_v3_getAccountAddress::ID:
case tonlib_api::testGiver_getAccountAddress::ID:
case tonlib_api::packAccountAddress::ID:
case tonlib_api::unpackAccountAddress::ID:
@ -1062,6 +1089,12 @@ td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_initi
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
return ton::GenericAccount::get_address(0 /*zerochain*/, ton::Wallet::get_init_state(key));
}
td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_v3_initialAccountState& test_wallet_state) {
TRY_RESULT(key_bytes, get_public_key(test_wallet_state.public_key_));
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
return ton::GenericAccount::get_address(
0 /*zerochain*/, ton::WalletV3::get_init_state(key, static_cast<td::uint32>(test_wallet_state.wallet_id_)));
}
td::Result<block::StdAddress> get_account_address(td::Slice account_address) {
TRY_RESULT_PREFIX(address, block::StdAddress::parse(account_address), TonlibError::InvalidAccountAddress());
@ -1070,6 +1103,9 @@ td::Result<block::StdAddress> get_account_address(td::Slice account_address) {
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::raw_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
@ -1079,6 +1115,12 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::testWallet_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
@ -1088,6 +1130,20 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::wallet_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
}
return tonlib_api::make_object<tonlib_api::accountAddress>(r_account_address.ok().rserialize(true));
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::wallet_v3_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
@ -1249,12 +1305,14 @@ td::Result<TonlibClient::FullConfig> TonlibClient::validate_config(tonlib_api::o
res.o_master_config = std::move(o_master_config);
res.ignore_cache = config->ignore_cache_;
res.use_callbacks_for_network = config->use_callbacks_for_network_;
res.wallet_id = td::as<td::uint32>(res.config.zero_state_id.root_hash.as_slice().data());
return std::move(res);
}
void TonlibClient::set_config(FullConfig full_config) {
config_ = std::move(full_config.config);
config_generation_++;
wallet_id_ = full_config.wallet_id;
blockchain_name_ = config_.zero_state_id.root_hash.as_slice().str();
use_callbacks_for_network_ = full_config.use_callbacks_for_network;
@ -1280,7 +1338,7 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
if (r_config.is_error()) {
return status_to_tonlib_api(r_config.move_as_error());
}
return tonlib_api::make_object<tonlib_api::ok>();
return tonlib_api::make_object<tonlib_api::options_configInfo>(r_config.ok().wallet_id);
}
td::Status TonlibClient::do_request(tonlib_api::options_setConfig& request,
@ -1893,6 +1951,23 @@ class GenericCreateSendGrams : public TonlibQueryActor {
destination_->get_address());
break;
}
case AccountState::WalletV3: {
if (!private_key_) {
return TonlibError::EmptyField("private_key");
}
if (message.size() > ton::WalletV3::max_message_size) {
return TonlibError::MessageTooLong();
}
auto wallet = ton::WalletV3(source_->get_smc_state());
TRY_RESULT(seqno, wallet.get_seqno());
TRY_RESULT(wallet_id, wallet.get_wallet_id());
auto valid_until = source_->get_sync_time();
valid_until += send_grams_.timeout_ == 0 ? 60 : send_grams_.timeout_;
raw.valid_until = valid_until;
raw.message_body = ton::WalletV3::make_a_gift_message(private_key_.unwrap(), wallet_id, seqno, valid_until,
amount, message, destination_->get_address());
break;
}
}
raw.new_state = source_->get_new_state();
@ -2433,8 +2508,8 @@ td::Status TonlibClient::do_request(int_api::GetAccountState request,
auto actor_id = actor_id_++;
actors_[actor_id] = td::actor::create_actor<GetRawAccountState>(
"GetAccountState", client_.get_client(), request.address, actor_shared(this, actor_id),
promise.wrap([address = request.address](auto&& state) mutable {
return td::make_unique<AccountState>(std::move(address), std::move(state));
promise.wrap([address = request.address, wallet_id = wallet_id_](auto&& state) mutable {
return td::make_unique<AccountState>(std::move(address), std::move(state), wallet_id);
}));
return td::Status::OK();
}
@ -2481,6 +2556,11 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_getAccountAddress&
return TonlibError::Internal();
}
template <class P>
td::Status TonlibClient::do_request(const tonlib_api::wallet_v3_getAccountAddress& request, P&&) {
UNREACHABLE();
return TonlibError::Internal();
}
template <class P>
td::Status TonlibClient::do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&) {
UNREACHABLE();
return TonlibError::Internal();

View file

@ -65,6 +65,7 @@ class TonlibClient : public td::actor::Actor {
// Config
Config config_;
td::uint32 config_generation_{0};
td::uint32 wallet_id_;
std::string blockchain_name_;
bool ignore_cache_{false};
bool use_callbacks_for_network_{false};
@ -123,6 +124,7 @@ class TonlibClient : public td::actor::Actor {
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::raw_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testWallet_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_v3_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testGiver_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::packAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::unpackAccountAddress& request);
@ -151,6 +153,8 @@ class TonlibClient : public td::actor::Actor {
template <class P>
td::Status do_request(const tonlib_api::wallet_getAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::wallet_v3_getAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::packAccountAddress& request, P&&);
@ -198,6 +202,7 @@ class TonlibClient : public td::actor::Actor {
td::optional<Config> o_master_config;
bool use_callbacks_for_network;
bool ignore_cache;
td::uint32 wallet_id;
};
static td::Result<FullConfig> validate_config(tonlib_api::object_ptr<tonlib_api::config> config);
void set_config(FullConfig config);

View file

@ -79,6 +79,9 @@ struct TonlibError {
static td::Status InvalidPemKey() {
return td::Status::Error(400, "INVALID_PEM_KEY");
}
static td::Status NeedConfig() {
return td::Status::Error(400, "NeedConfig");
}
static td::Status MessageTooLong() {
return td::Status::Error(400, "MESSAGE_TOO_LONG");
}

View file

@ -81,7 +81,7 @@ class TonlibCli : public td::actor::Actor {
std::string key_dir{"."};
bool in_memory{false};
bool use_callbacks_for_network{false};
bool use_simple_wallet{false};
td::int32 wallet_version = 2;
bool ignore_cache{false};
bool one_shot{false};
@ -96,6 +96,7 @@ class TonlibCli : public td::actor::Actor {
td::actor::ActorOwn<tonlib::TonlibClient> client_;
std::uint64_t next_query_id_{1};
td::Promise<td::Slice> cont_;
td::uint32 wallet_id_;
struct KeyInfo {
std::string public_key;
@ -176,6 +177,10 @@ class TonlibCli : public td::actor::Actor {
? make_object<tonlib_api::config>(options_.config, options_.name,
options_.use_callbacks_for_network, options_.ignore_cache)
: nullptr;
auto config2 = !options_.config.empty()
? make_object<tonlib_api::config>(options_.config, options_.name,
options_.use_callbacks_for_network, options_.ignore_cache)
: nullptr;
tonlib_api::object_ptr<tonlib_api::KeyStoreType> ks_type;
if (options_.in_memory) {
@ -183,6 +188,14 @@ class TonlibCli : public td::actor::Actor {
} else {
ks_type = make_object<tonlib_api::keyStoreTypeDirectory>(options_.key_dir);
}
auto obj =
tonlib::TonlibClient::static_request(make_object<tonlib_api::options_validateConfig>(std::move(config2)));
if (obj->get_id() != tonlib_api::error::ID) {
auto info = ton::move_tl_object_as<tonlib_api::options_configInfo>(obj);
wallet_id_ = static_cast<td::uint32>(info->default_wallet_id_);
} else {
LOG(ERROR) << "Invalid config";
}
send_query(make_object<tonlib_api::init>(make_object<tonlib_api::options>(std::move(config), std::move(ks_type))),
[](auto r_ok) {
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
@ -519,7 +532,7 @@ class TonlibCli : public td::actor::Actor {
}));
} else {
send_query(make_object<tonlib_api::options_validateConfig>(std::move(config)), promise.wrap([](auto&& info) {
td::TerminalIO::out() << "Config is valid\n";
td::TerminalIO::out() << "Config is valid: " << to_string(info) << "\n";
return td::Unit();
}));
}
@ -824,11 +837,19 @@ class TonlibCli : public td::actor::Actor {
auto r_key_i = to_key_i(key);
using tonlib_api::make_object;
if (r_key_i.is_ok()) {
auto obj = options_.use_simple_wallet
? tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)))
: tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
auto obj = [&](td::int32 version) {
if (version == 1) {
return tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
}
if (version == 2) {
return tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
}
return tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(keys_[r_key_i.ok()].public_key, wallet_id_)));
UNREACHABLE();
}(options_.wallet_version);
if (obj->get_id() != tonlib_api::error::ID) {
Address res;
res.address = ton::move_tl_object_as<tonlib_api::accountAddress>(obj);
@ -1166,7 +1187,7 @@ class TonlibCli : public td::actor::Actor {
void init_simple_wallet(std::string key, size_t key_i, td::Slice password) {
using tonlib_api::make_object;
if (options_.use_simple_wallet) {
if (options_.wallet_version == 1) {
send_query(make_object<tonlib_api::testWallet_init>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy()),
td::SecureString(password))),
@ -1259,8 +1280,8 @@ int main(int argc, char* argv[]) {
options.use_callbacks_for_network = true;
return td::Status::OK();
});
p.add_option('S', "use-simple-wallet", "do not use this", [&]() {
options.use_simple_wallet = true;
p.add_option('W', "wallet-version", "do not use this", [&](td::Slice arg) {
options.wallet_version = td::to_integer<td::int32>(arg);
return td::Status::OK();
});