mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Merge branch 'testnet' into block-generation
This commit is contained in:
commit
f4fd3ff3be
246 changed files with 7895 additions and 5430 deletions
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Use \"OFF\" for a static build." ON)
|
||||
|
||||
|
|
|
|||
|
|
@ -333,8 +333,8 @@ TEST(Tonlib, ConfigParseBug) {
|
|||
unsigned char buff[128];
|
||||
int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), literal.begin(), literal.end());
|
||||
CHECK(bits >= 0);
|
||||
auto slice = vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize();
|
||||
block::Config::do_get_gas_limits_prices(std::move(slice), 21).ensure();
|
||||
auto cell = vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize();
|
||||
block::Config::do_get_gas_limits_prices(vm::load_cell_slice(cell), 21).ensure();
|
||||
}
|
||||
|
||||
TEST(Tonlib, EncryptionApi) {
|
||||
|
|
@ -467,15 +467,20 @@ TEST(Tonlib, KeysApi) {
|
|||
make_object<tonlib_api::deleteKey>(make_object<tonlib_api::key>(key->public_key_, key->secret_.copy())))
|
||||
.move_as_ok();
|
||||
|
||||
auto err1 = sync_send(client, make_object<tonlib_api::importKey>(
|
||||
new_local_password.copy(), td::SecureString("wrong password"),
|
||||
make_object<tonlib_api::exportedKey>(copy_word_list())))
|
||||
.move_as_error();
|
||||
auto err1 = sync_send(
|
||||
client, make_object<tonlib_api::importKey>(new_local_password.copy(), td::SecureString("wrong password"),
|
||||
make_object<tonlib_api::exportedKey>(copy_word_list())));
|
||||
if (err1.is_ok()) {
|
||||
if (err1.ok()->public_key_ != key->public_key_) {
|
||||
err1 = td::Status::Error("imported key successfully, but the public key is different");
|
||||
}
|
||||
}
|
||||
err1.ensure_error();
|
||||
auto err2 =
|
||||
sync_send(client, make_object<tonlib_api::importKey>(new_local_password.copy(), td::SecureString(),
|
||||
make_object<tonlib_api::exportedKey>(copy_word_list())))
|
||||
.move_as_error();
|
||||
LOG(INFO) << err1 << " | " << err2;
|
||||
make_object<tonlib_api::exportedKey>(copy_word_list())));
|
||||
err2.ensure_error();
|
||||
LOG(INFO) << err1.move_as_error() << " | " << err2.move_as_error();
|
||||
auto imported_key =
|
||||
sync_send(client, make_object<tonlib_api::importKey>(new_local_password.copy(), mnemonic_password.copy(),
|
||||
make_object<tonlib_api::exportedKey>(copy_word_list())))
|
||||
|
|
@ -609,7 +614,30 @@ TEST(Tonlib, ConfigCache) {
|
|||
"seqno": 0,
|
||||
"root_hash": "gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=",
|
||||
"file_hash": "Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg="
|
||||
}
|
||||
},
|
||||
"hardforks": [
|
||||
{
|
||||
"file_hash": "jF3RTD+OyOoP+OI9oIjdV6M8EaOh9E+8+c3m5JkPYdg=",
|
||||
"seqno": 5141579,
|
||||
"root_hash": "6JSqIYIkW7y8IorxfbQBoXiuY3kXjcoYgQOxTJpjXXA=",
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808
|
||||
},
|
||||
{
|
||||
"file_hash": "WrNoMrn5UIVPDV/ug/VPjYatvde8TPvz5v1VYHCLPh8=",
|
||||
"seqno": 5172980,
|
||||
"root_hash": "054VCNNtUEwYGoRe1zjH+9b1q21/MeM+3fOo76Vcjes=",
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808
|
||||
},
|
||||
{
|
||||
"file_hash": "xRaxgUwgTXYFb16YnR+Q+VVsczLl6jmYwvzhQ/ncrh4=",
|
||||
"seqno": 5176527,
|
||||
"root_hash": "SoPLqMe9Dz26YJPOGDOHApTSe5i0kXFtRmRh/zPMGuI=",
|
||||
"workchain": -1,
|
||||
"shard": -9223372036854775808
|
||||
}
|
||||
]
|
||||
}
|
||||
})abc";
|
||||
auto custom = R"abc({
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "smc-envelope/GenericAccount.h"
|
||||
#include "smc-envelope/ManualDns.h"
|
||||
#include "smc-envelope/WalletV3.h"
|
||||
#include "smc-envelope/WalletV4.h"
|
||||
#include "smc-envelope/HighloadWallet.h"
|
||||
#include "smc-envelope/HighloadWalletV2.h"
|
||||
#include "smc-envelope/PaymentChannel.h"
|
||||
|
|
@ -227,6 +228,14 @@ td::Result<ton::WalletV3::InitData> to_init_data(const tonlib_api::wallet_v3_ini
|
|||
return std::move(init_data);
|
||||
}
|
||||
|
||||
td::Result<ton::WalletV4::InitData> to_init_data(const tonlib_api::wallet_v4_initialAccountState& wallet_state) {
|
||||
TRY_RESULT(key_bytes, get_public_key(wallet_state.public_key_));
|
||||
ton::WalletV4::InitData init_data;
|
||||
init_data.public_key = td::SecureString(key_bytes.key);
|
||||
init_data.wallet_id = static_cast<td::uint32>(wallet_state.wallet_id_);
|
||||
return std::move(init_data);
|
||||
}
|
||||
|
||||
td::Result<ton::RestrictedWallet::InitData> to_init_data(const tonlib_api::rwallet_initialAccountState& rwallet_state) {
|
||||
TRY_RESULT(init_key_bytes, get_public_key(rwallet_state.init_public_key_));
|
||||
TRY_RESULT(key_bytes, get_public_key(rwallet_state.public_key_));
|
||||
|
|
@ -318,6 +327,16 @@ class AccountState {
|
|||
return tonlib_api::make_object<tonlib_api::wallet_v3_accountState>(static_cast<td::uint32>(wallet_id),
|
||||
static_cast<td::uint32>(seqno));
|
||||
}
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::wallet_v4_accountState>> to_wallet_v4_accountState() const {
|
||||
if (wallet_type_ != WalletV4) {
|
||||
return TonlibError::AccountTypeUnexpected("WalletV4");
|
||||
}
|
||||
auto wallet = ton::WalletV4(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_v4_accountState>(static_cast<td::uint32>(wallet_id),
|
||||
static_cast<td::uint32>(seqno));
|
||||
}
|
||||
td::Result<tonlib_api::object_ptr<tonlib_api::wallet_highload_v1_accountState>> to_wallet_highload_v1_accountState()
|
||||
const {
|
||||
if (wallet_type_ != HighloadWalletV1) {
|
||||
|
|
@ -419,6 +438,8 @@ class AccountState {
|
|||
return f(to_dns_accountState());
|
||||
case PaymentChannel:
|
||||
return f(to_payment_channel_accountState());
|
||||
case WalletV4:
|
||||
return f(to_wallet_v4_accountState());
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
@ -457,7 +478,8 @@ class AccountState {
|
|||
HighloadWalletV2,
|
||||
ManualDns,
|
||||
PaymentChannel,
|
||||
RestrictedWallet
|
||||
RestrictedWallet,
|
||||
WalletV4
|
||||
};
|
||||
WalletType get_wallet_type() const {
|
||||
return wallet_type_;
|
||||
|
|
@ -476,6 +498,7 @@ class AccountState {
|
|||
case AccountState::HighloadWalletV1:
|
||||
case AccountState::HighloadWalletV2:
|
||||
case AccountState::RestrictedWallet:
|
||||
case AccountState::WalletV4:
|
||||
return true;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
|
@ -496,6 +519,8 @@ class AccountState {
|
|||
return td::make_unique<ton::HighloadWalletV2>(get_smc_state());
|
||||
case AccountState::RestrictedWallet:
|
||||
return td::make_unique<ton::RestrictedWallet>(get_smc_state());
|
||||
case AccountState::WalletV4:
|
||||
return td::make_unique<ton::WalletV4>(get_smc_state());
|
||||
}
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
|
|
@ -553,6 +578,23 @@ class AccountState {
|
|||
break;
|
||||
}
|
||||
},
|
||||
[&](tonlib_api::wallet_v4_initialAccountState& v4wallet) {
|
||||
for (auto revision : ton::SmartContractCode::get_revisions(ton::SmartContractCode::WalletV4)) {
|
||||
auto init_data = to_init_data(v4wallet);
|
||||
if (init_data.is_error()) {
|
||||
continue;
|
||||
}
|
||||
auto wallet = ton::WalletV4::create(init_data.move_as_ok(), revision);
|
||||
if (!(wallet->get_address(ton::masterchainId) == address_ ||
|
||||
wallet->get_address(ton::basechainId) == address_)) {
|
||||
continue;
|
||||
}
|
||||
wallet_type_ = WalletType::WalletV4;
|
||||
wallet_revision_ = revision;
|
||||
set_new_state(wallet->get_state());
|
||||
break;
|
||||
}
|
||||
},
|
||||
[&](tonlib_api::rwallet_initialAccountState& rwallet) {
|
||||
for (auto revision : ton::SmartContractCode::get_revisions(ton::SmartContractCode::RestrictedWallet)) {
|
||||
auto r_init_data = to_init_data(rwallet);
|
||||
|
|
@ -596,7 +638,7 @@ class AccountState {
|
|||
return wallet_type_;
|
||||
}
|
||||
auto wallet_id = static_cast<td::uint32>(address_.workchain + wallet_id_);
|
||||
ton::WalletV3::InitData init_data{key.as_octet_string(), wallet_id};
|
||||
ton::WalletInterface::DefaultInitData init_data{key.as_octet_string(), wallet_id};
|
||||
auto o_revision = ton::WalletV3::guess_revision(address_, init_data);
|
||||
if (o_revision) {
|
||||
wallet_type_ = WalletType::WalletV3;
|
||||
|
|
@ -604,6 +646,13 @@ class AccountState {
|
|||
set_new_state(ton::WalletV3::get_init_state(wallet_revision_, init_data));
|
||||
return wallet_type_;
|
||||
}
|
||||
o_revision = ton::WalletV4::guess_revision(address_, init_data);
|
||||
if (o_revision) {
|
||||
wallet_type_ = WalletType::WalletV4;
|
||||
wallet_revision_ = o_revision.value();
|
||||
set_new_state(ton::WalletV4::get_init_state(wallet_revision_, init_data));
|
||||
return wallet_type_;
|
||||
}
|
||||
o_revision = ton::HighloadWalletV2::guess_revision(address_, init_data);
|
||||
if (o_revision) {
|
||||
wallet_type_ = WalletType::HighloadWalletV2;
|
||||
|
|
@ -681,6 +730,12 @@ class AccountState {
|
|||
wallet_revision_ = o_revision.value();
|
||||
return wallet_type_;
|
||||
}
|
||||
o_revision = ton::WalletV4::guess_revision(code_hash);
|
||||
if (o_revision) {
|
||||
wallet_type_ = WalletType::WalletV4;
|
||||
wallet_revision_ = o_revision.value();
|
||||
return wallet_type_;
|
||||
}
|
||||
o_revision = ton::HighloadWalletV2::guess_revision(code_hash);
|
||||
if (o_revision) {
|
||||
wallet_type_ = WalletType::HighloadWalletV2;
|
||||
|
|
@ -1916,7 +1971,7 @@ class RunEmulator : public TonlibQueryActor {
|
|||
ton::UnixTime now = account_state_->get_sync_time();
|
||||
bool is_special = address.workchain == ton::masterchainId && config->is_special_smartcontract(address.addr);
|
||||
block::Account account(address.workchain, address.addr.bits());
|
||||
if (!account.unpack(std::move(shard_account), td::Ref<vm::CellSlice>(), now, is_special)) {
|
||||
if (!account.unpack(std::move(shard_account), now, is_special)) {
|
||||
check(td::Status::Error("Can't unpack shard account"));
|
||||
return;
|
||||
}
|
||||
|
|
@ -2253,6 +2308,13 @@ td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_v3_in
|
|||
->get_address(workchain_id);
|
||||
}
|
||||
|
||||
td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_v4_initialAccountState& test_wallet_state,
|
||||
td::int32 revision, ton::WorkchainId workchain_id) {
|
||||
TRY_RESULT(key_bytes, get_public_key(test_wallet_state.public_key_));
|
||||
return ton::WalletV4::create({key_bytes.key, static_cast<td::uint32>(test_wallet_state.wallet_id_)}, revision)
|
||||
->get_address(workchain_id);
|
||||
}
|
||||
|
||||
td::Result<block::StdAddress> get_account_address(
|
||||
const tonlib_api::wallet_highload_v1_initialAccountState& test_wallet_state, td::int32 revision,
|
||||
ton::WorkchainId workchain_id) {
|
||||
|
|
@ -2300,6 +2362,7 @@ static td::optional<ton::SmartContractCode::Type> get_wallet_type(tonlib_api::In
|
|||
td::overloaded(
|
||||
[](const tonlib_api::raw_initialAccountState&) { return td::optional<ton::SmartContractCode::Type>(); },
|
||||
[](const tonlib_api::wallet_v3_initialAccountState&) { return ton::SmartContractCode::WalletV3; },
|
||||
[](const tonlib_api::wallet_v4_initialAccountState&) { return ton::SmartContractCode::WalletV4; },
|
||||
[](const tonlib_api::wallet_highload_v1_initialAccountState&) {
|
||||
return ton::SmartContractCode::HighloadWalletV1;
|
||||
},
|
||||
|
|
@ -2389,6 +2452,12 @@ td::Status TonlibClient::do_request(tonlib_api::guessAccount& request,
|
|||
sources.push_back(Source{tonlib_api::make_object<tonlib_api::wallet_v3_initialAccountState>(
|
||||
request.public_key_, wallet_id_ + ton::basechainId),
|
||||
ton::basechainId});
|
||||
sources.push_back(Source{tonlib_api::make_object<tonlib_api::wallet_v4_initialAccountState>(
|
||||
request.public_key_, wallet_id_ + ton::masterchainId),
|
||||
ton::masterchainId});
|
||||
sources.push_back(Source{tonlib_api::make_object<tonlib_api::wallet_v4_initialAccountState>(
|
||||
request.public_key_, wallet_id_ + ton::basechainId),
|
||||
ton::basechainId});
|
||||
for (Source& source : sources) {
|
||||
auto o_type = get_wallet_type(*source.init_state);
|
||||
if (!o_type) {
|
||||
|
|
@ -2900,7 +2969,7 @@ struct ToRawTransactions {
|
|||
if (type == 0 || type == 0x2167da4b) {
|
||||
td::Status status;
|
||||
|
||||
auto r_body_message = vm::CellString::load(body.write());
|
||||
auto r_body_message = TRY_VM(vm::CellString::load(body.write()));
|
||||
LOG_IF(WARNING, r_body_message.is_error()) << "Failed to parse a message: " << r_body_message.error();
|
||||
|
||||
if (r_body_message.is_ok()) {
|
||||
|
|
@ -4921,6 +4990,8 @@ td::Status TonlibClient::do_request(const tonlib_api::importKey& request,
|
|||
if (!request.exported_key_) {
|
||||
return TonlibError::EmptyField("exported_key");
|
||||
}
|
||||
// Note: the mnemonic is considered valid if a certain hash starts with zero byte (see Mnemonic::is_basic_seed())
|
||||
// Therefore, importKey with invalid password has 1/256 chance to return OK
|
||||
TRY_RESULT(key, key_storage_.import_key(std::move(request.local_password_), std::move(request.mnemonic_password_),
|
||||
KeyStorage::ExportedKey{std::move(request.exported_key_->word_list_)}));
|
||||
TRY_RESULT(key_bytes, public_key_from_bytes(key.public_key.as_slice()));
|
||||
|
|
|
|||
|
|
@ -418,6 +418,8 @@ class TonlibCli : public td::actor::Actor {
|
|||
td::TerminalIO::out() << "exportkeypem [<key_id>] - export key\n";
|
||||
td::TerminalIO::out()
|
||||
<< "gethistory <key_id> - get history fo simple wallet with requested key (last 10 transactions)\n";
|
||||
td::TerminalIO::out() << "showtransactions <key_id> <lt> <hash> [<count>] - show transaction on account <key_id> "
|
||||
"with given <lt> and <hash> (in base64) and previous transactions (up to <count>).\n";
|
||||
td::TerminalIO::out() << "init <key_id> - init simple wallet with requested key\n";
|
||||
td::TerminalIO::out() << "transfer[f][F][e][k][c] <from_key_id> (<to_key_id> <value> <message>|<file_name>) - "
|
||||
"make transfer from <from_key_id>\n"
|
||||
|
|
@ -515,6 +517,8 @@ class TonlibCli : public td::actor::Actor {
|
|||
} else if (cmd == "getmasterchainsignatures") {
|
||||
auto seqno = parser.read_word();
|
||||
run_get_masterchain_block_signatures(seqno, std::move(cmd_promise));
|
||||
} else if (cmd == "showtransactions") {
|
||||
run_show_transactions(parser, std::move(cmd_promise));
|
||||
} else {
|
||||
cmd_promise.set_error(td::Status::Error(PSLICE() << "Unkwnown query `" << cmd << "`"));
|
||||
}
|
||||
|
|
@ -2157,6 +2161,45 @@ class TonlibCli : public td::actor::Actor {
|
|||
}));
|
||||
}
|
||||
|
||||
void run_show_transactions(td::ConstParser& parser, td::Promise<td::Unit> promise) {
|
||||
TRY_RESULT_PROMISE(promise, address, to_account_address(parser.read_word(), false));
|
||||
TRY_RESULT_PROMISE(promise, lt, td::to_integer_safe<td::int64>(parser.read_word()));
|
||||
TRY_RESULT_PROMISE(promise, hash, td::base64_decode(parser.read_word()));
|
||||
int count = 1;
|
||||
if (!parser.empty()) {
|
||||
TRY_RESULT_PROMISE_ASSIGN(promise, count, td::to_integer_safe<int>(parser.read_word()));
|
||||
}
|
||||
auto id = make_object<tonlib_api::internal_transactionId>(lt, hash);
|
||||
send_query(make_object<tonlib_api::raw_getTransactionsV2>(
|
||||
nullptr, ton::move_tl_object_as<tonlib_api::accountAddress>(std::move(address.address)),
|
||||
std::move(id), count, false),
|
||||
promise.wrap([](ton::tl_object_ptr<tonlib_api::raw_transactions>&& result) -> td::Result<td::Unit> {
|
||||
td::TerminalIO::out() << "Found " << result->transactions_.size() << " transactions\n";
|
||||
for (size_t i = 0; i < result->transactions_.size(); ++i) {
|
||||
td::TerminalIO::out() << "Transaction #" << i << "\n";
|
||||
auto& tr = result->transactions_[i];
|
||||
TRY_RESULT(root, vm::std_boc_deserialize(tr->data_));
|
||||
block::gen::Transaction::Record trans;
|
||||
if (!tlb::unpack_cell(root, trans)) {
|
||||
return td::Status::Error("cannot unpack transaction");
|
||||
}
|
||||
td::TerminalIO::out() << "Transaction Account: " << tr->address_->account_address_ << "\n";
|
||||
td::TerminalIO::out() << "Transaction LT: " << tr->transaction_id_->lt_ << "\n";
|
||||
td::TerminalIO::out() << "Transaction Hash: " << td::base64_encode(tr->transaction_id_->hash_)
|
||||
<< "\n";
|
||||
td::TerminalIO::out() << "Transaction Timestamp: " << tr->utime_ << "\n";
|
||||
td::TerminalIO::out() << "Transaction Out messages: " << tr->out_msgs_.size() << "\n";
|
||||
td::TerminalIO::out() << "Previous transaction LT: " << trans.prev_trans_lt << "\n";
|
||||
td::TerminalIO::out() << "Previous transaction Hash: "
|
||||
<< td::base64_encode(trans.prev_trans_hash.as_slice()) << "\n";
|
||||
std::ostringstream ss;
|
||||
block::gen::t_Transaction.print_ref(2048, ss, root);
|
||||
td::TerminalIO::out() << "Transaction dump: " << ss.str() << "\n";
|
||||
}
|
||||
return td::Unit();
|
||||
}));
|
||||
}
|
||||
|
||||
void get_history2(td::Slice key, td::Result<tonlib_api::object_ptr<tonlib_api::fullAccountState>> r_state,
|
||||
td::Promise<td::Unit> promise) {
|
||||
TRY_RESULT_PROMISE(promise, state, std::move(r_state));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue