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

updated tonlib + fixes in vm

This commit is contained in:
ton 2020-02-20 19:56:18 +04:00
parent 28735ddc9e
commit efd47af432
42 changed files with 750 additions and 307 deletions

View file

@ -1329,11 +1329,36 @@ td::Result<td::Bits256> get_adnl_address(td::Slice adnl_address) {
return address;
}
static td::optional<ton::SmartContractCode::Type> get_wallet_type(tonlib_api::InitialAccountState& state) {
return downcast_call2<td::optional<ton::SmartContractCode::Type>>(
state,
td::overloaded(
[](const tonlib_api::raw_initialAccountState&) { return td::optional<ton::SmartContractCode::Type>(); },
[](const tonlib_api::testGiver_initialAccountState&) { return td::optional<ton::SmartContractCode::Type>(); },
[](const tonlib_api::testWallet_initialAccountState&) { return ton::SmartContractCode::WalletV1; },
[](const tonlib_api::wallet_initialAccountState&) { return ton::SmartContractCode::WalletV2; },
[](const tonlib_api::wallet_v3_initialAccountState&) { return ton::SmartContractCode::WalletV3; },
[](const tonlib_api::wallet_highload_v1_initialAccountState&) {
return ton::SmartContractCode::HighloadWalletV1;
},
[](const tonlib_api::wallet_highload_v2_initialAccountState&) {
return ton::SmartContractCode::HighloadWalletV2;
},
[](const tonlib_api::dns_initialAccountState&) { return ton::SmartContractCode::ManualDns; }));
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::getAccountAddress& request) {
if (!request.initial_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto o_type = get_wallet_type(*request.initial_account_state_);
if (o_type) {
auto status = ton::SmartContractCode::validate_revision(o_type.value(), request.revision_);
if (status.is_error()) {
return status_to_tonlib_api(TonlibError::InvalidRevision());
}
}
auto r_account_address = downcast_call2<td::Result<block::StdAddress>>(
*request.initial_account_state_,
[&request](auto&& state) { return get_account_address(state, request.revision_); });
@ -1343,6 +1368,72 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
return tonlib_api::make_object<tonlib_api::accountAddress>(r_account_address.ok().rserialize(true));
}
td::Status TonlibClient::do_request(const tonlib_api::guessAccountRevision& request,
td::Promise<object_ptr<tonlib_api::accountRevisionList>>&& promise) {
if (!request.initial_account_state_) {
return TonlibError::EmptyField("initial_account_state");
}
auto o_type = get_wallet_type(*request.initial_account_state_);
if (!o_type) {
promise.set_value(tonlib_api::make_object<tonlib_api::accountRevisionList>(std::vector<td::int32>{0}));
return td::Status::OK();
}
auto revisions = ton::SmartContractCode::get_revisions(o_type.value());
std::vector<std::pair<int, block::StdAddress>> addresses;
TRY_STATUS(downcast_call2<td::Status>(*request.initial_account_state_, [&revisions, &addresses](const auto& state) {
for (auto revision : revisions) {
TRY_RESULT(address, get_account_address(state, revision));
addresses.push_back(std::make_pair(revision, address));
}
return td::Status::OK();
}));
auto actor_id = actor_id_++;
class GuessRevisions : public TonlibQueryActor {
public:
GuessRevisions(td::actor::ActorShared<TonlibClient> client, td::optional<ton::BlockIdExt> block_id,
std::vector<std::pair<int, block::StdAddress>> addresses, td::Promise<std::vector<int>> promise)
: TonlibQueryActor(std::move(client))
, block_id_(std::move(block_id))
, addresses_(std::move(addresses))
, promise_(std::move(promise)) {
}
private:
td::optional<ton::BlockIdExt> block_id_;
std::vector<std::pair<int, block::StdAddress>> addresses_;
td::Promise<std::vector<int>> promise_;
size_t left_{0};
std::vector<int> res;
void start_up() {
left_ += addresses_.size();
for (auto& p : addresses_) {
send_query(int_api::GetAccountState{p.second, block_id_.copy()},
promise_send_closure(td::actor::actor_id(this), &GuessRevisions::on_account_state, p.first));
}
}
void on_account_state(int revision, td::Result<td::unique_ptr<AccountState>> r_state) {
if (r_state.is_ok() && r_state.ok()->get_wallet_type() != AccountState::WalletType::Empty) {
res.push_back(revision);
}
left_--;
if (left_ == 0) {
promise_.set_value(std::move(res));
stop();
}
}
};
actors_[actor_id] = td::actor::create_actor<GuessRevisions>(
"GuessRevisions", actor_shared(this, actor_id), query_context_.block_id.copy(), std::move(addresses),
promise.wrap(
[](auto&& x) mutable { return tonlib_api::make_object<tonlib_api::accountRevisionList>(std::move(x)); }));
return td::Status::OK();
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::unpackAccountAddress& request) {
auto r_account_address = get_account_address(request.account_address_);

View file

@ -226,6 +226,8 @@ class TonlibClient : public td::actor::Actor {
td::Status do_request(const tonlib_api::getAccountState& request,
td::Promise<object_ptr<tonlib_api::fullAccountState>>&& promise);
td::Status do_request(const tonlib_api::guessAccountRevision& request,
td::Promise<object_ptr<tonlib_api::accountRevisionList>>&& promise);
td::Status do_request(tonlib_api::sync& request, td::Promise<object_ptr<tonlib_api::ton_blockIdExt>>&& promise);

View file

@ -32,6 +32,7 @@
// INVALID_ACCOUNT_ADDRESS
// INVALID_CONFIG
// INVALID_PEM_KEY
// INVALID_REVISION
// MESSAGE_TOO_LONG
// EMPTY_FIELD
// INVALID_FIELD
@ -80,6 +81,9 @@ struct TonlibError {
static td::Status InvalidPemKey() {
return td::Status::Error(400, "INVALID_PEM_KEY");
}
static td::Status InvalidRevision() {
return td::Status::Error(400, "INVALID_REVISION");
}
static td::Status NeedConfig() {
return td::Status::Error(400, "NeedConfig");
}

View file

@ -311,6 +311,7 @@ class TonlibCli : public td::actor::Actor {
td::TerminalIO::out() << "runmethod <addr> <method-id> <params>...\tRuns GET method <method-id> of account "
"<addr> with specified parameters\n";
td::TerminalIO::out() << "getstate <key_id>\tget state of wallet with requested key\n";
td::TerminalIO::out() << "guessrevision <key_id>\tsearch of existing accounts corresponding to the given key\n";
td::TerminalIO::out() << "getaddress <key_id>\tget address of wallet with requested key\n";
td::TerminalIO::out() << "dns resolve (<addr> | root) <name> <category>\n";
td::TerminalIO::out() << "dns cmd <key_id> <dns_cmd>\n";
@ -416,6 +417,8 @@ class TonlibCli : public td::actor::Actor {
run_dns_cmd(parser, std::move(cmd_promise));
} else if (cmd == "gethistory") {
get_history(parser.read_word(), std::move(cmd_promise));
} else if (cmd == "guessrevision") {
guess_revision(parser.read_word(), std::move(cmd_promise));
} else {
cmd_promise.set_error(td::Status::Error(PSLICE() << "Unkwnown query `" << cmd << "`"));
}
@ -1091,6 +1094,27 @@ class TonlibCli : public td::actor::Actor {
td::SecureString secret;
};
template <class F>
auto with_account_state(int version, std::string public_key, td::uint32 wallet_id, F&& f) {
using tonlib_api::make_object;
if (version == 1) {
return f(make_object<tonlib_api::testWallet_initialAccountState>(public_key));
}
if (version == 2) {
return f(make_object<tonlib_api::wallet_initialAccountState>(public_key));
}
if (version == 4) {
return f(make_object<tonlib_api::wallet_highload_v1_initialAccountState>(public_key, wallet_id));
}
if (version == 5) {
return f(make_object<tonlib_api::wallet_highload_v2_initialAccountState>(public_key, wallet_id));
}
if (version == 6) {
return f(make_object<tonlib_api::dns_initialAccountState>(public_key, wallet_id));
}
return f(make_object<tonlib_api::wallet_v3_initialAccountState>(public_key, wallet_id));
}
td::Result<Address> to_account_address(td::Slice key, bool need_private_key) {
if (key.empty()) {
return td::Status::Error("account address is empty");
@ -1106,27 +1130,7 @@ class TonlibCli : public td::actor::Actor {
return tonlib::TonlibClient::static_request(
make_object<tonlib_api::getAccountAddress>(std::move(x), revision));
};
if (version == 1) {
return do_request(make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key));
}
if (version == 2) {
return do_request(make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key));
}
if (version == 4) {
return do_request(make_object<tonlib_api::wallet_highload_v1_initialAccountState>(
keys_[r_key_i.ok()].public_key, wallet_id_));
}
if (version == 5) {
return do_request(make_object<tonlib_api::wallet_highload_v2_initialAccountState>(
keys_[r_key_i.ok()].public_key, wallet_id_));
}
if (version == 6) {
return do_request(
make_object<tonlib_api::dns_initialAccountState>(keys_[r_key_i.ok()].public_key, wallet_id_));
}
return do_request(
make_object<tonlib_api::wallet_v3_initialAccountState>(keys_[r_key_i.ok()].public_key, wallet_id_));
UNREACHABLE();
return with_account_state(version, keys_[r_key_i.ok()].public_key, wallet_id_, do_request);
}(options_.wallet_version, options_.wallet_revision);
if (obj->get_id() != tonlib_api::error::ID) {
Address res;
@ -1336,6 +1340,17 @@ class TonlibCli : public td::actor::Actor {
promise.send_closure(td::actor::actor_id(this), &TonlibCli::get_history2, key.str()));
}
void guess_revision(td::Slice key, td::Promise<td::Unit> promise) {
TRY_RESULT_PROMISE(promise, key_i, to_key_i(key));
with_account_state(options_.wallet_version, keys_[key_i].public_key, wallet_id_, [&](auto state) {
using tonlib_api::make_object;
send_query(make_object<tonlib_api::guessAccountRevision>(std::move(state)), promise.wrap([](auto revisions) {
td::TerminalIO::out() << to_string(revisions);
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));