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

Add blocks api to tonlib

This commit is contained in:
OmicronTau 2021-07-14 21:20:28 +03:00 committed by main
parent 759dc82c3c
commit f60cc6da10
4 changed files with 245 additions and 6 deletions

View file

@ -202,6 +202,18 @@ data bytes:secureBytes = Data;
liteServer.info now:int53 version:int32 capabilities:int64 = liteServer.Info; 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<ton.BlockIdExt> = 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.shortTxId> = 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<ton.blockIdExt> = blocks.Header;
//blocks.shortData header:blocks.Header transactions:blocks.Header = blocks.BlockData;
---functions--- ---functions---
init options:options = options.Info; 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.packPromise promise:pchan.promise = Data;
pchan.unpackPromise data:secureBytes = pchan.Promise; 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; onLiteServerQueryResult id:int64 bytes:bytes = Ok;
onLiteServerQueryError id:int64 error:error = Ok; onLiteServerQueryError id:int64 error:error = Ok;

Binary file not shown.

View file

@ -43,6 +43,11 @@
#include "ton/ton-shard.h" #include "ton/ton-shard.h"
#include "vm/boc.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/as.h"
#include "td/utils/Random.h" #include "td/utils/Random.h"
@ -54,6 +59,11 @@
#include "common/util.h" #include "common/util.h"
template <class Type>
using lite_api_ptr = ton::lite_api::object_ptr<Type>;
template <class Type>
using tonlib_api_ptr = ton::tonlib_api::object_ptr<Type>;
namespace tonlib { namespace tonlib {
namespace int_api { namespace int_api {
struct GetAccountState { struct GetAccountState {
@ -3960,17 +3970,18 @@ td::Status TonlibClient::do_request(const tonlib_api::liteServer_getInfo& reques
return td::Status::OK(); return td::Status::OK();
} }
auto to_bits256(td::Slice data, td::Slice name) -> td::Result<td::Bits256> {
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::Status TonlibClient::do_request(tonlib_api::withBlock& request,
td::Promise<object_ptr<tonlib_api::Object>>&& promise) { td::Promise<object_ptr<tonlib_api::Object>>&& promise) {
if (!request.id_) { if (!request.id_) {
return TonlibError::EmptyField("id"); return TonlibError::EmptyField("id");
} }
auto to_bits256 = [](td::Slice data, td::Slice name) -> td::Result<td::Bits256> {
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(root_hash, to_bits256(request.id_->root_hash_, "root_hash"));
TRY_RESULT(file_hash, to_bits256(request.id_->file_hash_, "file_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); 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(); return td::Status::OK();
} }
auto to_tonlib_api(const ton::lite_api::tonNode_blockIdExt& blk) -> tonlib_api_ptr<tonlib_api::ton_blockIdExt> {
return tonlib_api::make_object<tonlib_api::ton_blockIdExt>(
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<tonlib_api::ton_blockIdExt> {
return tonlib_api::make_object<tonlib_api::ton_blockIdExt>(
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<tonlib_api::ton_blockIdExt> {
return tonlib_api::make_object<tonlib_api::ton_blockIdExt>( //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<lite_api_ptr<ton::lite_api::tonNode_blockIdExt>> {
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<ton::lite_api::tonNode_blockIdExt>(
blk.workchain_, blk.shard_, blk.seqno_, root_hash, file_hash);
}
td::Status TonlibClient::do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info,
td::Promise<object_ptr<tonlib_api::blocks_masterchainInfo>>&& promise) {
client_.send_query(ton::lite_api::liteServer_getMasterchainInfo(),
promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_masterchainInfo>&& masterchain_info) {
return tonlib_api::make_object<tonlib_api::blocks_masterchainInfo>(
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<object_ptr<tonlib_api::blocks_shards>>&& 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<ton::lite_api::liteServer_allShardsInfo>&& 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<tonlib_api::blocks_shards>(std::move(shards));
}
}
}));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::blocks_lookupBlock& request,
td::Promise<object_ptr<tonlib_api::ton_blockIdExt>>&& promise) {
client_.send_query(ton::lite_api::liteServer_lookupBlock(
request.mode_,
ton::lite_api::make_object<ton::lite_api::tonNode_blockId>((*request.id_).workchain_, (*request.id_).shard_, (*request.id_).seqno_),
(td::uint64)(request.lt_),
(td::uint32)(request.utime_)),
promise.wrap([](lite_api_ptr<ton::lite_api::liteServer_blockHeader>&& header) {
const auto& id = header->id_;
return to_tonlib_api(*id);
//tonlib_api::make_object<tonlib_api::ton_blockIdExt>(
// 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<tonlib_api::blocks_shortTxId> {
return tonlib_api::make_object<tonlib_api::blocks_shortTxId>(
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<object_ptr<tonlib_api::blocks_transactions>>&& 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<ton::lite_api::liteServer_transactionId3>(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<ton::lite_api::liteServer_blockTransactions>&& 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<tonlib_api::blocks_transactions>(std::move(r));
}));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::blocks_getBlockHeader& request,
td::Promise<object_ptr<tonlib_api::blocks_header>>&& 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<ton::lite_api::liteServer_blockHeader>&& 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<ton::BlockIdExt> 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<tonlib_api::blocks_header>(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<tonlib_api::blocks_header>(std::move(header));
}));
return td::Status::OK();
}
template <class P> template <class P>
td::Status TonlibClient::do_request(const tonlib_api::runTests& request, P&&) { td::Status TonlibClient::do_request(const tonlib_api::runTests& request, P&&) {
UNREACHABLE(); UNREACHABLE();

View file

@ -321,6 +321,8 @@ class TonlibClient : public td::actor::Actor {
td::Status do_request(tonlib_api::pchan_unpackPromise& request, td::Status do_request(tonlib_api::pchan_unpackPromise& request,
td::Promise<object_ptr<tonlib_api::pchan_promise>>&& promise); td::Promise<object_ptr<tonlib_api::pchan_promise>>&& promise);
void do_dns_request(std::string name, td::int32 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id, void do_dns_request(std::string name, td::int32 category, td::int32 ttl, td::optional<ton::BlockIdExt> block_id,
block::StdAddress address, td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise); block::StdAddress address, td::Promise<object_ptr<tonlib_api::dns_resolved>>&& promise);
struct DnsFinishData { struct DnsFinishData {
@ -342,6 +344,17 @@ class TonlibClient : public td::actor::Actor {
td::Status do_request(tonlib_api::withBlock& request, td::Promise<object_ptr<tonlib_api::Object>>&& promise); td::Status do_request(tonlib_api::withBlock& request, td::Promise<object_ptr<tonlib_api::Object>>&& promise);
td::Status do_request(const tonlib_api::blocks_getMasterchainInfo& masterchain_info,
td::Promise<object_ptr<tonlib_api::blocks_masterchainInfo>>&& promise);
td::Status do_request(const tonlib_api::blocks_getShards& request,
td::Promise<object_ptr<tonlib_api::blocks_shards>>&& promise);
td::Status do_request(const tonlib_api::blocks_lookupBlock& block_header,
td::Promise<object_ptr<tonlib_api::ton_blockIdExt>>&& promise);
td::Status do_request(const tonlib_api::blocks_getTransactions& block_data,
td::Promise<object_ptr<tonlib_api::blocks_transactions>>&& promise);
td::Status do_request(const tonlib_api::blocks_getBlockHeader& request,
td::Promise<object_ptr<tonlib_api::blocks_header>>&& promise);
void proxy_request(td::int64 query_id, std::string data); void proxy_request(td::int64 query_id, std::string data);
friend class TonlibQueryActor; friend class TonlibQueryActor;