-
Notifications
You must be signed in to change notification settings - Fork 115
Description
Background
Currently, it is difficult to create public notes as outputs during the execution of a network transaction. This is because, during the execution of a network transaction, the network transaction builder has no knowledge of the public notes that may be generated as a result of the transaction. For a public note to be created, its public details must exist in the AdviceMap.
Problem
The primary problem I want to address is how a note-script-based AMM would operate on Miden. Consider an AMM account that is a Network account. Users create network SWAP notes (for simplicity, assume these SWAP notes can only be consumed by the AMM network account). When the network transaction builder processes these SWAP notes, it executes them against the AMM network account.
In this example, the AMM account consumes the network SWAP note and asserts that the x * y = k formula (or whichever underlying formula is used) holds after fulfilling the SWAP note by creating an output P2ID note.
Currently, this process works only if the output P2ID note is private. The transaction fails when trying to create a public P2ID note because the network transaction builder does not add the public note details to the AdviceMap. This means that either the network note or the network account must populate the AdviceMap with the required data for creating the P2ID note.
Given the storage limitations of notes, it is likely that the network account will need to store the public note data on-chain in order to create public output notes.
Short-Term Solution
A short-term solution would be for network accounts wishing to achieve such functionality would need to write custom logic which would populate the AdviceMap in MASM with the output note it intends to create. Ideally, we should add a helper function for this to the miden namespace.
As Bobbin noted, this issue might alternatively be solved by creating an on-chain NoteScript registry. However, building a NoteScript registry may be overkill in the short term. Although, with such a registry, network note scripts that want to create public output notes could use FPI to read the necessary data, such as the NoteScript, which would be stored in the registry as a vector of felts. This approach might introduce another complication, as it is unclear whether the network transaction builder can utilize FPI.
Concrete Short-Term Tasks
Tasks that would help enable public note creation during the execution of a network note transaction:
- Create a generalized procedure in the
midennamespace that inserts public note details into theAdviceMap.
Later on:
- Once implemented, modify the current
SWAPscript to allow it to be filled as a network note. - Generalize the standard
SWAPnote to be able to be filled as a Public, Private, or Network note.
Context from Slack thread:
Alex:
Just thinking about how a network note could output another note during its execution.
As far as I can tell to do so, the note needs to do the following:
| Key | Value |
|---|---|
output_note.recipient() |
output_note.digest().format_for_advice() |
output_note.inputs().commitment() |
output_note.inputs().format_for_advice() |
output_note.script().root() |
output_note.script() |
This way, when the transaction note calls exec.tx::create_note all the public note details are already in the AdviceMap
The question is though, where could the vectors of Felts be stored in the note, for the recipient, inputs, and script? Note inputs is only 128 Felt s. The Vec<Felt> for a P2ID note script is 362 felts.
I don't think it would be possible to write the note script as felts directly in the note as this would change the note script itself (chicken or the egg problem).
This is where public output notes are inserted into the AdviceMap: https://github.com/0xMiden/miden-base/blob/ba5bed3e31d205040a6a23735aadca8f608ddaec/crates/miden-objects/src/transaction/tx_args.rs#L175
Bobbin's reponse:
We could provide a helper procedure in the miden namespace - something like load_recipient. This procedure could take the following inputs:
SERIAL_NUMinputs_ptrandnum_inputs.SCRIPT_ROOT
This procedure then would need to insert all relevant entries into the advice map based on these.
The trickiest part here would be to figure out how to map the SCRIPT_ROOT to the actual script. A few thoughts on this:
- For well-known notes (e.g., P2ID) that should be straight-forward.
If the script root is for the note that is currently being executed, that should be pretty simple as well. - The main complexity would be to load the script for other non-standard notes. Here, we could have several options:
- Encode the script into the auxiliary note data - something similar to what I described in `NoteTag` requirements and simplification #1449 (reply in thread)
- Create a concept of on-chain note script registry.
The registry approach is probably the most robust. User would be able to execute transactions to add scripts to the onchain registry. And then these scripts would be similar to the well-known note scripts. I don't have a good idea yet of how this note script registry would work. A few questions to think through:
Can we store this in an account somehow or do we need to create a new "logical entity" in the chain for it.
How would users add entries into this registry?
What kind of validation would need to be done before an entry can be added to the registry? (e.g., we may want to make sure that the key is in-fact the MAST root of the underlying script - but doing this may not be trivial).
Somewhat related to #1049
cc-ing @Mirko-von-Leipzig re network transactions