refactor: convert note scripts from program to library format#2340
refactor: convert note scripts from program to library format#2340bobbinth merged 4 commits into0xMiden:nextfrom
Conversation
|
Hey @bobbinth, |
@Farukest could you prepare a short reproducible example (ideally incl. a branch) and file a bug accordingly please? |
Hey @mmagician opened : bug report: 0xMiden/miden-vm#2608 |
This change implements issue 0xMiden#2339 - converting note scripts from program format to library format with @note_script annotation support. Changes: - Add @note_script annotation to all standard note scripts (p2id, p2ide, swap, mint, burn) in asm/standards/notes/ - Add NoteScript::from_library constructor that finds the procedure with @note_script attribute (or falls back to 'main' procedure) and uses it as the entrypoint - Update build.rs to compile note scripts as libraries (.masl) instead of programs (.masb) using assemble_library_from_dir with unique namespace - Update well_known_note.rs to load NoteScript from Library - Remove wrapper script files (asm/note_scripts/*.masm) that are no longer needed - Add NoteError variants for missing/multiple @note_script procedures Note: The @note_script attribute propagation from MASM to Library is not yet fully supported in miden-assembly 0.20. The implementation falls back to finding a procedure named 'main' when the attribute is not found.
ba05848 to
05bd528
Compare
|
Hi @Farukest, the bug in the VM was closed and we should be able to Whenever the PR is ready for a review, please request one (or ping if that doesn't work). Thanks! |
Address review feedback: instead of the temp directory workaround in build.rs, use simple wrapper files in note_scripts/ that re-export the main procedure from miden::standards::notes with pub use. Changes: - Add wrapper files (BURN.masm, P2ID.masm, P2IDE.masm, MINT.masm, SWAP.masm) with pub use re-exports - Simplify compile_note_scripts in build.rs to use assemble_library directly without temp directory hack - Remove unused ASM_STANDARDS_NOTES_DIR constant and AsmPath import
PhilippGackstatter
left a comment
There was a problem hiding this comment.
Looks good, thank you! It's great that we can now use procref for getting the root of note scripts 🎉.
| const LOCAL_EXIT_TREE_SLOT=word("miden::agglayer::let") | ||
|
|
||
| const BURN_NOTE_ROOT = [15615638671708113717, 1774623749760042586, 2028263167268363492, 12931944505143778072] | ||
| const BURN_NOTE_ROOT = [2756591441383390862, 11367570355116383975, 7462969093049029253, 13293708936511347663] |
There was a problem hiding this comment.
It looks like we can now remove this constant and instead do:
procref.::miden::standards::notes::burn::main
swapw
# => [SERIAL_NUM, SCRIPT_ROOT]
The same should work for the P2ID root in crates/miden-agglayer/asm/bridge/agglayer_faucet.masm.
| let mut entrypoint_by_attr = None; | ||
| let mut entrypoint_by_name = None; | ||
|
|
||
| for export in library.exports() { | ||
| if let Some(proc_export) = export.as_procedure() { | ||
| // Check for @note_script attribute | ||
| if proc_export.attributes.has(NOTE_SCRIPT_ATTRIBUTE) { | ||
| if entrypoint_by_attr.is_some() { | ||
| return Err(NoteError::NoteScriptMultipleProceduresWithAttribute); | ||
| } | ||
| entrypoint_by_attr = Some(proc_export.node); | ||
| } | ||
|
|
||
| // Check for procedure named "main" as fallback | ||
| if proc_export.path.last() == Some(NOTE_SCRIPT_MAIN_PROC) { | ||
| entrypoint_by_name = Some(proc_export.node); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Prefer @note_script attribute, fallback to "main" procedure | ||
| let entrypoint = entrypoint_by_attr | ||
| .or(entrypoint_by_name) | ||
| .ok_or(NoteError::NoteScriptNoProcedureWithAttribute)?; |
There was a problem hiding this comment.
I think we can search only for the @note_script attribute and if not found, error out. In other words, I wouldn't implement fall-back behavior to main.
I also think we don't really need to enforce that the procedure is called main although it is nice for uniformity and is also fine to keep as it's easy to remove later.
crates/miden-standards/build.rs
Outdated
| let source_code = fs::read_to_string(&masm_file_path) | ||
| .expect("reading the note script's MASM source code should succeed"); |
There was a problem hiding this comment.
Can we turn this into an error instead of panicking?
crates/miden-standards/build.rs
Outdated
| .to_str() | ||
| .ok_or_else(|| Report::msg("failed to convert file name to &str"))?; | ||
| let mut masb_file_path = target_dir.join(masm_file_name); | ||
| let named_source = NamedSource::new(script_name.clone(), source_code); |
There was a problem hiding this comment.
Currently, for the BURN note, we'd get BURN as the library path. Can we lowercase this and prefix it with miden::standards::note_scripts, so we'd get miden::standards::note_scripts::burn as the library path?
Since the note scripts are part of miden::standards::notes already, I don't think these individual note libraries would really be used, but it doesn't hurt to make it consistent, since it is a part of our public API.
There was a problem hiding this comment.
I think we can actually get rid of these individual note libraries entirely - but I'd leave this for a follow-up PR.
mmagician
left a comment
There was a problem hiding this comment.
LGTM bar the comments that @PhilippGackstatter left
| let mut entrypoint_by_attr = None; | ||
| let mut entrypoint_by_name = None; | ||
|
|
||
| for export in library.exports() { | ||
| if let Some(proc_export) = export.as_procedure() { | ||
| // Check for @note_script attribute | ||
| if proc_export.attributes.has(NOTE_SCRIPT_ATTRIBUTE) { | ||
| if entrypoint_by_attr.is_some() { | ||
| return Err(NoteError::NoteScriptMultipleProceduresWithAttribute); | ||
| } | ||
| entrypoint_by_attr = Some(proc_export.node); | ||
| } | ||
|
|
||
| // Check for procedure named "main" as fallback | ||
| if proc_export.path.last() == Some(NOTE_SCRIPT_MAIN_PROC) { | ||
| entrypoint_by_name = Some(proc_export.node); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Prefer @note_script attribute, fallback to "main" procedure | ||
| let entrypoint = entrypoint_by_attr | ||
| .or(entrypoint_by_name) | ||
| .ok_or(NoteError::NoteScriptNoProcedureWithAttribute)?; |
bobbinth
left a comment
There was a problem hiding this comment.
Looks good! Thank you! Once comments from @PhilippGackstatter are addressed, we should be good to merge.
crates/miden-standards/build.rs
Outdated
| .to_str() | ||
| .ok_or_else(|| Report::msg("failed to convert file name to &str"))?; | ||
| let mut masb_file_path = target_dir.join(masm_file_name); | ||
| let named_source = NamedSource::new(script_name.clone(), source_code); |
There was a problem hiding this comment.
I think we can actually get rid of these individual note libraries entirely - but I'd leave this for a follow-up PR.
f82adca to
7f43858
Compare
Changes based on PR review: - Replace hardcoded note script roots with procref in bridge_out.masm and agglayer_faucet.masm (BURN_NOTE_ROOT and P2ID_SCRIPT_ROOT) - Remove main procedure fallback in NoteScript::from_library, require @note_script attribute - Use pub use re-exports in note script wrappers to preserve @note_script attribute from the original procedures - Improve error handling in build.rs (replace expect with proper errors) - Use lowercase library paths (miden::standards::note_scripts::burn) - Update miden-* dependencies to v0.20.3 for attribute serialization fix
7f43858 to
f6d0881
Compare
This removes the individual note script wrapper files (BURN, P2ID, P2IDE, MINT, SWAP) and their separate compilation, as suggested in PR 0xMiden#2340. Instead of compiling and loading each note script as a separate .masl file, the note scripts are now loaded directly from the main standards library using the new NoteScript::from_library_with_path method. Changes: - Add NoteScript::from_library_with_path method to extract a specific note script procedure from a library containing multiple note scripts - Remove asm/note_scripts/ wrapper files - Remove compile_note_scripts function from build.rs - Update note Rust files (burn.rs, p2id.rs, p2ide.rs, mint.rs, swap.rs) to use StandardsLib with procedure path lookup - Add NoteScriptProcedureNotFound and NoteScriptProcedureMissingAttribute error variants
bobbinth
left a comment
There was a problem hiding this comment.
Looks good! Thank you! I left one comment inline, but I don't think we need to address it, and so, I'll merge the PR as is.
| fs::create_dir_all(&temp_dir).into_diagnostic()?; | ||
|
|
||
| // Copy the file to the temp directory with lowercase name | ||
| let temp_file = temp_dir.join(format!("{}.masm", script_name_lower)); | ||
| fs::copy(&masm_file_path, &temp_file).into_diagnostic()?; | ||
|
|
||
| // write the binary MASB to the output dir | ||
| masb_file_path.set_extension("masb"); | ||
| fs::write(masb_file_path, bytes).unwrap(); | ||
| // Compile using assemble_library_from_dir with miden::standards::note_scripts namespace | ||
| let namespace = AsmPath::validate("miden::standards::note_scripts") | ||
| .expect("namespace path should be valid"); | ||
| let script_library = assembler | ||
| .clone() | ||
| .assemble_library_from_dir(&temp_dir, namespace) | ||
| .wrap_err("failed to assemble note script library")?; |
There was a problem hiding this comment.
I thinks we could have probably done this w/o creating a temporary directory, but given that this code will (hopefully) go away soon, it is fine to leave it as is.
This removes the individual note script wrapper files (BURN, P2ID, P2IDE, MINT, SWAP) and their separate compilation, as suggested in PR 0xMiden#2340. Instead of compiling and loading each note script as a separate .masl file, the note scripts are now loaded directly from the main standards library using the new NoteScript::from_library_with_path method. Changes: - Add NoteScript::from_library_with_path method to extract a specific note script procedure from a library containing multiple note scripts - Remove asm/note_scripts/ wrapper files - Remove compile_note_scripts function from build.rs - Update note Rust files (burn.rs, p2id.rs, p2ide.rs, mint.rs, swap.rs) to use StandardsLib with procedure path lookup - Add NoteScriptProcedureNotFound and NoteScriptProcedureMissingAttribute error variants
* refactor: convert note scripts from program to library format This change implements issue #2339 - converting note scripts from program format to library format with @note_script annotation support. Changes: - Add @note_script annotation to all standard note scripts (p2id, p2ide, swap, mint, burn) in asm/standards/notes/ - Add NoteScript::from_library constructor that finds the procedure with @note_script attribute (or falls back to 'main' procedure) and uses it as the entrypoint - Update build.rs to compile note scripts as libraries (.masl) instead of programs (.masb) using assemble_library_from_dir with unique namespace - Update well_known_note.rs to load NoteScript from Library - Remove wrapper script files (asm/note_scripts/*.masm) that are no longer needed - Add NoteError variants for missing/multiple @note_script procedures Note: The @note_script attribute propagation from MASM to Library is not yet fully supported in miden-assembly 0.20. The implementation falls back to finding a procedure named 'main' when the attribute is not found. * refactor: use pub use re-exports in note script wrappers Address review feedback: instead of the temp directory workaround in build.rs, use simple wrapper files in note_scripts/ that re-export the main procedure from miden::standards::notes with pub use. Changes: - Add wrapper files (BURN.masm, P2ID.masm, P2IDE.masm, MINT.masm, SWAP.masm) with pub use re-exports - Simplify compile_note_scripts in build.rs to use assemble_library directly without temp directory hack - Remove unused ASM_STANDARDS_NOTES_DIR constant and AsmPath import * refactor: address review feedback for note script library conversion Changes based on PR review: - Replace hardcoded note script roots with procref in bridge_out.masm and agglayer_faucet.masm (BURN_NOTE_ROOT and P2ID_SCRIPT_ROOT) - Remove main procedure fallback in NoteScript::from_library, require @note_script attribute - Update note script wrappers to use @note_script attribute with exec instead of pub use re-exports (MASM doesn't support attributes on pub use) - Improve error handling in build.rs (replace expect with proper errors) - Use lowercase library paths (miden::standards::note_scripts::burn) - Update miden-* dependencies to v0.20.3 for attribute serialization fix * refactor: remove individual note script libraries This removes the individual note script wrapper files (BURN, P2ID, P2IDE, MINT, SWAP) and their separate compilation, as suggested in PR #2340. Instead of compiling and loading each note script as a separate .masl file, the note scripts are now loaded directly from the main standards library using the new NoteScript::from_library_with_path method. Changes: - Add NoteScript::from_library_with_path method to extract a specific note script procedure from a library containing multiple note scripts - Remove asm/note_scripts/ wrapper files - Remove compile_note_scripts function from build.rs - Update note Rust files (burn.rs, p2id.rs, p2ide.rs, mint.rs, swap.rs) to use StandardsLib with procedure path lookup - Add NoteScriptProcedureNotFound and NoteScriptProcedureMissingAttribute error variants * refactor: use minimal MastForest with external node in from_library_with_path Instead of copying the entire library's MastForest, create a minimal forest containing only a single ExternalNode referencing the procedure's digest. This significantly reduces memory usage as the actual procedure code will be resolved at runtime via MastForestStore. * refactor: rename from_library_with_path to from_library_reference - Renamed NoteScript::from_library_with_path to from_library_reference to better indicate that the resulting note script contains only a reference to the procedure - Updated docstring for create_external_node_forest helper function - Updated all usages in miden-standards note modules * fix: remove duplicate changelog entry --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
* refactor: convert note scripts from program to library format This change implements issue 0xMiden#2339 - converting note scripts from program format to library format with @note_script annotation support. Changes: - Add @note_script annotation to all standard note scripts (p2id, p2ide, swap, mint, burn) in asm/standards/notes/ - Add NoteScript::from_library constructor that finds the procedure with @note_script attribute (or falls back to 'main' procedure) and uses it as the entrypoint - Update build.rs to compile note scripts as libraries (.masl) instead of programs (.masb) using assemble_library_from_dir with unique namespace - Update well_known_note.rs to load NoteScript from Library - Remove wrapper script files (asm/note_scripts/*.masm) that are no longer needed - Add NoteError variants for missing/multiple @note_script procedures Note: The @note_script attribute propagation from MASM to Library is not yet fully supported in miden-assembly 0.20. The implementation falls back to finding a procedure named 'main' when the attribute is not found. * refactor: use pub use re-exports in note script wrappers Address review feedback: instead of the temp directory workaround in build.rs, use simple wrapper files in note_scripts/ that re-export the main procedure from miden::standards::notes with pub use. Changes: - Add wrapper files (BURN.masm, P2ID.masm, P2IDE.masm, MINT.masm, SWAP.masm) with pub use re-exports - Simplify compile_note_scripts in build.rs to use assemble_library directly without temp directory hack - Remove unused ASM_STANDARDS_NOTES_DIR constant and AsmPath import * refactor: address review feedback for note script library conversion Changes based on PR review: - Replace hardcoded note script roots with procref in bridge_out.masm and agglayer_faucet.masm (BURN_NOTE_ROOT and P2ID_SCRIPT_ROOT) - Remove main procedure fallback in NoteScript::from_library, require @note_script attribute - Update note script wrappers to use @note_script attribute with exec instead of pub use re-exports (MASM doesn't support attributes on pub use) - Improve error handling in build.rs (replace expect with proper errors) - Use lowercase library paths (miden::standards::note_scripts::burn) - Update miden-* dependencies to v0.20.3 for attribute serialization fix * refactor: remove individual note script libraries This removes the individual note script wrapper files (BURN, P2ID, P2IDE, MINT, SWAP) and their separate compilation, as suggested in PR 0xMiden#2340. Instead of compiling and loading each note script as a separate .masl file, the note scripts are now loaded directly from the main standards library using the new NoteScript::from_library_with_path method. Changes: - Add NoteScript::from_library_with_path method to extract a specific note script procedure from a library containing multiple note scripts - Remove asm/note_scripts/ wrapper files - Remove compile_note_scripts function from build.rs - Update note Rust files (burn.rs, p2id.rs, p2ide.rs, mint.rs, swap.rs) to use StandardsLib with procedure path lookup - Add NoteScriptProcedureNotFound and NoteScriptProcedureMissingAttribute error variants * refactor: use minimal MastForest with external node in from_library_with_path Instead of copying the entire library's MastForest, create a minimal forest containing only a single ExternalNode referencing the procedure's digest. This significantly reduces memory usage as the actual procedure code will be resolved at runtime via MastForestStore. * refactor: rename from_library_with_path to from_library_reference - Renamed NoteScript::from_library_with_path to from_library_reference to better indicate that the resulting note script contains only a reference to the procedure - Updated docstring for create_external_node_forest helper function - Updated all usages in miden-standards note modules * fix: remove duplicate changelog entry --------- Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
Summary
Converts note scripts from program format (
begin...end) to library format with@note_scriptannotation support.Changes
@note_scriptannotation to all standard note scripts (p2id, p2ide, swap, mint, burn)NoteScript::from_library()constructor that finds the procedure with@note_scriptattributebuild.rsto compile note scripts as libraries (.masl) instead of programs (.masb)well_known_note.rsto loadNoteScriptfromLibraryasm/note_scripts/*.masm)NoteErrorvariants for missing/multiple@note_scriptproceduresNote
The
@note_scriptattribute propagation from MASM to Library is not yet fully supported in_miden-assembly 0.20_.The implementation falls back to finding a procedure named
mainwhen the attribute is not found.Closes #2339