Skip to content

Commit

Permalink
Add publishers to proof of getLibrariesWithProof response (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
dungeon-master-666 committed Mar 9, 2024
1 parent d19b509 commit bba1fd2
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 68 deletions.
4 changes: 2 additions & 2 deletions tl/generate/scheme/lite_api.tl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ liteServer.partialBlockProof complete:Bool from:tonNode.blockIdExt to:tonNode.bl
liteServer.configInfo mode:# id:tonNode.blockIdExt state_proof:bytes config_proof:bytes = liteServer.ConfigInfo;
liteServer.validatorStats mode:# id:tonNode.blockIdExt count:int complete:Bool state_proof:bytes data_proof:bytes = liteServer.ValidatorStats;
liteServer.libraryResult result:(vector liteServer.libraryEntry) = liteServer.LibraryResult;
liteServer.libraryResultWithProof id:tonNode.blockIdExt result:(vector liteServer.libraryEntry) state_proof:bytes data_proof:bytes = liteServer.LibraryResultWithProof;
liteServer.libraryResultWithProof id:tonNode.blockIdExt mode:# result:(vector liteServer.libraryEntry) state_proof:bytes data_proof:bytes = liteServer.LibraryResultWithProof;
liteServer.shardBlockLink id:tonNode.blockIdExt proof:bytes = liteServer.ShardBlockLink;
liteServer.shardBlockProof masterchain_id:tonNode.blockIdExt links:(vector liteServer.shardBlockLink) = liteServer.ShardBlockProof;
liteServer.lookupBlockResult id:tonNode.blockIdExt mode:# mc_block_id:tonNode.blockIdExt client_mc_state_proof:bytes mc_block_proof:bytes shard_links:(vector liteServer.shardBlockLink) header:bytes prev_header:bytes = liteServer.LookupBlockResult;
Expand Down Expand Up @@ -86,7 +86,7 @@ liteServer.getConfigAll mode:# id:tonNode.blockIdExt = liteServer.ConfigInfo;
liteServer.getConfigParams mode:# id:tonNode.blockIdExt param_list:(vector int) = liteServer.ConfigInfo;
liteServer.getValidatorStats#091a58bc mode:# id:tonNode.blockIdExt limit:int start_after:mode.0?int256 modified_after:mode.2?int = liteServer.ValidatorStats;
liteServer.getLibraries library_list:(vector int256) = liteServer.LibraryResult;
liteServer.getLibrariesWithProof id:tonNode.blockIdExt library_list:(vector int256) = liteServer.LibraryResultWithProof;
liteServer.getLibrariesWithProof id:tonNode.blockIdExt mode:# library_list:(vector int256) = liteServer.LibraryResultWithProof;
liteServer.getShardBlockProof id:tonNode.blockIdExt = liteServer.ShardBlockProof;

liteServer.queryPrefix = Object;
Expand Down
Binary file modified tl/generate/scheme/lite_api.tlo
Binary file not shown.
83 changes: 47 additions & 36 deletions tonlib/tonlib/TonlibClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4532,7 +4532,7 @@ void TonlibClient::get_libraries(ton::BlockIdExt blkid, std::vector<td::Bits256>
return;
}

client_.send_query(ton::lite_api::liteServer_getLibrariesWithProof(ton::create_tl_lite_block_id(blkid), std::move(not_cached_hashes)),
client_.send_query(ton::lite_api::liteServer_getLibrariesWithProof(ton::create_tl_lite_block_id(blkid), 1, std::move(not_cached_hashes)),
promise.wrap([self=this, blkid, result_entries = std::move(result_entries), not_cached_hashes]
(td::Result<ton::lite_api::object_ptr<ton::lite_api::liteServer_libraryResultWithProof>> r_libraries) mutable
-> td::Result<tonlib_api::object_ptr<tonlib_api::smc_libraryResult>> {
Expand All @@ -4549,48 +4549,59 @@ void TonlibClient::get_libraries(ton::BlockIdExt blkid, std::vector<td::Bits256>
return state.move_as_error();
}
auto state_root = state.move_as_ok();
auto rconfig = block::ConfigInfo::extract_config(state_root, block::ConfigInfo::needLibraries);
if (rconfig.is_error()) {
LOG(WARNING) << "cannot extract config: " << rconfig.move_as_error().to_string();
return rconfig.move_as_error();
}
auto config = rconfig.move_as_ok();
for (auto& hash : not_cached_hashes) {
auto libres = config->lookup_library(hash);
if (libres.is_null()) {
LOG(WARNING) << "library " << hash.to_hex() << " not found in config";
if (std::any_of(libraries->result_.begin(), libraries->result_.end(),
[&hash](const auto& lib) { return lib->hash_.bits().equals(hash.cbits(), 256); })) {
return TonlibError::Internal("library is included in response but it's not found in proof");
}
continue;

try {
block::gen::ShardStateUnsplit::Record state_record;
if (!tlb::unpack_cell(state_root, state_record)) {
return td::Status::Error("cannot unpack shardchain state");
}
auto libraries_dict = vm::Dictionary(state_record.r1.libraries->prefetch_ref(), 256);

for (auto& hash : not_cached_hashes) {
auto csr = libraries_dict.lookup(hash.bits(), 256);
if (csr.is_null()) {
LOG(WARNING) << "library " << hash.to_hex() << " not found in config";
if (std::any_of(libraries->result_.begin(), libraries->result_.end(),
[&hash](const auto& lib) { return lib->hash_.bits().equals(hash.cbits(), 256); })) {
return TonlibError::Internal("library is included in response but it's not found in proof");
}
continue;
}
block::gen::LibDescr::Record libdescr;
if (!tlb::csr_unpack(csr, libdescr)) {
return TonlibError::Internal("cannot unpack LibDescr record");
}

auto lib_it = std::find_if(libraries->result_.begin(), libraries->result_.end(),
[&hash](const auto& lib) { return lib->hash_.bits().equals(hash.cbits(), 256); });
if (lib_it == libraries->result_.end()) {
auto lib_it = std::find_if(libraries->result_.begin(), libraries->result_.end(),
[&hash](const auto& lib) { return lib->hash_.bits().equals(hash.cbits(), 256); });
if (lib_it == libraries->result_.end()) {
return TonlibError::Internal("library is found in proof but not in response");
}
auto& lib = *lib_it;
auto contents = vm::std_boc_deserialize(lib->data_);
if (!contents.is_ok() || contents.ok().is_null()) {
return TonlibError::Internal(PSLICE() << "cannot deserialize library cell " << lib->hash_.to_hex());
}
}
auto& lib = *lib_it;
auto contents = vm::std_boc_deserialize(lib->data_);
if (!contents.is_ok() || contents.ok().is_null()) {
return TonlibError::Internal(PSLICE() << "cannot deserialize library cell " << lib->hash_.to_hex());
}

if (!contents.ok()->get_hash().bits().equals(hash.cbits(), 256)) {
return TonlibError::Internal(PSLICE() << "library hash mismatch data " << contents.ok()->get_hash().to_hex() << " != requested " << hash.to_hex());
}
if (!contents.ok()->get_hash().bits().equals(hash.cbits(), 256)) {
return TonlibError::Internal(PSLICE() << "library hash mismatch data " << contents.ok()->get_hash().to_hex() << " != requested " << hash.to_hex());
}

if (contents.ok()->get_hash() != libres->get_hash()) {
return TonlibError::Internal(PSLICE() << "library hash mismatch data " << lib->hash_.to_hex() << " != proof " << libres->get_hash().to_hex());
if (contents.ok()->get_hash() != libdescr.lib->get_hash()) {
return TonlibError::Internal(PSLICE() << "library hash mismatch data " << lib->hash_.to_hex() << " != proof " << libdescr.lib->get_hash().to_hex());
}

result_entries.push_back(tonlib_api::make_object<tonlib_api::smc_libraryEntry>(lib->hash_, lib->data_.as_slice().str()));
self->libraries.set_ref(lib->hash_, contents.move_as_ok());
LOG(DEBUG) << "registered library " << lib->hash_.to_hex();
}

result_entries.push_back(tonlib_api::make_object<tonlib_api::smc_libraryEntry>(lib->hash_, lib->data_.as_slice().str()));
self->libraries.set_ref(lib->hash_, contents.move_as_ok());
LOG(DEBUG) << "registered library " << lib->hash_.to_hex();
self->store_libs_to_disk();
return tonlib_api::make_object<tonlib_api::smc_libraryResult>(std::move(result_entries));
} catch (vm::VmError& err) {
return TonlibError::Internal(PSLICE() << "error while checking getLibrariesWithProof proof: " << err.get_msg());
} catch (vm::VmVirtError& err) {
return TonlibError::Internal(PSLICE() << "virtualization error while checking getLibrariesWithProof proof: " << err.get_msg());
}
self->store_libs_to_disk();
return tonlib_api::make_object<tonlib_api::smc_libraryResult>(std::move(result_entries));
}));
}

Expand Down
59 changes: 31 additions & 28 deletions validator/impl/liteserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ void LiteQuery::perform() {
this->perform_getLibraries(q.library_list_);
},
[&](lite_api::liteServer_getLibrariesWithProof& q) {
this->perform_getLibrariesWithProof(ton::create_block_id(q.id_), q.library_list_);
this->perform_getLibrariesWithProof(ton::create_block_id(q.id_), q.mode_, q.library_list_);
},
[&](lite_api::liteServer_getShardBlockProof& q) {
this->perform_getShardBlockProof(create_block_id(q.id_));
Expand Down Expand Up @@ -970,7 +970,7 @@ void LiteQuery::continue_getLibraries(Ref<ton::validator::MasterchainState> mc_s
finish_query(std::move(b));
}

void LiteQuery::perform_getLibrariesWithProof(BlockIdExt blkid, std::vector<td::Bits256> library_list) {
void LiteQuery::perform_getLibrariesWithProof(BlockIdExt blkid, int mode, std::vector<td::Bits256> library_list) {
LOG(INFO) << "started a getLibrariesWithProof(<list of " << library_list.size() << " parameters>) liteserver query";
if (library_list.size() > 16) {
LOG(INFO) << "too many libraries requested, returning only first 16";
Expand All @@ -979,11 +979,11 @@ void LiteQuery::perform_getLibrariesWithProof(BlockIdExt blkid, std::vector<td::
sort( library_list.begin(), library_list.end() );
library_list.erase( unique( library_list.begin(), library_list.end() ), library_list.end() );

set_continuation([this, library_list]() -> void { continue_getLibrariesWithProof(library_list); });
set_continuation([this, library_list, mode]() -> void { continue_getLibrariesWithProof(library_list, mode); });
request_mc_block_data_state(blkid);
}

void LiteQuery::continue_getLibrariesWithProof(std::vector<td::Bits256> library_list) {
void LiteQuery::continue_getLibrariesWithProof(std::vector<td::Bits256> library_list, int mode) {
LOG(INFO) << "obtained masterchain block = " << base_blk_id_.to_str();
CHECK(mc_state_.not_null());

Expand All @@ -993,40 +993,43 @@ void LiteQuery::continue_getLibrariesWithProof(std::vector<td::Bits256> library_
}

vm::MerkleProofBuilder pb{mc_state_->root_cell()};

auto rconfig = block::ConfigInfo::extract_config(pb.root(), block::ConfigInfo::needLibraries);
if (rconfig.is_error()) {
fatal_error("cannot extract library list block configuration from masterchain state");
return;
}
auto config = rconfig.move_as_ok();

if (false) {
std::ostringstream os;
vm::load_cell_slice(config->get_libraries_root()).print_rec(os);
LOG(INFO) << "\n" << os.str();

auto lib_dict = std::make_unique<vm::Dictionary>(config->get_libraries_root(), 256);
for (auto k: *lib_dict) {
std::ostringstream oss;
k.second->print_rec(oss);
LOG(INFO) << "library " << k.first.to_hex(256) << ": \n" << oss.str();
}
block::gen::ShardStateUnsplit::Record state;
if (!tlb::unpack_cell(pb.root(), state)) {
fatal_error("cannot unpack header of shardchain state "s + base_blk_id_.to_str());
}
auto libraries_dict = vm::Dictionary(state.r1.libraries->prefetch_ref(), 256);

std::vector<ton::tl_object_ptr<ton::lite_api::liteServer_libraryEntry>> result;
for (const auto& hash : library_list) {
LOG(INFO) << "looking for library " << hash.to_hex();
auto libres = config->lookup_library(hash);
if (libres.is_null()) {
LOG(INFO) << "library lookup result is null";

auto csr = libraries_dict.lookup(hash.bits(), 256);
if (csr.is_null() || csr->prefetch_ulong(2) != 0 || !csr->have_refs()) { // shared_lib_descr$00 lib:^Cell
continue;
}
auto data = vm::std_boc_serialize(libres);
block::gen::LibDescr::Record libdescr;
if (!tlb::csr_unpack(csr, libdescr)) {
fatal_error("cannot unpack LibDescr record "s + hash.to_hex());
return;
}
if (!libdescr.lib->get_hash().bits().equals(hash.bits(), 256)) {
LOG(ERROR) << "public library hash mismatch: expected " << hash.to_hex() << " , found "
<< libdescr.lib->get_hash().to_hex();
continue;
}

auto data = vm::std_boc_serialize(libdescr.lib);
if (data.is_error()) {
LOG(WARNING) << "library serialization failed: " << data.move_as_error().to_string();
continue;
}
if (mode & 1) {
// include first 16 publishers in the proof
auto publishers_dict = vm::Dictionary{vm::DictNonEmpty(), libdescr.publishers, 256};
auto iter = publishers_dict.begin();
constexpr int max_publishers = 15; // set to 15 because publishers_dict.begin() counts as the first visit
for (int i = 0; i < max_publishers && iter != publishers_dict.end(); ++i, ++iter) {}
}
result.push_back(ton::create_tl_object<ton::lite_api::liteServer_libraryEntry>(hash, data.move_as_ok()));
}

Expand All @@ -1045,7 +1048,7 @@ void LiteQuery::continue_getLibrariesWithProof(std::vector<td::Bits256> library_
return;
}

auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_libraryResultWithProof>(ton::create_tl_lite_block_id(base_blk_id_), std::move(result),
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_libraryResultWithProof>(ton::create_tl_lite_block_id(base_blk_id_), mode, std::move(result),
state_proof_boc.move_as_ok(), data_proof_boc.move_as_ok());
finish_query(std::move(b));
}
Expand Down
4 changes: 2 additions & 2 deletions validator/impl/liteserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ class LiteQuery : public td::actor::Actor {
UnixTime gen_utime, LogicalTime gen_lt);
void perform_getLibraries(std::vector<td::Bits256> library_list);
void continue_getLibraries(Ref<MasterchainState> mc_state, BlockIdExt blkid, std::vector<td::Bits256> library_list);
void perform_getLibrariesWithProof(BlockIdExt blkid, std::vector<td::Bits256> library_list);
void continue_getLibrariesWithProof(std::vector<td::Bits256> library_list);
void perform_getLibrariesWithProof(BlockIdExt blkid, int mode, std::vector<td::Bits256> library_list);
void continue_getLibrariesWithProof(std::vector<td::Bits256> library_list, int mode);
void perform_getOneTransaction(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, LogicalTime lt);
void continue_getOneTransaction();
void perform_getTransactions(WorkchainId workchain, StdSmcAddress addr, LogicalTime lt, Bits256 hash, unsigned count);
Expand Down

0 comments on commit bba1fd2

Please sign in to comment.