Skip to content

Commit f4027a5

Browse files
feat: changelog event (#456)
* feat: Add event compatible with SPL account compression Alongside our `TransactionIndexerEvent` (which lets the clients restore their UTXO state and wallets from compressed accounts), emit also the new `ChangelogEvent`, which is mostly compatible with the event emited by SPL account compression program. * update pnpm lock * reverted transaction event enum --------- Co-authored-by: Michal Rostecki <vadorovsky@protonmail.com>
1 parent 799ab41 commit f4027a5

File tree

18 files changed

+956
-105
lines changed

18 files changed

+956
-105
lines changed

Cargo.lock

+199-28
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/accounts/merkle-tree-set-0.json

+3-3
Large diffs are not rendered by default.

merkle-tree/concurrent/src/lib.rs

+39-17
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub struct ConcurrentMerkleTree<
3737
pub next_index: u64,
3838
/// History of roots.
3939
pub roots: [[u8; 32]; MAX_ROOTS],
40+
/// Number of successful operations on the tree.
41+
pub sequence_number: u64,
4042
/// History of Merkle proofs.
4143
pub changelog: [ChangelogEntry<HEIGHT>; MAX_CHANGELOG],
4244
/// Index of the newest changelog.
@@ -61,6 +63,7 @@ where
6163
changelog: [ChangelogEntry::default(); MAX_CHANGELOG],
6264
current_changelog_index: 0,
6365
roots: [[0u8; 32]; MAX_ROOTS],
66+
sequence_number: 0,
6467
current_root_index: 0,
6568
rightmost_proof: [[0u8; 32]; HEIGHT],
6669
next_index: 0,
@@ -254,7 +257,7 @@ where
254257
new_leaf: &[u8; 32],
255258
leaf_index: usize,
256259
proof: &[[u8; 32]; HEIGHT],
257-
) -> Result<(), HasherError> {
260+
) -> Result<ChangelogEntry<HEIGHT>, HasherError> {
258261
let mut node = *new_leaf;
259262
let mut changelog_path = [[0u8; 32]; HEIGHT];
260263

@@ -301,7 +304,7 @@ where
301304
}
302305
}
303306

304-
Ok(())
307+
Ok(changelog_entry)
305308
}
306309

307310
/// Replaces the `old_leaf` under the `leaf_index` with a `new_leaf`, using
@@ -314,7 +317,7 @@ where
314317
new_leaf: &[u8; 32],
315318
leaf_index: usize,
316319
proof: &[[u8; 32]; HEIGHT],
317-
) -> Result<(), HasherError> {
320+
) -> Result<ChangelogEntry<HEIGHT>, HasherError> {
318321
let updated_proof = if self.next_index > 0 && MAX_CHANGELOG > 0 {
319322
match self.update_proof_or_leaf(changelog_index, leaf_index, proof) {
320323
Some(proof) => proof,
@@ -337,8 +340,13 @@ where
337340
self.update_leaf_in_tree(new_leaf, leaf_index, &updated_proof)
338341
}
339342

340-
/// Appends a new leaf to the tree.
341-
pub fn append(&mut self, leaf: &[u8; 32]) -> Result<(), HasherError> {
343+
/// Appends a new leaf to the tree with the given `changelog_entry` to save
344+
/// the Merkle path in.
345+
fn append_with_changelog_entry(
346+
&mut self,
347+
leaf: &[u8; 32],
348+
changelog_entry: &mut ChangelogEntry<HEIGHT>,
349+
) -> Result<(), HasherError> {
342350
if self.next_index >= 1 << HEIGHT {
343351
return Err(HasherError::TreeFull);
344352
}
@@ -397,13 +405,16 @@ where
397405
}
398406
}
399407

408+
changelog_entry.root = current_node;
409+
changelog_entry.path = changelog_path;
410+
changelog_entry.index = self.next_index;
411+
400412
self.inc_current_changelog_index();
401413
if let Some(changelog_element) = self
402414
.changelog
403415
.get_mut(self.current_changelog_index as usize)
404416
{
405-
*changelog_element =
406-
ChangelogEntry::new(current_node, changelog_path, self.next_index as usize)
417+
*changelog_element = *changelog_entry;
407418
}
408419
self.inc_current_root_index();
409420
*self
@@ -412,21 +423,32 @@ where
412423
.ok_or(HasherError::RootsZero)? = current_node;
413424
}
414425

415-
self.next_index += 1;
426+
self.sequence_number = self.sequence_number.saturating_add(1);
427+
self.next_index = self.next_index.saturating_add(1);
416428
self.rightmost_leaf = *leaf;
417429

418430
Ok(())
419431
}
420432

421-
/// Appends a new pair of leaves to the tree.
422-
pub fn append_two(
433+
/// Appends a new leaf to the tree.
434+
pub fn append(&mut self, leaf: &[u8; 32]) -> Result<ChangelogEntry<HEIGHT>, HasherError> {
435+
let mut changelog_entry = ChangelogEntry::default();
436+
self.append_with_changelog_entry(leaf, &mut changelog_entry)?;
437+
Ok(changelog_entry)
438+
}
439+
440+
/// Appends a new batch of leaves to the tree.
441+
pub fn append_batch<const N: usize>(
423442
&mut self,
424-
leaf_left: &[u8; 32],
425-
leaf_right: &[u8; 32],
426-
) -> Result<(), HasherError> {
427-
// TODO(vadorovsky): Instead of this naive double append, implement an
428-
// optimized insertion of two leaves.
429-
self.append(leaf_left)?;
430-
self.append(leaf_right)
443+
leaves: &[&[u8; 32]; N],
444+
) -> Result<[Box<ChangelogEntry<HEIGHT>>; N], HasherError> {
445+
let mut changelog_entries: [Box<ChangelogEntry<HEIGHT>>; N] =
446+
std::array::from_fn(|_| Box::<ChangelogEntry<HEIGHT>>::default());
447+
448+
for (leaf, changelog_entry) in leaves.iter().zip(changelog_entries.iter_mut()) {
449+
self.append_with_changelog_entry(leaf, changelog_entry)?;
450+
}
451+
452+
Ok(changelog_entries)
431453
}
432454
}

merkle-tree/indexed/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ where
5050
// to any other leaf yet.
5151
// This low leaf is going to be updated during the first `update`
5252
// operation.
53-
self.merkle_tree.append(&H::zero_indexed_leaf())
53+
self.merkle_tree.append(&H::zero_indexed_leaf())?;
54+
55+
Ok(())
5456
}
5557

5658
pub fn changelog_index(&self) -> usize {

0 commit comments

Comments
 (0)