rollkit/iavl

Add deep trees for IAVL, for fraud proofs and stateless execution

musalbas opened this issue · 1 comments

This should be done in a separate branch eg (deepiavl), as we shouldn't assume this will be merged into iavl upstream.

How to add deep trees:

  1. Add a DeepTree (deep_tree.go) that inherits or extends MutableTree
  2. Modify this Verify function and the functions it calls to add a DeepTree instance as an (optional) parameter, all the way down the stack into computeRootHash
  3. In pathWithLeaf.computeRootHash and pathToLeaf.computeRootHash, every time a hash for a leaf or a node is computed, add it to to the nodeCache in the nodeDB of the MutableTree of the DeepTree (or your own custom cache/map), by creating new Node() object with nil left and right nodes
  4. After a range proof is verified with Verify(), DeepTree should loop through all the the entries in nodeCache to populate Node objects with pointers to their respective left and right Node objects, where available (you can also do this step inside computeRootHash instead of doing it after, as well)
  5. You can now call Set() in MutableTree with the root node to update values in the deep tree (you'll need to set the ImmutableTree's root first), and call Hash() in MutableTree's ImmutableTree to get the root hash

Tracking:

Based on https://github.com/cosmos/iavl/blob/master/docs/proof/proof.md I think some extra steps will also be needed:

  1. We might need to modify the proof so that it includes the values of the sibling nodes, not just the hashes, as we need to know those in order for Set() to know if it needs to do any re-balancing operations, as the size of nodes are in their values, not hashes. I think this may up to ~double the hashes in the proof in the worse case. I think this is fine because we can optimize this later on as we only need to include these nodes for insertions and deletions, not updates (as updates don't need a rebalance), and also because afaik only up to one rebalancing operation needs to be done per insert/delete, so we only need to provide the nodes up to the point where rebalancing is done. See https://github.com/cosmos/iavl/blob/f50272dc2b8f521ea1fe4db3d9b67913a42cded3/node.go#L508
  2. When doing step 4, we also need to populate the key field of the inner nodes with the highest key in its left branch that we know of (https://github.com/cosmos/iavl/blob/master/docs/node/node.md).

This tool is also pretty handy for visualization: https://www.cs.usfca.edu/~galles/visualization/AVLtree.html