From a4a3ea2b77ae1e527885a5dfe88723ee29ef4d4d Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Wed, 30 Nov 2022 08:39:32 +0300 Subject: [PATCH] liteServer.getAccountStatePrunned method (#534) --- lite-client/lite-client.cpp | 83 ++++++++++++++++++-------------- lite-client/lite-client.h | 5 +- tl/generate/scheme/lite_api.tl | 1 + tl/generate/scheme/lite_api.tlo | Bin 13396 -> 13532 bytes validator/impl/liteserver.cpp | 17 +++++++ 5 files changed, 69 insertions(+), 37 deletions(-) diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp index ecaa97bc..d7d38037 100644 --- a/lite-client/lite-client.cpp +++ b/lite-client/lite-client.cpp @@ -1005,11 +1005,12 @@ bool TestNode::do_parse_line() { return eoln() && get_server_mc_block_id(); } else if (word == "sendfile") { return !eoln() && set_error(send_ext_msg_from_filename(get_line_tail())); - } else if (word == "getaccount") { + } else if (word == "getaccount" || word == "getaccountprunned") { + bool prunned = word == "getaccountprunned"; return parse_account_addr_ext(workchain, addr, addr_ext) && - (seekeoln() - ? get_account_state(workchain, addr, mc_last_id_, addr_ext) - : parse_block_id_ext(blkid) && seekeoln() && get_account_state(workchain, addr, blkid, addr_ext)); + (seekeoln() ? get_account_state(workchain, addr, mc_last_id_, addr_ext, "", -1, prunned) + : parse_block_id_ext(blkid) && seekeoln() && + get_account_state(workchain, addr, blkid, addr_ext, "", -1, prunned)); } else if (word == "saveaccount" || word == "saveaccountcode" || word == "saveaccountdata") { std::string filename; int mode = ((word.c_str()[11] >> 1) & 3); @@ -1173,7 +1174,7 @@ td::Status TestNode::send_ext_msg_from_filename(std::string filename) { } bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - int addr_ext, std::string filename, int mode) { + int addr_ext, std::string filename, int mode, bool prunned) { if (!ref_blkid.is_valid()) { return set_error("must obtain last block information before making other queries"); } @@ -1181,35 +1182,44 @@ bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress return set_error("server connection not ready"); } if (addr_ext) { - return get_special_smc_addr(addr_ext, [this, ref_blkid, filename, mode](td::Result res) { - if (res.is_error()) { - LOG(ERROR) << "cannot resolve special smart contract address: " << res.move_as_error(); - } else { - get_account_state(ton::masterchainId, res.move_as_ok(), ref_blkid, 0, filename, mode); - } - }); + return get_special_smc_addr( + addr_ext, [this, ref_blkid, filename, mode, prunned](td::Result res) { + if (res.is_error()) { + LOG(ERROR) << "cannot resolve special smart contract address: " << res.move_as_error(); + } else { + get_account_state(ton::masterchainId, res.move_as_ok(), ref_blkid, 0, filename, mode, prunned); + } + }); } auto a = ton::create_tl_object(workchain, addr); - auto b = ton::serialize_tl_object(ton::create_tl_object( - ton::create_tl_lite_block_id(ref_blkid), std::move(a)), - true); - LOG(INFO) << "requesting account state for " << workchain << ":" << addr.to_hex() << " with respect to " - << ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode; - return envelope_send_query( - std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode](td::Result R) { - if (R.is_error()) { - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "cannot parse answer to liteServer.getAccountState"; - } else { - auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_account_state, ref_blkid, ton::create_block_id(f->id_), - ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), - std::move(f->proof_), std::move(f->state_), workchain, addr, filename, mode); - } - }); + td::BufferSlice b; + if (prunned) { + b = ton::serialize_tl_object(ton::create_tl_object( + ton::create_tl_lite_block_id(ref_blkid), std::move(a)), + true); + } else { + b = ton::serialize_tl_object(ton::create_tl_object( + ton::create_tl_lite_block_id(ref_blkid), std::move(a)), + true); + } + LOG(INFO) << "requesting " << (prunned ? "prunned " : "") << "account state for " << workchain << ":" << addr.to_hex() + << " with respect to " << ref_blkid.to_str() << " with savefile `" << filename << "` and mode " << mode; + return envelope_send_query(std::move(b), [Self = actor_id(this), workchain, addr, ref_blkid, filename, mode, + prunned](td::Result R) { + if (R.is_error()) { + return; + } + auto F = ton::fetch_tl_object(R.move_as_ok(), true); + if (F.is_error()) { + LOG(ERROR) << "cannot parse answer to liteServer.getAccountState"; + } else { + auto f = F.move_as_ok(); + td::actor::send_closure_later(Self, &TestNode::got_account_state, ref_blkid, ton::create_block_id(f->id_), + ton::create_block_id(f->shardblk_), std::move(f->shard_proof_), + std::move(f->proof_), std::move(f->state_), workchain, addr, filename, mode, + prunned); + } + }); } td::int64 TestNode::compute_method_id(std::string method) { @@ -1901,15 +1911,18 @@ bool TestNode::get_last_transactions(ton::WorkchainId workchain, ton::StdSmcAddr void TestNode::got_account_state(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state, - ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode) { - LOG(INFO) << "got account state for " << workchain << ":" << addr.to_hex() << " with respect to blocks " - << blk.to_str() << (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str()); + ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode, + bool prunned) { + LOG(INFO) << "got " << (prunned ? "prunned " : "") << "account state for " << workchain << ":" << addr.to_hex() + << " with respect to blocks " << blk.to_str() + << (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str()); block::AccountState account_state; account_state.blk = blk; account_state.shard_blk = shard_blk; account_state.shard_proof = std::move(shard_proof); account_state.proof = std::move(proof); account_state.state = std::move(state); + account_state.is_virtualized = prunned; auto r_info = account_state.validate(ref_blk, block::StdAddress(workchain, addr)); if (r_info.is_error()) { LOG(ERROR) << r_info.error().message(); diff --git a/lite-client/lite-client.h b/lite-client/lite-client.h index e62e801c..2602a0a7 100644 --- a/lite-client/lite-client.h +++ b/lite-client/lite-client.h @@ -191,10 +191,11 @@ class TestNode : public td::actor::Actor { td::Status send_ext_msg_from_filename(std::string filename); td::Status save_db_file(ton::FileHash file_hash, td::BufferSlice data); bool get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, - int addr_ext = 0, std::string filename = "", int mode = -1); + int addr_ext = 0, std::string filename = "", int mode = -1, bool prunned = false); void got_account_state(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state, - ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode); + ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode, + bool prunned); bool parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, int addr_ext, std::string method_name, bool ext_mode); bool after_parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid, diff --git a/tl/generate/scheme/lite_api.tl b/tl/generate/scheme/lite_api.tl index b2a72dc9..a01da11a 100644 --- a/tl/generate/scheme/lite_api.tl +++ b/tl/generate/scheme/lite_api.tl @@ -68,6 +68,7 @@ liteServer.getState id:tonNode.blockIdExt = liteServer.BlockState; liteServer.getBlockHeader id:tonNode.blockIdExt mode:# = liteServer.BlockHeader; liteServer.sendMessage body:bytes = liteServer.SendMsgStatus; liteServer.getAccountState id:tonNode.blockIdExt account:liteServer.accountId = liteServer.AccountState; +liteServer.getAccountStatePrunned id:tonNode.blockIdExt account:liteServer.accountId = liteServer.AccountState; liteServer.runSmcMethod mode:# id:tonNode.blockIdExt account:liteServer.accountId method_id:long params:bytes = liteServer.RunMethodResult; liteServer.getShardInfo id:tonNode.blockIdExt workchain:int shard:long exact:Bool = liteServer.ShardInfo; liteServer.getAllShardsInfo id:tonNode.blockIdExt = liteServer.AllShardsInfo; diff --git a/tl/generate/scheme/lite_api.tlo b/tl/generate/scheme/lite_api.tlo index a015d93265e1565c6ade590701b540a76a604c53..0572fd46ea0b4cf65c807d446eb130fd34e6b1ce 100644 GIT binary patch delta 67 zcmcbTaVK-b95qI%$#d1(b=X@oqZD&8OHzYVi^@`q^wLvH9FvptOY=&COA<>`1By!X X@={Y67y^%17EC_Cud(@qS_&@!lZzUP delta 18 acmcbUc_m}R95qJC$#d1(H?L7Q-~|9vj0dg& diff --git a/validator/impl/liteserver.cpp b/validator/impl/liteserver.cpp index 0d59d605..febdbf94 100644 --- a/validator/impl/liteserver.cpp +++ b/validator/impl/liteserver.cpp @@ -153,6 +153,10 @@ void LiteQuery::start_up() { this->perform_getAccountState(ton::create_block_id(q.id_), static_cast(q.account_->workchain_), q.account_->id_, 0); }, + [&](lite_api::liteServer_getAccountStatePrunned& q) { + this->perform_getAccountState(ton::create_block_id(q.id_), static_cast(q.account_->workchain_), + q.account_->id_, 0x40000000); + }, [&](lite_api::liteServer_getOneTransaction& q) { this->perform_getOneTransaction(ton::create_block_id(q.id_), static_cast(q.account_->workchain_), q.account_->id_, @@ -1206,6 +1210,19 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) { } td::BufferSlice data; if (acc_root.not_null()) { + if (mode_ & 0x40000000) { + vm::MerkleProofBuilder mpb{acc_root}; + // account_none$0 = Account; + // account$1 addr:MsgAddressInt storage_stat:StorageInfo storage:AccountStorage = Account; + // account_storage$_ last_trans_lt:uint64 balance:CurrencyCollection state:AccountState = AccountStorage; + // account_active$1 _:StateInit = AccountState; + auto S = mpb.root()->load_cell(); + if (S.is_error()) { + fatal_error(S.move_as_error_prefix("Failed to load account: ")); + return; + } + acc_root = mpb.extract_proof(); + } auto res = vm::std_boc_serialize(std::move(acc_root)); if (res.is_error()) { fatal_error(res.move_as_error());