diff --git a/tl/generate/scheme/tonlib_api.tl b/tl/generate/scheme/tonlib_api.tl index 4d928c18..7022a0b6 100644 --- a/tl/generate/scheme/tonlib_api.tl +++ b/tl/generate/scheme/tonlib_api.tl @@ -202,6 +202,18 @@ data bytes:secureBytes = Data; liteServer.info now:int53 version:int32 capabilities:int64 = liteServer.Info; + +blocks.masterchainInfo last:ton.BlockIdExt state_root_hash:bytes init:ton.BlockIdExt = blocks.MasterchainInfo; +blocks.shards shards:vector = blocks.Shards; +blocks.accountTransactionId account:bytes lt:int64 = blocks.AccountTransactionId; +blocks.shortTxId mode:# account:mode.0?bytes lt:mode.1?int64 hash:mode.2?bytes = liteServer.TransactionId; +blocks.transactions id:ton.blockIdExt req_count:int32 incomplete:Bool transactions:vector = blocks.Transactions; +blocks.header id:ton.blockIdExt global_id:int32 version:int32 after_merge:Bool after_split:Bool before_split:Bool want_merge:Bool + want_split:Bool validator_list_hash_short:int32 catchain_seqno:int32 min_ref_mc_seqno:int32 is_key_block:Bool + prev_key_block_seqno:int32 + start_lt:int64 end_lt:int64 vert_seqno:# + prev_blocks:vector = blocks.Header; +//blocks.shortData header:blocks.Header transactions:blocks.Header = blocks.BlockData; ---functions--- init options:options = options.Info; @@ -278,6 +290,13 @@ pchan.validatePromise public_key:bytes promise:pchan.promise = Ok; pchan.packPromise promise:pchan.promise = Data; pchan.unpackPromise data:secureBytes = pchan.Promise; + +blocks.getMasterchainInfo = blocks.MasterchainInfo; +blocks.getShards id:ton.blockIdExt = blocks.Shards; +blocks.lookupBlock mode:int32 id:ton.blockId lt:int64 utime:int32 = ton.BlockIdExt; +blocks.getTransactions id:ton.blockIdExt mode:# count:# after:blocks.accountTransactionId = blocks.Transactions; +blocks.getBlockHeader id:ton.blockIdExt = blocks.Header; + onLiteServerQueryResult id:int64 bytes:bytes = Ok; onLiteServerQueryError id:int64 error:error = Ok; diff --git a/tl/generate/scheme/tonlib_api.tlo b/tl/generate/scheme/tonlib_api.tlo index 0add8dd6..a510d2fa 100644 Binary files a/tl/generate/scheme/tonlib_api.tlo and b/tl/generate/scheme/tonlib_api.tlo differ diff --git a/tonlib/tonlib/TonlibClient.cpp b/tonlib/tonlib/TonlibClient.cpp index 5ad50a09..6928cf08 100644 --- a/tonlib/tonlib/TonlibClient.cpp +++ b/tonlib/tonlib/TonlibClient.cpp @@ -43,6 +43,11 @@ #include "ton/ton-shard.h" #include "vm/boc.h" +#include "vm/cellops.h" +#include "vm/cells/MerkleProof.h" +#include "vm/vm.h" +#include "vm/cp0.h" +#include "vm/memo.h" #include "td/utils/as.h" #include "td/utils/Random.h" @@ -54,6 +59,11 @@ #include "common/util.h" +template +using lite_api_ptr = ton::lite_api::object_ptr; +template +using tonlib_api_ptr = ton::tonlib_api::object_ptr; + namespace tonlib { namespace int_api { struct GetAccountState { @@ -3960,17 +3970,18 @@ td::Status TonlibClient::do_request(const tonlib_api::liteServer_getInfo& reques return td::Status::OK(); } +auto to_bits256(td::Slice data, td::Slice name) -> td::Result { + if (data.size() != 32) { + return TonlibError::InvalidField(name, "wrong length (not 32 bytes)"); + } + return td::Bits256(data.ubegin()); +} + td::Status TonlibClient::do_request(tonlib_api::withBlock& request, td::Promise>&& promise) { if (!request.id_) { return TonlibError::EmptyField("id"); } - auto to_bits256 = [](td::Slice data, td::Slice name) -> td::Result { - if (data.size() != 32) { - return TonlibError::InvalidField(name, "wrong length (not 32 bytes)"); - } - return td::Bits256(data.ubegin()); - }; TRY_RESULT(root_hash, to_bits256(request.id_->root_hash_, "root_hash")); TRY_RESULT(file_hash, to_bits256(request.id_->file_hash_, "file_hash")); ton::BlockIdExt block_id(request.id_->workchain_, request.id_->shard_, request.id_->seqno_, root_hash, file_hash); @@ -3978,6 +3989,202 @@ td::Status TonlibClient::do_request(tonlib_api::withBlock& request, return td::Status::OK(); } +auto to_tonlib_api(const ton::lite_api::tonNode_blockIdExt& blk) -> tonlib_api_ptr { + return tonlib_api::make_object( + blk.workchain_, blk.shard_, blk.seqno_, blk.root_hash_.as_slice().str(), blk.file_hash_.as_slice().str()); +} + +/*auto to_tonlib_api(const ton::BlockIdExt& blk) -> tonlib_api_ptr { + return tonlib_api::make_object( + blk.workchain, blk.shard, blk.seqno, blk.root_hash.as_slice().str(), blk.file_hash.as_slice().str()); +}*/ + +auto to_tonlib_api(const ton::lite_api::tonNode_zeroStateIdExt& zeroStateId) + -> tonlib_api_ptr { + return tonlib_api::make_object( //TODO check wether shard indeed 0??? + zeroStateId.workchain_, 0, 0, zeroStateId.root_hash_.as_slice().str(), zeroStateId.file_hash_.as_slice().str()); +} + +auto to_lite_api(const tonlib_api::ton_blockIdExt& blk) -> td::Result> { + TRY_RESULT(root_hash, to_bits256(blk.root_hash_, "blk.root_hash")) + TRY_RESULT(file_hash, to_bits256(blk.file_hash_, "blk.file_hash")) + return ton::lite_api::make_object( + blk.workchain_, blk.shard_, blk.seqno_, root_hash, file_hash); +} + +td::Status TonlibClient::do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info, + td::Promise>&& promise) { + client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(), + promise.wrap([](lite_api_ptr&& masterchain_info) { + return tonlib_api::make_object( + to_tonlib_api(*masterchain_info->last_), masterchain_info->state_root_hash_.as_slice().str(), + to_tonlib_api(*masterchain_info->init_)); + })); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::blocks_getShards& request, + td::Promise>&& promise) { + TRY_RESULT(block, to_lite_api(*request.id_)) + client_.send_query(ton::lite_api::liteServer_getAllShardsInfo(std::move(block)), + promise.wrap([](lite_api_ptr&& all_shards_info) { + td::BufferSlice proof = std::move((*all_shards_info).proof_); + td::BufferSlice data = std::move((*all_shards_info).data_); + if (data.empty()) { + //return td::Status::Error("shard configuration is empty"); + } else { + auto R = vm::std_boc_deserialize(data.clone()); + if (R.is_error()) { + //return td::Status::Error("cannot deserialize shard configuration"); + } + auto root = R.move_as_ok(); + block::ShardConfig sh_conf; + if (!sh_conf.unpack(vm::load_cell_slice_ref(root))) { + //return td::Status::Error("cannot extract shard block list from shard configuration"); + } else { + auto ids = sh_conf.get_shard_hash_ids(true); + tonlib_api::blocks_shards shards; + for (auto id : ids) { + auto ref = sh_conf.get_shard_hash(ton::ShardIdFull(id)); + if (ref.not_null()) { + shards.shards_.push_back(to_tonlib_api(ref->top_block_id())); + } + } + return tonlib_api::make_object(std::move(shards)); + } + } + })); + return td::Status::OK(); +} + + +td::Status TonlibClient::do_request(const tonlib_api::blocks_lookupBlock& request, + td::Promise>&& promise) { + client_.send_query(ton::lite_api::liteServer_lookupBlock( + request.mode_, + ton::lite_api::make_object((*request.id_).workchain_, (*request.id_).shard_, (*request.id_).seqno_), + (td::uint64)(request.lt_), + (td::uint32)(request.utime_)), + promise.wrap([](lite_api_ptr&& header) { + const auto& id = header->id_; + return to_tonlib_api(*id); + //tonlib_api::make_object( + // ton::tonlib_api::ton_blockIdExt(id->workchain_, id->) + //); + })); + return td::Status::OK(); +} + +auto to_tonlib_api(const ton::lite_api::liteServer_transactionId& txid) + -> tonlib_api_ptr { + return tonlib_api::make_object( + txid.mode_, txid.account_.as_slice().str(), txid.lt_, txid.hash_.as_slice().str()); +} + +td::Status TonlibClient::do_request(const tonlib_api::blocks_getTransactions& request, + td::Promise>&& promise) { + TRY_RESULT(block, to_lite_api(*request.id_)) + TRY_RESULT(account, to_bits256((*request.after_).account_, "account")); + auto after = ton::lite_api::make_object(account, (*request.after_).lt_); + client_.send_query(ton::lite_api::liteServer_listBlockTransactions( + std::move(block), + request.mode_, + request.count_, + std::move(after), + false, + false), + promise.wrap([](lite_api_ptr&& bTxes) { + const auto& id = bTxes->id_; + //for (auto id : ids) { + tonlib_api::blocks_transactions r; + r.id_ = to_tonlib_api(*id); + r.req_count_ = bTxes->req_count_; + r.incomplete_ = bTxes->incomplete_; + for (auto& id: bTxes->ids_) { + //tonlib_api::blocks_shortTxId txid = tonlib_api::blocks_shortTxId(id->mode_, id->account_.as_slice().str(), id->lt_, id->hash_.as_slice().str()); + //r.transactions_.push_back(txid); + r.transactions_.push_back(to_tonlib_api(*id)); + } + return tonlib_api::make_object(std::move(r)); + })); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::blocks_getBlockHeader& request, + td::Promise>&& promise) { + TRY_RESULT(block, to_lite_api(*request.id_)) + client_.send_query(ton::lite_api::liteServer_getBlockHeader( + std::move(block), + 0xffff), + promise.wrap([](lite_api_ptr&& hdr) { + auto blk_id = ton::create_block_id(hdr->id_); + auto R = vm::std_boc_deserialize(std::move(hdr->header_proof_)); + tonlib_api::blocks_header header; + if (R.is_error()) { + LOG(WARNING) << "R.is_error() "; + } else { + auto root = R.move_as_ok(); + try { + ton::RootHash vhash{root->get_hash().bits()}; + auto virt_root = vm::MerkleProof::virtualize(root, 1); + if (virt_root.is_null()) { + LOG(WARNING) << "virt root is null"; + } else { + std::vector prev; + ton::BlockIdExt mc_blkid; + bool after_split; + auto res = block::unpack_block_prev_blk_ext(virt_root, blk_id, prev, mc_blkid, after_split); + if (res.is_error()) { + LOG(WARNING) << "res.is_error() "; + } else { + block::gen::Block::Record blk; + block::gen::BlockInfo::Record info; + if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info))) { + LOG(WARNING) << "unpack failed"; + } else { + header.id_ = to_tonlib_api(blk_id); + header.global_id_ = blk.global_id; + header.version_ = info.version; + header.after_merge_ = info.after_merge; + header.after_split_ = info.after_split; + header.before_split_ = info.before_split; + header.want_merge_ = info.want_merge; + header.want_split_ = info.want_split; + header.validator_list_hash_short_ = info.gen_validator_list_hash_short; + header.catchain_seqno_ = info.gen_catchain_seqno; + header.min_ref_mc_seqno_ = info.min_ref_mc_seqno; + header.start_lt_ = info.start_lt; + header.end_lt_ = info.end_lt; + header.vert_seqno_ = info.vert_seq_no; + if(!info.not_master) { + header.prev_key_block_seqno_ = info.prev_key_block_seqno; + } + for (auto id : prev) { + header.prev_blocks_.push_back(to_tonlib_api(id)); + } + //if(info.before_split) { + //} else { + //} + return tonlib_api::make_object(std::move(header)); + } + } + } + } catch (vm::VmError& err) { + auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); + LOG(ERROR) << std::move(E); + } catch (vm::VmVirtError& err) { + auto E = err.as_status(PSLICE() << "error processing header for " << blk_id.to_str() << " :"); + LOG(ERROR) << std::move(E); + } catch (...) { + LOG(WARNING) << "exception catched "; + } + } + return tonlib_api::make_object(std::move(header)); + })); + return td::Status::OK(); +} + + template td::Status TonlibClient::do_request(const tonlib_api::runTests& request, P&&) { UNREACHABLE(); diff --git a/tonlib/tonlib/TonlibClient.h b/tonlib/tonlib/TonlibClient.h index 52529db6..bedc1d49 100644 --- a/tonlib/tonlib/TonlibClient.h +++ b/tonlib/tonlib/TonlibClient.h @@ -321,6 +321,8 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(tonlib_api::pchan_unpackPromise& request, td::Promise>&& promise); + + void do_dns_request(std::string name, td::int32 category, td::int32 ttl, td::optional block_id, block::StdAddress address, td::Promise>&& promise); struct DnsFinishData { @@ -342,6 +344,17 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(tonlib_api::withBlock& request, td::Promise>&& promise); + td::Status do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::blocks_getShards& request, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::blocks_lookupBlock& block_header, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::blocks_getTransactions& block_data, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::blocks_getBlockHeader& request, + td::Promise>&& promise); + void proxy_request(td::int64 query_id, std::string data); friend class TonlibQueryActor;