Skip to content

Merkle Optimisation#85

Open
dkgoutham wants to merge 36 commits intomainfrom
feature/merkle-optimisation
Open

Merkle Optimisation#85
dkgoutham wants to merge 36 commits intomainfrom
feature/merkle-optimisation

Conversation

@dkgoutham
Copy link
Copy Markdown

Summary

  • Add insert_at(leaf, index) to MerkleTree for targeted insertion, replacing a 1024-iteration insert loop in transaction-builder with a single call
  • Add serialize()/deserialize() for MerkleTree with IndexedDB tree_snapshots store, so page reloads restore the tree from a snapshot instead of replaying all leaves
  • Add build_from_leaves() batch constructor that builds the tree in a single bottom-up pass, used when rebuilding from > 100 stored leaves

Base automatically changed from fetaure/transfers to main February 4, 2026 09:02
next_index: u64,
}

// TODO: For now we implement a full merkle tree. We should study if a partial
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove the TODO if we solve it

Comment on lines +160 to +165
if index_u64 > self.next_index {
return Err(format!(
"insert_at: index {} exceeds next_index {}, would create gap",
index, self.next_index
));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is what we want. The idea of having insertAt is to allow these gaps to happen, and to be solved when receiving missing leaves later.
E.g., If a user receives leaf 8 5ms before leaf 7, it does not panic, and after 5 ms the root will be the same as if we received leaves in order.
If something fails, besides reasonable delays, the root won't match, and the proof will fail. But that will be caused by other issues (e.g. RPC failures).

let parent_level = level
.checked_add(1)
.ok_or_else(|| JsValue::from_str("Level overflow"))?;
let parent_level = level.checked_add(1).expect("level < depth <= 32");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use Result as return value instead of expect

Comment on lines +570 to +572
tree.insert(&leaf(1)).expect("insert 0");
tree.insert(&leaf(2)).expect("insert 1");
tree.insert(&leaf(3)).expect("insert 2");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of nitpicking. Expect works for tests, but error messages could be more detailed

}


await persistTree();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works. But it means we serialize and save the tree after each processed leaf. Not sure if it could be batched to make fewer allocations. Can be addressed on a different PR. Feel free to ignore.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also happens in pool-store.js

Comment on lines +225 to +227
if (!poolStore.isTreeInitialized()) {
await poolStore.rebuildTree();
}
Copy link
Copy Markdown
Contributor

@Fantoni0 Fantoni0 Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that the tree will be rebuilt only if it is null. Meaning that we assume the restored version will be up to date. If the restored version is missing any leaves for any reason, it will fail.

I did try to run a small demo (see https://github.com/NethermindEth/stellar-private-transactions?tab=readme-ov-file#demo-application), but the deposit failed. Probably because there's a mismatch between the off-chain and on-chain roots.
That was an error on my end, due to a mixed state from a previous deployment. The demo still works. So it seems the assumption is correct so far 🙌

Copy link
Copy Markdown
Contributor

@Fantoni0 Fantoni0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is good 🙌 , but some changes can be made. And we need to ensure it does note break the demo functionality.

torisamples pushed a commit to torisamples/stellar-private-payments that referenced this pull request Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants