Replies: 3 comments 7 replies
-
My initial feeling is that I would also prefer to make both SMT and MMR work with Merkle sets, either as a single Merkle set (SMT) or a collection of them (MMR). I agree that we should also evaluate the approach of introducing SMT and MMR as new data structures, but having more flexible core Merkle set functionality that is data-set agnostic and usable for any (or most) Merkle-tree-based data structure(s) would make the advice provider more powerful without adding too many different moving parts. Regarding the other current shortcomings of the advice provider -
Just to clarify - you're talking about a new instruction that just handles cloning, right? So the user would call
I would like to think about other ways, but this is straightforward and works, so maybe it makes sense to take this approach for now so we can get initial implementations of everything we currently need for the rollup. |
Beta Was this translation helpful? Give feedback.
-
A new idea is to address some of these issues by replacing With this, |
Beta Was this translation helpful? Give feedback.
-
@bobbinth could you explain the bit below further?
Would the lookup for the root be done in the current version of MASM or are you thinking about some change to the VM? I was trying to figure out if we could extend the |
Beta Was this translation helpful? Give feedback.
-
In this discussion I wanted to think through potential refactoring that we'll need to make to the advice provider to better support MMR and SMT data structures. But first, I'd like to describe high-level goals and general structure of the advice provider.
Purpose of Advice provider
The purpose of the advice provider evolved somewhat over time. At first, it was just for providing nondeterministic inputs to the VM, but more recently it became a full-blown interface for the VM to communicate with the host. With the latest round of updates, the advice provide now persists beyond the execution of the VM and thus can be used by the VM to return large amounts of data (though, this data needs to be committed to via the values returned on the stack).
The advice provider consists of 3 parts:
The purpose of the Merkle store is let the VM manipulate authenticated data structure without having to worry about how these data structures are implemented. That is, as long as a data structure meets the required interface, the VM can work with it regardless of what the data structure actually is.
The interface the VM imposes on these data structure is as follows:
The data structures we have implemented as of yet (considering SMT and MMR to be still in progress):
MerkleTree
for when we know that most leaves are zeros.PartialMerkleTree
.The VM exposes 3 instructions to work with these
mtree_get
,mtree_set
, andmtree_cwm
(see here). These instructions don't care which one of the 3 data structures they work with. For example, a program usingmtree_get
should work in exactly the same way regardless of whether the underlying data structure isMerkleTree
,SimpleSmt
, orMerklePathSet
as long as the advice provider has enough data to satisfy this specific instruction invocation.This is useful, for example, when we want to prepare a transaction for proving by someone else. In this scenario, we would first execute the transaction and instantiate the advice provider with full sparse Merkle trees describing account storage, vault etc. as we don't know which storage slots will be read/updated by the transaction. But as the transaction is executing, we can collect the minimum amount of data needed to execute/prove it. Thus, we can send this data to the prover and the prove can instantiate their advice provider with only the partial data they have.
Current shortcomings
The way the advice provider is currently set up is not sufficient to support compact SMT and MMR data structure and we'll probably need to modify it somewhat. But even before we get there, the advice provider has a couple of issues.
Current Issue 1
Clone and update operation works awkwardly and is challenging to use in some situations. Currently, this is done via
mtree_cwm
- but I now believe this instruction was a mistake. Instead, we should have had an instruction to clone an existing Merkle set and then use the already existingmtree_set
to update it.To support a separate clone operation, we need to add a new method to the
AdvcieProvider
interface. Something like:In the implementation (e.g., MemAdviceProvider) this shouldn't be too difficult to support either - i.e., instead of using
BTreeMap<[u8; 32], MerkleSet>
we could useBTreeMap<[u8; 32], Vec<MerkleSet>>
and then clone operation would add new item to the vector under the specified key.Current Issue 2
There is no way to create a new Merkle set in the advice provider. That is, we can pre-load the advice provider with some Merkle sets (each having a unique root), and we can modify them, but we cannot create a blank Merkle set and start adding leaves to it.
One way to address this is to always pre-load the advice provider with immutable empty Sparse Merkle trees of all possible depth (1 - 64). That will allow users to clone empty tries of desired depth (using the clone method described above) and then add leaves to them using
mtree_set
instruction.There could be other ways too.
Challenges with MMR
MMR is not a single tree but rather a collection of trees each with a different root. Thus, it doesn't quite fit the current advice provider model well (where every structure is identified by a single root). There are two main operations we want to support with an MMR: (1) verify that a node is in the MMR and (2) append a new node to the MMR.
I think there are broadly two ways of supporting MMRs in the advice provider:
The first approach would require adding new methods to the
AdviceProvider
trait which would access Mmr or PartialMmr structs directly. This would probably imply that we need dedicated assembly instructions to work with MMRs (rather than putting the functionality intostdlib
). Instruction to verify membership would probably be pretty simple, but I'm not sure how complex the instruction for appending a new node would be. Another open question for this approach is how identify a given MMR in the advice provider (since there no single unique root). We could probably use a collection of peaks to do that - but maybe there is a better approach.The second approach would require fewer changes to the
AdviceProvider
interface, but we'd probably need to change the underlying implementation to add another level of indirection. Specifically, given a root we would first need to figure out which data structure could "serve" information about that root, and then go to that data structure. The data structure itself could contain information about one or more roots (vs. current situation where each data structure contains only a single root). Handling membership proofs this way would again be easy - but I'm not sure yet if there is a good way handle insertions since for efficient insertions we need to treat the whole operation as atomic.I'm leaning somewhat towards the second approach - but we should think through both to see all the pros and cons.
Challenges with compact SMT
The main challenge with supporting compact SMT (i.e., similar to the one here) is that currently the
AdviceProvider
assumes that for all Merkle sets leaves are located at the same depth, and moreover, we can update only leaves (even thoughmtree_set
instruction is more general).Similar to MMRs, we have two broad approaches to add support for compact SMTs:
The first approach is similar to what is proposed in #724. We need to add some specialized methods for handling compact SMTs to the advice provider. We also probably will need to have 2 different implementations: one for full SMT and one for compact one. And we may have to introduce specialized assembly instructions to work with the SMT data structures directly.
The second approach would probably require adding ability to update internal nodes of Merkle sets via the
mtree_set
instruction. This could be a fairly complex thing to do.As with MMR, I'm leaning towards the second approach - but we should evaluate both.
Beta Was this translation helpful? Give feedback.
All reactions