Skip to content

Commit 3daa6f7

Browse files
committed
Remove concept of virtualization level
But for a single place in test-db, we used virtualization level 0 for non-virtualized cells and level 1 for virtualized ones. With this patch, we do not store this level anymore and instead infer it based on "effective" level (previously known as VirtualizationParameters::level) and the actual level of the cell. This is mainly done to reduce cognitive complexity of the code. However, as a nice side-effect, changes in VirtualCell give a negligible performance improvement on the verification benchmark.
1 parent 413b898 commit 3daa6f7

36 files changed

+142
-228
lines changed

blockchain-explorer/blockchain-explorer-http.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
366366
last_trans_hash.set_zero();
367367
block::CurrencyCollection balance = block::CurrencyCollection::zero();
368368
try {
369-
auto state_root = vm::MerkleProof::virtualize(acc_c.q_roots[1], 1);
369+
auto state_root = vm::MerkleProof::virtualize(acc_c.q_roots[1]);
370370
if (state_root.is_null()) {
371371
abort("account state proof is invalid");
372372
return *this;
@@ -474,7 +474,7 @@ HttpAnswer& HttpAnswer::operator<<(BlockHeaderCell head_c) {
474474
vm::CellSlice cs{vm::NoVm(), head_c.root};
475475
auto block_id = head_c.block_id;
476476
try {
477-
auto virt_root = vm::MerkleProof::virtualize(head_c.root, 1);
477+
auto virt_root = vm::MerkleProof::virtualize(head_c.root);
478478
if (virt_root.is_null()) {
479479
abort("invalid merkle proof");
480480
return *this;

crypto/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ set(TON_CRYPTO_CORE_SOURCE
7878
vm/cells/PrunnedCell.h
7979
vm/cells/UsageCell.h
8080
vm/cells/VirtualCell.h
81-
vm/cells/VirtualizationParameters.h
8281

8382
vm/cells.h
8483
vm/cellslice.h

crypto/block/check-proof.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blki
7373

7474
td::Result<td::Bits256> check_state_proof(ton::BlockIdExt blkid, td::Slice proof) {
7575
TRY_RESULT(proof_root, vm::std_boc_deserialize(proof));
76-
auto virt_root = vm::MerkleProof::virtualize(std::move(proof_root), 1);
76+
auto virt_root = vm::MerkleProof::virtualize(std::move(proof_root));
7777
if (virt_root.is_null()) {
7878
return td::Status::Error("account state proof is invalid");
7979
}
@@ -86,7 +86,7 @@ td::Result<Ref<vm::Cell>> check_extract_state_proof(ton::BlockIdExt blkid, td::S
8686
try {
8787
TRY_RESULT(state_hash, check_state_proof(blkid, proof));
8888
TRY_RESULT(state_root, vm::std_boc_deserialize(data));
89-
auto state_virt_root = vm::MerkleProof::virtualize(std::move(state_root), 1);
89+
auto state_virt_root = vm::MerkleProof::virtualize(std::move(state_root));
9090
if (state_virt_root.is_null()) {
9191
return td::Status::Error("account state proof is invalid");
9292
}
@@ -118,13 +118,13 @@ td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td:
118118
return td::Status::Error("shard configuration proof must have exactly two roots");
119119
}
120120
try {
121-
auto mc_state_root = vm::MerkleProof::virtualize(std::move(P_roots[1]), 1);
121+
auto mc_state_root = vm::MerkleProof::virtualize(std::move(P_roots[1]));
122122
if (mc_state_root.is_null()) {
123123
return td::Status::Error("shard configuration proof is invalid");
124124
}
125125
ton::Bits256 mc_state_hash = mc_state_root->get_hash().bits();
126126
TRY_STATUS_PREFIX(
127-
check_block_header_proof(vm::MerkleProof::virtualize(std::move(P_roots[0]), 1), blk, &mc_state_hash, true),
127+
check_block_header_proof(vm::MerkleProof::virtualize(std::move(P_roots[0])), blk, &mc_state_hash, true),
128128
"error in shard configuration block header proof :");
129129
block::gen::ShardStateUnsplit::Record sstate;
130130
if (!(tlb::unpack_cell(mc_state_root, sstate))) {
@@ -171,12 +171,12 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const
171171
}
172172

173173
try {
174-
auto state_root = vm::MerkleProof::virtualize(std::move(Q_roots[1]), 1);
174+
auto state_root = vm::MerkleProof::virtualize(std::move(Q_roots[1]));
175175
if (state_root.is_null()) {
176176
return td::Status::Error("account state proof is invalid");
177177
}
178178
ton::Bits256 state_hash = state_root->get_hash().bits();
179-
TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk,
179+
TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0])), shard_blk,
180180
&state_hash, true, save_utime, save_lt),
181181
"error in account shard block header proof : ");
182182
block::gen::ShardStateUnsplit::Record sstate;
@@ -223,7 +223,7 @@ td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, b
223223
Ref<vm::Cell> root;
224224

225225
if (is_virtualized && true_root.not_null()) {
226-
root = vm::MerkleProof::virtualize(true_root, 1);
226+
root = vm::MerkleProof::virtualize(true_root);
227227
if (root.is_null()) {
228228
return td::Status::Error("account state proof is invalid");
229229
}
@@ -346,7 +346,7 @@ td::Result<BlockTransactionList::Info> BlockTransactionList::validate(bool check
346346
if (check_proof) {
347347
try {
348348
TRY_RESULT(proof_cell, vm::std_boc_deserialize(std::move(proof_boc)));
349-
auto virt_root = vm::MerkleProof::virtualize(proof_cell, 1);
349+
auto virt_root = vm::MerkleProof::virtualize(proof_cell);
350350

351351
if (blkid.root_hash != virt_root->get_hash().bits()) {
352352
return td::Status::Error("Invalid block proof root hash");
@@ -452,15 +452,15 @@ td::Status BlockProofLink::validate(td::uint32* save_utime) const {
452452
}
453453
try {
454454
// virtualize Merkle proof roots
455-
auto vs_root = vm::MerkleProof::virtualize(proof, 1);
455+
auto vs_root = vm::MerkleProof::virtualize(proof);
456456
if (vs_root.is_null()) {
457457
return td::Status::Error("BlockProofLink contains an invalid Merkle proof for source block "s + from.to_str());
458458
}
459459
ton::Bits256 state_hash;
460460
if (from.seqno()) {
461461
TRY_STATUS(check_block_header(vs_root, from, is_fwd ? nullptr : &state_hash));
462462
}
463-
auto vd_root = dest_proof.not_null() ? vm::MerkleProof::virtualize(dest_proof, 1) : Ref<vm::Cell>{};
463+
auto vd_root = dest_proof.not_null() ? vm::MerkleProof::virtualize(dest_proof) : Ref<vm::Cell>{};
464464
if (vd_root.is_null() && to.seqno()) {
465465
return td::Status::Error("BlockProofLink contains an invalid Merkle proof for destination block "s + to.to_str());
466466
}
@@ -483,7 +483,7 @@ td::Status BlockProofLink::validate(td::uint32* save_utime) const {
483483
}
484484
if (!is_fwd) {
485485
// check a backward link
486-
auto vstate_root = vm::MerkleProof::virtualize(state_proof, 1);
486+
auto vstate_root = vm::MerkleProof::virtualize(state_proof);
487487
if (vstate_root.is_null()) {
488488
return td::Status::Error("backward BlockProofLink contains an invalid Merkle proof for source state "s +
489489
from.to_str());

crypto/test/test-db.cpp

+21-21
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,13 @@ TEST(Cell, MerkleProof) {
663663
auto proof = MerkleProof::generate(cell, is_prunned);
664664
// CellBuilder::virtualize(proof, 1);
665665
//ASSERT_EQ(1u, proof->get_level());
666-
auto virtualized_proof = MerkleProof::virtualize(proof, 1);
666+
auto virtualized_proof = MerkleProof::virtualize(proof);
667667
auto exploration3 = CellExplorer::explore(virtualized_proof, exploration.ops);
668668
ASSERT_EQ(exploration.log, exploration3.log);
669669

670670
auto proof2 = MerkleProof::generate(cell, usage_tree.get());
671671
CHECK(proof2->get_depth() == proof->get_depth());
672-
auto virtualized_proof2 = MerkleProof::virtualize(proof2, 1);
672+
auto virtualized_proof2 = MerkleProof::virtualize(proof2);
673673
auto exploration4 = CellExplorer::explore(virtualized_proof2, exploration.ops);
674674
ASSERT_EQ(exploration.log, exploration4.log);
675675
}
@@ -690,7 +690,7 @@ TEST(Cell, MerkleProofCombine) {
690690
CellExplorer::explore(usage_cell, exploration1.ops);
691691
proof1 = MerkleProof::generate(cell, usage_tree.get());
692692

693-
auto virtualized_proof = MerkleProof::virtualize(proof1, 1);
693+
auto virtualized_proof = MerkleProof::virtualize(proof1);
694694
auto exploration = CellExplorer::explore(virtualized_proof, exploration1.ops);
695695
ASSERT_EQ(exploration.log, exploration1.log);
696696
}
@@ -702,7 +702,7 @@ TEST(Cell, MerkleProofCombine) {
702702
CellExplorer::explore(usage_cell, exploration2.ops);
703703
proof2 = MerkleProof::generate(cell, usage_tree.get());
704704

705-
auto virtualized_proof = MerkleProof::virtualize(proof2, 1);
705+
auto virtualized_proof = MerkleProof::virtualize(proof2);
706706
auto exploration = CellExplorer::explore(virtualized_proof, exploration2.ops);
707707
ASSERT_EQ(exploration.log, exploration2.log);
708708
}
@@ -715,7 +715,7 @@ TEST(Cell, MerkleProofCombine) {
715715
CellExplorer::explore(usage_cell, exploration2.ops);
716716
proof12 = MerkleProof::generate(cell, usage_tree.get());
717717

718-
auto virtualized_proof = MerkleProof::virtualize(proof12, 1);
718+
auto virtualized_proof = MerkleProof::virtualize(proof12);
719719
auto exploration_a = CellExplorer::explore(virtualized_proof, exploration1.ops);
720720
auto exploration_b = CellExplorer::explore(virtualized_proof, exploration2.ops);
721721
ASSERT_EQ(exploration_a.log, exploration1.log);
@@ -724,7 +724,7 @@ TEST(Cell, MerkleProofCombine) {
724724

725725
{
726726
auto check = [&](auto proof_union) {
727-
auto virtualized_proof = MerkleProof::virtualize(proof_union, 1);
727+
auto virtualized_proof = MerkleProof::virtualize(proof_union);
728728
auto exploration_a = CellExplorer::explore(virtualized_proof, exploration1.ops);
729729
auto exploration_b = CellExplorer::explore(virtualized_proof, exploration2.ops);
730730
ASSERT_EQ(exploration_a.log, exploration1.log);
@@ -738,14 +738,14 @@ TEST(Cell, MerkleProofCombine) {
738738
check(proof_union_fast);
739739
}
740740
{
741-
cell = MerkleProof::virtualize(proof12, 1);
741+
cell = MerkleProof::virtualize(proof12);
742742

743743
auto usage_tree = std::make_shared<CellUsageTree>();
744744
auto usage_cell = UsageCell::create(cell, usage_tree->root_ptr());
745745
CellExplorer::explore(usage_cell, exploration1.ops);
746746
auto proof = MerkleProof::generate(cell, usage_tree.get());
747747

748-
auto virtualized_proof = MerkleProof::virtualize(proof, 2);
748+
auto virtualized_proof = MerkleProof::virtualize(proof);
749749
auto exploration = CellExplorer::explore(virtualized_proof, exploration1.ops);
750750
ASSERT_EQ(exploration.log, exploration1.log);
751751
if (proof->get_hash() != proof1->get_hash()) {
@@ -2152,28 +2152,28 @@ TEST(Cell, MerkleProofHands) {
21522152
test_boc_deserializer_full(merkle_proof).ensure();
21532153

21542154
{
2155-
auto virtual_node = proof->virtualize({0, 1});
2155+
auto virtual_node = proof->virtualize(0);
21562156
ASSERT_EQ(0u, virtual_node->get_level());
2157-
ASSERT_EQ(1u, virtual_node->get_virtualization());
2157+
ASSERT_EQ(1u, virtual_node->is_virtualized());
21582158
CellSlice cs{NoVm(), virtual_node};
21592159
auto virtual_data = cs.fetch_ref();
21602160
ASSERT_EQ(0u, virtual_data->get_level());
2161-
ASSERT_EQ(1u, virtual_data->get_virtualization());
2161+
ASSERT_EQ(1u, virtual_data->is_virtualized());
21622162
ASSERT_EQ(data->get_hash(), virtual_data->get_hash());
21632163

21642164
auto virtual_node_copy =
21652165
CellBuilder{}.store_bits(node->get_data(), node->get_bits()).store_ref(virtual_data).finalize();
21662166
ASSERT_EQ(0u, virtual_node_copy->get_level());
2167-
ASSERT_EQ(1u, virtual_node_copy->get_virtualization());
2167+
ASSERT_EQ(1u, virtual_node_copy->is_virtualized());
21682168
ASSERT_EQ(virtual_node->get_hash(), virtual_node_copy->get_hash());
21692169

21702170
{
21712171
auto two_nodes = CellBuilder{}.store_ref(virtual_node).store_ref(node).finalize();
21722172
ASSERT_EQ(0u, two_nodes->get_level());
2173-
ASSERT_EQ(1u, two_nodes->get_virtualization());
2173+
ASSERT_EQ(1u, two_nodes->is_virtualized());
21742174
CellSlice cs2(NoVm(), two_nodes);
2175-
ASSERT_EQ(1u, cs2.prefetch_ref(0)->get_virtualization());
2176-
ASSERT_EQ(0u, cs2.prefetch_ref(1)->get_virtualization());
2175+
ASSERT_EQ(1u, cs2.prefetch_ref(0)->is_virtualized());
2176+
ASSERT_EQ(0u, cs2.prefetch_ref(1)->is_virtualized());
21772177
}
21782178
}
21792179
LOG(ERROR) << td::NamedThreadSafeCounter::get_default();
@@ -2195,7 +2195,7 @@ TEST(Cell, MerkleProofArrayHands) {
21952195
ASSERT_TRUE(proof->get_hash(1) != arr.root()->get_hash(1));
21962196
ASSERT_EQ(arr.root()->get_hash(0), arr.root()->get_hash(1));
21972197

2198-
CompactArray new_arr(arr.size(), proof->virtualize({0, 1}));
2198+
CompactArray new_arr(arr.size(), proof->virtualize(0));
21992199
for (auto k : keys) {
22002200
ASSERT_EQ(arr.get(k), new_arr.get(k));
22012201
}
@@ -2222,7 +2222,7 @@ TEST(Cell, MerkleProofCombineArray) {
22222222
}
22232223
}
22242224

2225-
CompactArray arr2(n, vm::MerkleProof::virtualize(root, 1));
2225+
CompactArray arr2(n, vm::MerkleProof::virtualize(root));
22262226
for (size_t i = 0; i < n; i++) {
22272227
CHECK(arr.get(i) == arr2.get(i));
22282228
}
@@ -2920,7 +2920,7 @@ TEST(TonDb, BocRespectsUsageCell) {
29202920
auto usage_cell = vm::UsageCell::create(cell, usage_tree->root_ptr());
29212921
auto serialization = serialize_boc(usage_cell);
29222922
auto proof = vm::MerkleProof::generate(cell, usage_tree.get());
2923-
auto virtualized_proof = vm::MerkleProof::virtualize(proof, 1);
2923+
auto virtualized_proof = vm::MerkleProof::virtualize(proof);
29242924
auto serialization_of_virtualized_cell = serialize_boc(virtualized_proof);
29252925
ASSERT_STREQ(serialization, serialization_of_virtualized_cell);
29262926
}
@@ -2946,7 +2946,7 @@ TEST(UsageTree, ThreadSafe) {
29462946
thread.join();
29472947
}
29482948
auto proof = vm::MerkleProof::generate(cell, usage_tree.get());
2949-
auto virtualized_proof = vm::MerkleProof::virtualize(proof, 1);
2949+
auto virtualized_proof = vm::MerkleProof::virtualize(proof);
29502950
for (auto &exploration : explorations) {
29512951
auto new_exploration = vm::CellExplorer::explore(virtualized_proof, exploration.ops);
29522952
ASSERT_EQ(exploration.log, new_exploration.log);
@@ -3024,8 +3024,8 @@ TEST(TonDb, DoNotMakeListsPrunned) {
30243024
auto cell = vm::CellBuilder().store_bytes("abc").finalize();
30253025
auto is_prunned = [&](const td::Ref<vm::Cell> &cell) { return true; };
30263026
auto proof = vm::MerkleProof::generate(cell, is_prunned);
3027-
auto virtualized_proof = vm::MerkleProof::virtualize(proof, 1);
3028-
ASSERT_TRUE(virtualized_proof->get_virtualization() == 0);
3027+
auto virtualized_proof = vm::MerkleProof::virtualize(proof);
3028+
ASSERT_TRUE(!virtualized_proof->is_virtualized());
30293029
}
30303030

30313031
TEST(TonDb, CellStat) {

crypto/vm/boc.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ int BagOfCells::add_root(td::Ref<vm::Cell> add_root) {
163163
if (add_root.is_null()) {
164164
return 0;
165165
}
166-
LOG_CHECK(add_root->get_virtualization() == 0) << "TODO: support serialization of virtualized cells";
166+
LOG_CHECK(!add_root->is_virtualized()) << "TODO: support serialization of virtualized cells";
167167
//const Cell::Hash& hash = add_root->get_hash();
168168
//for (const auto& root_info : roots) {
169169
//if (root_info.cell->get_hash() == hash) {
@@ -217,7 +217,7 @@ td::Result<int> BagOfCells::import_cell(td::Ref<vm::Cell> cell, int depth) {
217217
cell_list_[pos].should_cache = true;
218218
return pos;
219219
}
220-
if (cell->get_virtualization() != 0) {
220+
if (cell->is_virtualized()) {
221221
return td::Status::Error(
222222
"error while importing a cell into a bag of cells: cell has non-zero virtualization level");
223223
}

crypto/vm/cells/Cell.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ td::Status Cell::check_equals_unloaded(const Ref<Cell>& other) const {
4848
return td::Status::OK();
4949
}
5050

51-
Ref<Cell> Cell::virtualize(VirtualizationParameters virt) const {
52-
return VirtualCell::create(virt, Ref<Cell>(this));
51+
Ref<Cell> Cell::virtualize(td::uint32 effective_level) const {
52+
return VirtualCell::create(effective_level, Ref<Cell>(this));
5353
}
5454

5555
std::ostream& operator<<(std::ostream& os, const Cell& c) {

crypto/vm/cells/Cell.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "vm/cells/CellTraits.h"
2626
#include "vm/cells/CellUsageTree.h"
2727
#include "vm/cells/LevelMask.h"
28-
#include "vm/cells/VirtualizationParameters.h"
2928

3029
#include "td/utils/Status.h"
3130

@@ -38,10 +37,9 @@ class DataCell;
3837
class Cell : public CellTraits {
3938
public:
4039
using LevelMask = detail::LevelMask;
41-
using VirtualizationParameters = detail::VirtualizationParameters;
4240
struct LoadedCell {
4341
Ref<DataCell> data_cell;
44-
VirtualizationParameters virt;
42+
td::uint32 effective_level;
4543
CellUsageTree::NodePtr tree_node; // TODO: inline_vector?
4644
};
4745

@@ -57,8 +55,9 @@ class Cell : public CellTraits {
5755
// load interface
5856
virtual td::Status set_data_cell(Ref<DataCell> &&data_cell) const = 0;
5957
virtual td::Result<LoadedCell> load_cell() const = 0;
60-
virtual Ref<Cell> virtualize(VirtualizationParameters virt) const;
61-
virtual td::uint32 get_virtualization() const = 0;
58+
virtual Ref<Cell> virtualize(td::uint32 effective_level) const;
59+
// Cell is virtualized if its effective level is less than its actual level.
60+
virtual bool is_virtualized() const = 0;
6261
virtual CellUsageTree::NodePtr get_tree_node() const = 0;
6362
virtual bool is_loaded() const = 0;
6463

crypto/vm/cells/CellBuilder.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ Ref<DataCell> CellBuilder::finalize(bool special) {
100100
}
101101

102102
Ref<Cell> CellBuilder::create_pruned_branch(Ref<Cell> cell, td::uint32 new_level, td::uint32 virt_level) {
103-
if (cell->is_loaded() && cell->get_level() <= virt_level && cell->get_virtualization() == 0) {
103+
if (cell->is_loaded() && cell->get_level() <= virt_level && !cell->is_virtualized()) {
104104
CellSlice cs(NoVm{}, cell);
105105
if (cs.size_refs() == 0) {
106106
return cell;

0 commit comments

Comments
 (0)