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

Add method listBlockTransactionsExt to liteserver (#399)

* Verify proof for method blocks.getTransactions

* check completeness of response

* fix start_lt

* fix mode & 128, check bTxes->ids_ out of bounds

* Improve gitactions; separate cpp-check (#346)

* Use ninja build tool and compile blockchain-explorer

Ninja builds TON much faster;

* Use clang instead of gcc

* remove blockchain-explorer

since target not found on github action

* move ccpcheck to other gitaction

* run nativelib-java only against wallets branch for now

* rename gitaction

* Update windows2019x64-tonlib-java.yml

* Update windows2019x64-tonlib-java.yml

* Update macos-10.15-tonlib-java.yml

* Update windows2019x64-tonlib-java.yml

* Update windows2019x64-tonlib-java.yml

* rebase

* update tlo's

* Revert "Improve gitactions; separate cpp-check (#346)"

This reverts commit bd1d96e6d391e48840d81cfcf10d2692848e504e.

* add checks, simplify ls response

* Revert workflows

* Add verifying proofs

* fix win build

---------

Co-authored-by: neodiX42 <namlem@gmail.com>
This commit is contained in:
Marat 2023-03-07 16:49:25 +00:00 committed by GitHub
parent 4db7ad039a
commit 078aabe50e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 502 additions and 16 deletions

View file

@ -315,6 +315,113 @@ td::Result<TransactionList::Info> TransactionList::validate() const {
return std::move(res);
}
td::Result<BlockTransaction::Info> BlockTransaction::validate(bool check_proof) const {
if (root.is_null()) {
return td::Status::Error("transactions are expected to be non-empty");
}
if (check_proof && proof->get_hash().bits().compare(root->get_hash().bits(), 256)) {
return td::Status::Error(PSLICE() << "transaction hash mismatch: Merkle proof expects "
<< proof->get_hash().bits().to_hex(256)
<< " but received data has " << root->get_hash().bits().to_hex(256));
}
block::gen::Transaction::Record trans;
if (!tlb::unpack_cell(root, trans)) {
return td::Status::Error("cannot unpack transaction cell");
}
Info res;
res.blkid = blkid;
res.now = trans.now;
res.lt = trans.lt;
res.hash = root->get_hash().bits();
res.transaction = root;
return std::move(res);
}
td::Result<BlockTransactionList::Info> BlockTransactionList::validate(bool check_proof) const {
constexpr int max_answer_transactions = 256;
TRY_RESULT_PREFIX(list, vm::std_boc_deserialize_multi(std::move(transactions_boc)), "cannot deserialize transactions boc: ");
std::vector<td::Ref<vm::Cell>> tx_proofs(list.size());
if (check_proof) {
try {
TRY_RESULT(proof_cell, vm::std_boc_deserialize(std::move(proof_boc)));
auto virt_root = vm::MerkleProof::virtualize(proof_cell, 1);
if (blkid.root_hash != virt_root->get_hash().bits()) {
return td::Status::Error("Invalid block proof root hash");
}
block::gen::Block::Record blk;
block::gen::BlockExtra::Record extra;
if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(std::move(blk.extra), extra))) {
return td::Status::Error("Error unpacking proof cell");
}
vm::AugmentedDictionary acc_dict{vm::load_cell_slice_ref(extra.account_blocks), 256,
block::tlb::aug_ShardAccountBlocks};
bool eof = false;
ton::LogicalTime reverse = reverse_mode ? ~0ULL : 0;
ton::LogicalTime trans_lt = static_cast<ton::LogicalTime>(start_lt);
td::Bits256 cur_addr = start_addr;
bool allow_same = true;
int count = 0;
while (!eof && count < req_count && count < max_answer_transactions) {
auto value = acc_dict.extract_value(
acc_dict.vm::DictionaryFixed::lookup_nearest_key(cur_addr.bits(), 256, !reverse, allow_same));
if (value.is_null()) {
eof = true;
break;
}
allow_same = false;
if (cur_addr != start_addr) {
trans_lt = reverse;
}
block::gen::AccountBlock::Record acc_blk;
if (!tlb::csr_unpack(std::move(value), acc_blk) || acc_blk.account_addr != cur_addr) {
return td::Status::Error("Error unpacking proof account block");
}
vm::AugmentedDictionary trans_dict{vm::DictNonEmpty(), std::move(acc_blk.transactions), 64,
block::tlb::aug_AccountTransactions};
td::BitArray<64> cur_trans{(long long)trans_lt};
while (count < req_count && count < max_answer_transactions) {
auto tvalue = trans_dict.extract_value_ref(
trans_dict.vm::DictionaryFixed::lookup_nearest_key(cur_trans.bits(), 64, !reverse));
if (tvalue.is_null()) {
trans_lt = reverse;
break;
}
if (static_cast<size_t>(count) < tx_proofs.size()) {
tx_proofs[count] = std::move(tvalue);
}
count++;
}
}
if (static_cast<size_t>(count) != list.size()) {
return td::Status::Error(PSLICE() << "Txs count mismatch in proof (" << count << ") and response (" << list.size() << ")");
}
} catch (vm::VmError& err) {
return err.as_status("Couldn't verify proof: ");
} catch (vm::VmVirtError& err) {
return err.as_status("Couldn't verify proof: ");
} catch (...) {
return td::Status::Error("Unknown exception raised while verifying proof");
}
}
Info res;
for (int i = 0; i < static_cast<int>(list.size()); i++) {
auto& root = list[i];
BlockTransaction transaction;
transaction.root = root;
transaction.blkid = blkid;
transaction.proof = tx_proofs[i];
TRY_RESULT(info, transaction.validate(check_proof));
res.transactions.push_back(std::move(info));
}
return std::move(res);
}
td::Status BlockProofLink::validate(td::uint32* save_utime) const {
if (save_utime) {
*save_utime = 0;