Skip to content

Commit a2523e4

Browse files
committed
[CLAUDE-GENERATED] feat(avm): fast simulation optimizations
1 parent f6a20c6 commit a2523e4

File tree

14 files changed

+607
-150
lines changed

14 files changed

+607
-150
lines changed

barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/tx_execution.cpp

Lines changed: 116 additions & 109 deletions
Large diffs are not rendered by default.

barretenberg/cpp/src/barretenberg/vm2/simulation/interfaces/db.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,41 @@ class LowLevelMerkleDBInterface {
6767
virtual SequentialInsertionResult<NullifierLeafValue> insert_indexed_leaves_nullifier_tree(
6868
const NullifierLeafValue& leaf_value) = 0;
6969

70+
// Batch insert methods for indexed trees. These provide true batch insertion when
71+
// supported by the underlying implementation (e.g., WorldState).
72+
// Default implementations loop over single inserts for backwards compatibility.
73+
virtual void batch_insert_indexed_leaves_nullifier_tree(const std::vector<NullifierLeafValue>& leaves)
74+
{
75+
for (const auto& leaf : leaves) {
76+
insert_indexed_leaves_nullifier_tree(leaf);
77+
}
78+
}
79+
virtual void batch_insert_indexed_leaves_public_data_tree(const std::vector<PublicDataLeafValue>& leaves)
80+
{
81+
for (const auto& leaf : leaves) {
82+
insert_indexed_leaves_public_data_tree(leaf);
83+
}
84+
}
85+
7086
// todo(ilyas): does this need to be a vector of appendLeafResult? We should only care abou the end of appendings
7187
virtual std::vector<AppendLeafResult> append_leaves(MerkleTreeId tree_id, std::span<const FF> leaves) = 0;
7288

7389
virtual void pad_tree(MerkleTreeId tree_id, size_t num_leaves) = 0;
7490

91+
// Combined flush + pad methods: insert data AND padding in a single underlying tree write.
92+
// These avoid the overhead of separate insert and pad operations.
93+
// Default implementations do separate operations for backwards compatibility.
94+
virtual void flush_and_pad_nullifier_tree(const std::vector<NullifierLeafValue>& leaves, size_t padding_count)
95+
{
96+
batch_insert_indexed_leaves_nullifier_tree(leaves);
97+
pad_tree(MerkleTreeId::NULLIFIER_TREE, padding_count);
98+
}
99+
virtual void flush_and_pad_note_hash_tree(const std::vector<FF>& leaves, size_t padding_count)
100+
{
101+
append_leaves(MerkleTreeId::NOTE_HASH_TREE, leaves);
102+
pad_tree(MerkleTreeId::NOTE_HASH_TREE, padding_count);
103+
}
104+
75105
virtual void create_checkpoint() = 0;
76106
virtual void commit_checkpoint() = 0;
77107
virtual void revert_checkpoint() = 0;

barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,23 @@ SequentialInsertionResult<NullifierLeafValue> PureRawMerkleDB::insert_indexed_le
776776
return result;
777777
}
778778

779+
void PureRawMerkleDB::batch_insert_indexed_leaves_nullifier_tree(const std::vector<NullifierLeafValue>& leaves)
780+
{
781+
if (!leaves.empty()) {
782+
// Use WorldState's true batch insert - this is much faster than inserting one by one.
783+
ws_instance.insert_indexed_leaves<NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, leaves, ws_revision.forkId);
784+
}
785+
}
786+
787+
void PureRawMerkleDB::batch_insert_indexed_leaves_public_data_tree(const std::vector<PublicDataLeafValue>& leaves)
788+
{
789+
if (!leaves.empty()) {
790+
// Use WorldState's true batch insert - this is much faster than inserting one by one.
791+
ws_instance.insert_indexed_leaves<PublicDataLeafValue>(
792+
MerkleTreeId::PUBLIC_DATA_TREE, leaves, ws_revision.forkId);
793+
}
794+
}
795+
779796
// This method currently returns a vector of intermediate roots and sibling paths, but in practice we might only
780797
// need or care about the last one for simulation, this would simplify how we append in this function.
781798
// todo(ilyas): Given this function says append, perhaps we just want to restrict to NoteHash?
@@ -811,6 +828,33 @@ void PureRawMerkleDB::pad_tree(MerkleTreeId tree_id, size_t num_leaves)
811828
}
812829
}
813830

831+
void PureRawMerkleDB::flush_and_pad_nullifier_tree(const std::vector<NullifierLeafValue>& leaves, size_t padding_count)
832+
{
833+
// Combine data and padding into a single batch insert.
834+
std::vector<NullifierLeafValue> combined;
835+
combined.reserve(leaves.size() + padding_count);
836+
combined.insert(combined.end(), leaves.begin(), leaves.end());
837+
combined.insert(combined.end(), padding_count, NullifierLeafValue::empty());
838+
839+
if (!combined.empty()) {
840+
ws_instance.batch_insert_indexed_leaves(
841+
MerkleTreeId::NULLIFIER_TREE, combined, NULLIFIER_SUBTREE_HEIGHT, ws_revision.forkId);
842+
}
843+
}
844+
845+
void PureRawMerkleDB::flush_and_pad_note_hash_tree(const std::vector<FF>& leaves, size_t padding_count)
846+
{
847+
// Combine data and padding into a single append_leaves call.
848+
std::vector<FF> combined;
849+
combined.reserve(leaves.size() + padding_count);
850+
combined.insert(combined.end(), leaves.begin(), leaves.end());
851+
combined.insert(combined.end(), padding_count, FF(0));
852+
853+
if (!combined.empty()) {
854+
ws_instance.append_leaves(MerkleTreeId::NOTE_HASH_TREE, combined, ws_revision.forkId);
855+
}
856+
}
857+
814858
void PureRawMerkleDB::create_checkpoint()
815859
{
816860
ws_instance.checkpoint(ws_revision.forkId);

barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,14 @@ class PureRawMerkleDB final : public LowLevelMerkleDBInterface {
133133
const PublicDataLeafValue& leaf_value) override;
134134
SequentialInsertionResult<NullifierLeafValue> insert_indexed_leaves_nullifier_tree(
135135
const NullifierLeafValue& leaf_value) override;
136+
// True batch insert methods that use WorldState's batch APIs.
137+
void batch_insert_indexed_leaves_nullifier_tree(const std::vector<NullifierLeafValue>& leaves) override;
138+
void batch_insert_indexed_leaves_public_data_tree(const std::vector<PublicDataLeafValue>& leaves) override;
136139
std::vector<AppendLeafResult> append_leaves(MerkleTreeId tree_id, std::span<const FF> leaves) override;
137140
void pad_tree(MerkleTreeId tree_id, size_t num_leaves) override;
141+
// Combined flush + pad methods for single tree write.
142+
void flush_and_pad_nullifier_tree(const std::vector<NullifierLeafValue>& leaves, size_t padding_count) override;
143+
void flush_and_pad_note_hash_tree(const std::vector<FF>& leaves, size_t padding_count) override;
138144

139145
void create_checkpoint() override;
140146
void commit_checkpoint() override;

0 commit comments

Comments
 (0)