The path returned by `EmptySubtreeRoots` starts at the root, and goes to
the leaf. The MerkleStore constructor assumed the other direction, so
the parent/child hashes were reversed.
This fixes the bug and adds a test.
Prior to this commit, we limited the constants count to 64 for the empty
subtrees depth computation. This is a hard-assumption that every tree of
Miden will have a depth up to 64 - and will cause undefined behavior if
it doesn't.
With the introduction of `MerkleStore::merge_roots` and the deprecation
of `mtree_cwm` instruction from the VM, this assumption is broken and
the user might end with trees with depth greater than 64. This broken
assumption could lead to attack vectors.
We can easily fix that by extending the pre-computed hashes list to the
maximum of `u8` (i.e. 255). This will have zero impact on functionality,
and will be completely safe to use without hard assumptions.
Returning tuples is often confusing as they don't convey meaning and it
should be used only when there is no possible ambiguity.
For `MerkleStore`, we had a couple of tuples being returned, and reading
the implementation was required in order to distinguish if they were
leaf values or computed roots.
This commit introduces two containers that will self-document these
returns: `RootPath` and `ValuePath`. It will also update `set_node` to
return both the new root & the new path, so we can prevent duplicated
traversals downstream when updating a node (one to update, the second to
fetch the new path/root).
The store builds the path from root to leaf, this updates the code to
return a path from leaf to root, as it is done by the other structures.
This also added custom error for missing root.
Prior to this commit, the MerkleStore panicked under certain bounds. It
will prevent such panics by using checked operations.
ilog2, for instance, will panic when the operand is zero. However, there
is a documentation rule enforcing the merkle tree to be size at least 2.
If this rule is checked, then the panic is impossible.
This commit introduce common derive proc macros to MerkleStore. These
are required downstream as the in-memory storage can be cloned.
It also introduces constructors common to the other types of the crate
that will help to build a merkle store, using a build pattern.
Prior to this commit, there was an internal procedure with the merkle
trees to compute empty sub-tree for arbitrary depths.
However, this isn't ideal as this code can be reused in any merkle
implementation that uses RPO as backend.
This commit introduces a structure that will generate these empty
subtrees values.