From 21139b68ee130822e2014294a49adbf88e0624cf Mon Sep 17 00:00:00 2001 From: sergerad Date: Wed, 14 Aug 2024 13:13:54 +1200 Subject: [PATCH 01/18] add unsafe constructors to individual nodes --- core/src/mast/node/basic_block_node/mod.rs | 12 ++++++++++++ core/src/mast/node/call_node.rs | 12 ++++++++++++ core/src/mast/node/join_node.rs | 6 ++++-- core/src/mast/node/loop_node.rs | 7 +++++++ core/src/mast/node/split_node.rs | 5 +++-- core/src/mast/serialization/info.rs | 15 +++++++-------- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/core/src/mast/node/basic_block_node/mod.rs b/core/src/mast/node/basic_block_node/mod.rs index 8c833da42..a8852b579 100644 --- a/core/src/mast/node/basic_block_node/mod.rs +++ b/core/src/mast/node/basic_block_node/mod.rs @@ -88,6 +88,18 @@ impl BasicBlockNode { Self::with_decorators(operations, DecoratorList::new()) } + /// Returns a new [`BasicBlockNode`] from values that are assumed to be correct. + /// Should only be used when the source of the inputs is trusted (e.g. deserialization). + pub fn new_unsafe( + operations: Vec, + decorators: DecoratorList, + digest: RpoDigest, + ) -> Self { + // TODO(serge): Receive operation batches instead of generating them + let (op_batches, _) = batch_ops(operations); + Self { op_batches, digest, decorators } + } + /// Returns a new [`BasicBlockNode`] instantiated with the specified operations and decorators. /// /// # Errors (TODO) diff --git a/core/src/mast/node/call_node.rs b/core/src/mast/node/call_node.rs index cee4d8c39..f5038dd57 100644 --- a/core/src/mast/node/call_node.rs +++ b/core/src/mast/node/call_node.rs @@ -51,6 +51,12 @@ impl CallNode { Ok(Self { callee, is_syscall: false, digest }) } + /// Returns a new [`CallNode`] from values that are assumed to be correct. + /// Should only be used when the source of the inputs is trusted (e.g. deserialization). + pub fn new_unsafe(callee: MastNodeId, digest: RpoDigest) -> Self { + Self { callee, is_syscall: false, digest } + } + /// Returns a new [`CallNode`] instantiated with the specified callee and marked as a kernel /// call. pub fn new_syscall( @@ -68,6 +74,12 @@ impl CallNode { Ok(Self { callee, is_syscall: true, digest }) } + + /// Returns a new syscall [`CallNode`] from values that are assumed to be correct. + /// Should only be used when the source of the inputs is trusted (e.g. deserialization). + pub fn new_syscall_unsafe(callee: MastNodeId, digest: RpoDigest) -> Self { + Self { callee, is_syscall: true, digest } + } } //------------------------------------------------------------------------------------------------- diff --git a/core/src/mast/node/join_node.rs b/core/src/mast/node/join_node.rs index f4f92ff6a..5411c431f 100644 --- a/core/src/mast/node/join_node.rs +++ b/core/src/mast/node/join_node.rs @@ -49,8 +49,10 @@ impl JoinNode { Ok(Self { children, digest }) } - #[cfg(test)] - pub fn new_test(children: [MastNodeId; 2], digest: RpoDigest) -> Self { + /// Returns a new [`JoinNode`] from values that are assumed to be correct. + /// Should only be used when the source of the inputs is trusted (e.g. deserialization). + pub fn new_unsafe(children: [MastNodeId; 2], digest: RpoDigest) -> Self { + // TODO(serge): debug_assert worthwhile? Need to pass in forest length to check children len Self { children, digest } } } diff --git a/core/src/mast/node/loop_node.rs b/core/src/mast/node/loop_node.rs index dfda217c2..08e30ca69 100644 --- a/core/src/mast/node/loop_node.rs +++ b/core/src/mast/node/loop_node.rs @@ -32,6 +32,7 @@ impl LoopNode { /// Constructors impl LoopNode { + /// Returns a new [`LoopNode`] instantiated with the specified body node. pub fn new(body: MastNodeId, mast_forest: &MastForest) -> Result { if body.as_usize() >= mast_forest.nodes.len() { return Err(MastForestError::NodeIdOverflow(body, mast_forest.nodes.len())); @@ -44,6 +45,12 @@ impl LoopNode { Ok(Self { body, digest }) } + + /// Returns a new [`LoopNode`] from values that are assumed to be correct. + /// Should only be used when the source of the inputs is trusted (e.g. deserialization). + pub fn new_unsafe(body: MastNodeId, digest: RpoDigest) -> Self { + Self { body, digest } + } } impl LoopNode { diff --git a/core/src/mast/node/split_node.rs b/core/src/mast/node/split_node.rs index f6dcaacf8..635049157 100644 --- a/core/src/mast/node/split_node.rs +++ b/core/src/mast/node/split_node.rs @@ -52,8 +52,9 @@ impl SplitNode { Ok(Self { branches, digest }) } - #[cfg(test)] - pub fn new_test(branches: [MastNodeId; 2], digest: RpoDigest) -> Self { + /// Returns a new [`SplitNode`] from values that are assumed to be correct. + /// Should only be used when the source of the inputs is trusted (e.g. deserialization). + pub fn new_unsafe(branches: [MastNodeId; 2], digest: RpoDigest) -> Self { Self { branches, digest } } } diff --git a/core/src/mast/serialization/info.rs b/core/src/mast/serialization/info.rs index 3b72a29ea..cc4670706 100644 --- a/core/src/mast/serialization/info.rs +++ b/core/src/mast/serialization/info.rs @@ -2,7 +2,7 @@ use miden_crypto::hash::rpo::RpoDigest; use winter_utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; use super::{basic_block_data_decoder::BasicBlockDataDecoder, DataOffset}; -use crate::mast::{MastForest, MastNode, MastNodeId}; +use crate::mast::{CallNode, JoinNode, LoopNode, MastForest, MastNode, MastNodeId, SplitNode}; // MAST NODE INFO // ================================================================================================ @@ -35,6 +35,7 @@ impl MastNodeInfo { offset, len: num_operations_and_decorators, } => { + // TODO(serge): Decode operation batches directly let (operations, decorators) = basic_block_data_decoder .decode_operations_and_decorators(offset, num_operations_and_decorators)?; @@ -44,30 +45,28 @@ impl MastNodeInfo { let left_child = MastNodeId::from_u32_safe(left_child_id, mast_forest)?; let right_child = MastNodeId::from_u32_safe(right_child_id, mast_forest)?; - Ok(MastNode::new_join(left_child, right_child, mast_forest) - .expect("invalid node id")) + Ok(MastNode::Join(JoinNode::new_unsafe([left_child, right_child], self.digest))) }, MastNodeType::Split { if_branch_id, else_branch_id } => { let if_branch = MastNodeId::from_u32_safe(if_branch_id, mast_forest)?; let else_branch = MastNodeId::from_u32_safe(else_branch_id, mast_forest)?; - Ok(MastNode::new_split(if_branch, else_branch, mast_forest) - .expect("invalid node id")) + Ok(MastNode::Split(SplitNode::new_unsafe([if_branch, else_branch], self.digest))) }, MastNodeType::Loop { body_id } => { let body_id = MastNodeId::from_u32_safe(body_id, mast_forest)?; - Ok(MastNode::new_loop(body_id, mast_forest).expect("invalid node id")) + Ok(MastNode::Loop(LoopNode::new_unsafe(body_id, self.digest))) }, MastNodeType::Call { callee_id } => { let callee_id = MastNodeId::from_u32_safe(callee_id, mast_forest)?; - Ok(MastNode::new_call(callee_id, mast_forest).expect("invalid node id")) + Ok(MastNode::Call(CallNode::new_unsafe(callee_id, self.digest))) }, MastNodeType::SysCall { callee_id } => { let callee_id = MastNodeId::from_u32_safe(callee_id, mast_forest)?; - Ok(MastNode::new_syscall(callee_id, mast_forest).expect("invalid node id")) + Ok(MastNode::Call(CallNode::new_syscall_unsafe(callee_id, self.digest))) }, MastNodeType::Dyn => Ok(MastNode::new_dyn()), MastNodeType::External => Ok(MastNode::new_external(self.digest)), From 7be6deb3bc3511c0f1fa1c5843d31ddcdece586f Mon Sep 17 00:00:00 2001 From: sergerad Date: Wed, 14 Aug 2024 20:06:20 +1200 Subject: [PATCH 02/18] break out batch_ops --- core/src/mast/node/basic_block_node/mod.rs | 37 +++++++++++--------- core/src/mast/node/basic_block_node/tests.rs | 18 +++++----- core/src/mast/serialization/info.rs | 7 ++-- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/core/src/mast/node/basic_block_node/mod.rs b/core/src/mast/node/basic_block_node/mod.rs index a8852b579..7e487458d 100644 --- a/core/src/mast/node/basic_block_node/mod.rs +++ b/core/src/mast/node/basic_block_node/mod.rs @@ -95,7 +95,6 @@ impl BasicBlockNode { decorators: DecoratorList, digest: RpoDigest, ) -> Self { - // TODO(serge): Receive operation batches instead of generating them let (op_batches, _) = batch_ops(operations); Self { op_batches, digest, decorators } } @@ -113,7 +112,7 @@ impl BasicBlockNode { #[cfg(debug_assertions)] validate_decorators(&operations, &decorators); - let (op_batches, digest) = batch_ops(operations); + let (op_batches, digest) = batch_and_hash_ops(operations); Self { op_batches, digest, decorators } } } @@ -304,18 +303,29 @@ impl<'a> Iterator for OperationOrDecoratorIterator<'a> { // HELPER FUNCTIONS // ================================================================================================ +/// Groups the provided operations into batches and computes the hash of the block. +fn batch_and_hash_ops(ops: Vec) -> (Vec, RpoDigest) { + // Group the operations into batches. + let (batches, batch_groups) = batch_ops(ops); + + // Compute the hash of all operation groups. + let op_groups = &flatten_slice_elements(&batch_groups); + let hash = hasher::hash_elements(op_groups); + + (batches, hash) +} + /// Groups the provided operations into batches as described in the docs for this module (i.e., /// up to 9 operations per group, and 8 groups per batch). -/// -/// After the operations have been grouped, computes the hash of the block. -fn batch_ops(ops: Vec) -> (Vec, RpoDigest) { - let mut batch_acc = OpBatchAccumulator::new(); +/// Returns a list of operation batches and a list of operation groups. +fn batch_ops(ops: Vec) -> (Vec, Vec<[Felt; BATCH_SIZE]>) { let mut batches = Vec::::new(); + let mut batch_acc = OpBatchAccumulator::new(); let mut batch_groups = Vec::<[Felt; BATCH_SIZE]>::new(); for op in ops { - // if the operation cannot be accepted into the current accumulator, add the contents of - // the accumulator to the list of batches and start a new accumulator + // If the operation cannot be accepted into the current accumulator, add the contents of + // the accumulator to the list of batches and start a new accumulator. if !batch_acc.can_accept_op(op) { let batch = batch_acc.into_batch(); batch_acc = OpBatchAccumulator::new(); @@ -324,22 +334,17 @@ fn batch_ops(ops: Vec) -> (Vec, RpoDigest) { batches.push(batch); } - // add the operation to the accumulator + // Add the operation to the accumulator. batch_acc.add_op(op); } - // make sure we finished processing the last batch + // Make sure we finished processing the last batch. if !batch_acc.is_empty() { let batch = batch_acc.into_batch(); batch_groups.push(*batch.groups()); batches.push(batch); } - - // compute the hash of all operation groups - let op_groups = &flatten_slice_elements(&batch_groups); - let hash = hasher::hash_elements(op_groups); - - (batches, hash) + (batches, batch_groups) } /// Checks if a given decorators list is valid (only checked in debug mode) diff --git a/core/src/mast/node/basic_block_node/tests.rs b/core/src/mast/node/basic_block_node/tests.rs index 49a663ae3..1826be788 100644 --- a/core/src/mast/node/basic_block_node/tests.rs +++ b/core/src/mast/node/basic_block_node/tests.rs @@ -5,7 +5,7 @@ use crate::{Decorator, ONE}; fn batch_ops() { // --- one operation ---------------------------------------------------------------------- let ops = vec![Operation::Add]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -21,7 +21,7 @@ fn batch_ops() { // --- two operations --------------------------------------------------------------------- let ops = vec![Operation::Add, Operation::Mul]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -37,7 +37,7 @@ fn batch_ops() { // --- one group with one immediate value ------------------------------------------------- let ops = vec![Operation::Add, Operation::Push(Felt::new(12345678))]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -63,7 +63,7 @@ fn batch_ops() { Operation::Push(Felt::new(7)), Operation::Add, ]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -98,7 +98,7 @@ fn batch_ops() { Operation::Add, Operation::Push(Felt::new(7)), ]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(2, batches.len()); let batch0 = &batches[0]; @@ -147,7 +147,7 @@ fn batch_ops() { Operation::Add, ]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -181,7 +181,7 @@ fn batch_ops() { Operation::Add, Operation::Push(Felt::new(11)), ]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -215,7 +215,7 @@ fn batch_ops() { Operation::Push(ONE), Operation::Push(Felt::new(2)), ]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(1, batches.len()); let batch = &batches[0]; @@ -260,7 +260,7 @@ fn batch_ops() { Operation::Pad, ]; - let (batches, hash) = super::batch_ops(ops.clone()); + let (batches, hash) = super::batch_and_hash_ops(ops.clone()); assert_eq!(2, batches.len()); let batch0 = &batches[0]; diff --git a/core/src/mast/serialization/info.rs b/core/src/mast/serialization/info.rs index cc4670706..652d35d84 100644 --- a/core/src/mast/serialization/info.rs +++ b/core/src/mast/serialization/info.rs @@ -2,7 +2,9 @@ use miden_crypto::hash::rpo::RpoDigest; use winter_utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; use super::{basic_block_data_decoder::BasicBlockDataDecoder, DataOffset}; -use crate::mast::{CallNode, JoinNode, LoopNode, MastForest, MastNode, MastNodeId, SplitNode}; +use crate::mast::{ + BasicBlockNode, CallNode, JoinNode, LoopNode, MastForest, MastNode, MastNodeId, SplitNode, +}; // MAST NODE INFO // ================================================================================================ @@ -35,11 +37,10 @@ impl MastNodeInfo { offset, len: num_operations_and_decorators, } => { - // TODO(serge): Decode operation batches directly let (operations, decorators) = basic_block_data_decoder .decode_operations_and_decorators(offset, num_operations_and_decorators)?; - Ok(MastNode::new_basic_block_with_decorators(operations, decorators)) + Ok(MastNode::Block(BasicBlockNode::new_unsafe(operations, decorators, self.digest))) }, MastNodeType::Join { left_child_id, right_child_id } => { let left_child = MastNodeId::from_u32_safe(left_child_id, mast_forest)?; From bcde40bf503c2499466e476fe47a0cf7c04f1d16 Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 15 Aug 2024 10:05:26 +1200 Subject: [PATCH 03/18] start benches --- Cargo.lock | 1 + assembly/Cargo.toml | 35 ++++++++++--- assembly/benches/deserialize_std_lib.rs | 70 +++++++++++++++++++++++++ assembly/src/lib.rs | 10 ++-- 4 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 assembly/benches/deserialize_std_lib.rs diff --git a/Cargo.lock b/Cargo.lock index db15dfcc0..d3c42bd4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1016,6 +1016,7 @@ name = "miden-assembly" version = "0.11.0" dependencies = [ "aho-corasick", + "criterion", "lalrpop", "lalrpop-util", "miden-core", diff --git a/assembly/Cargo.toml b/assembly/Cargo.toml index ce816d9bf..163997f89 100644 --- a/assembly/Cargo.toml +++ b/assembly/Cargo.toml @@ -17,9 +17,19 @@ edition.workspace = true bench = false doctest = false +[[bench]] +name = "deserialize_std_lib" +harness = false + [features] default = ["std"] -std = ["aho-corasick/std", "miette/fancy", "miette/std", "thiserror/std", "vm-core/std"] +std = [ + "aho-corasick/std", + "miette/fancy", + "miette/std", + "thiserror/std", + "vm-core/std", +] testing = ["dep:regex"] [dependencies] @@ -27,20 +37,33 @@ aho-corasick = { version = "1.1", default-features = false } lalrpop-util = { version = "0.20", default-features = false } miette = { package = "miden-miette", version = "7.1", default-features = false, features = [ "fancy-no-syscall", - "derive" + "derive", +] } +regex = { version = "1.10", optional = true, default-features = false, features = [ + "unicode", + "perf", +] } +smallvec = { version = "1.13", features = [ + "union", + "const_generics", + "const_new", ] } -regex = { version = "1.10", optional = true, default-features = false, features = ["unicode", "perf"] } -smallvec = { version = "1.13", features = ["union", "const_generics", "const_new"] } thiserror = { package = "miden-thiserror", version = "1.0", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes"] } +tracing = { version = "0.1", default-features = false, features = [ + "attributes", +] } unicode-width = { version = "0.1", features = ["no_std"] } vm-core = { package = "miden-core", path = "../core", version = "0.11", default-features = false, features = [ "diagnostics", ] } [dev-dependencies] +criterion = "0.5" pretty_assertions = "1.4" -regex = { version = "1.10", default-features = false, features = [ "unicode", "perf"] } +regex = { version = "1.10", default-features = false, features = [ + "unicode", + "perf", +] } [build-dependencies] lalrpop = { version = "0.20", default-features = false } diff --git a/assembly/benches/deserialize_std_lib.rs b/assembly/benches/deserialize_std_lib.rs new file mode 100644 index 000000000..aeb6eb827 --- /dev/null +++ b/assembly/benches/deserialize_std_lib.rs @@ -0,0 +1,70 @@ +use std::time::Duration; + +use criterion::{criterion_group, criterion_main, Criterion}; +use miden_assembly::{ + ast::{Module, ModuleKind}, + diagnostics::{IntoDiagnostic, Report}, + testing::TestContext, + Assembler, Deserializable, Library, LibraryPath, Serializable, +}; +use vm_core::utils::SliceReader; + +// TODO(serge): dedupe copy paste from library/tests.rs +macro_rules! parse_module { + ($context:expr, $path:literal, $source:expr) => {{ + let path = LibraryPath::new($path).into_diagnostic()?; + let source_file = + $context.source_manager().load(concat!("test", line!()), $source.to_string()); + Module::parse(path, ModuleKind::Library, source_file)? + }}; +} + +// TODO(serge): impl proper benchmark and remove return Result +fn deserialize_std_lib(c: &mut Criterion) -> Result<(), Report> { + let context = TestContext::new(); + let foo = r#" + export.foo + add + end + export.foo_mul + mul + end + "#; + let foo = parse_module!(&context, "test::foo", foo); + + // declare bar module + let bar = r#" + export.bar + mtree_get + end + export.bar_mul + mul + end + "#; + let bar = parse_module!(&context, "test::bar", bar); + let modules = [foo, bar]; + + let mut group = c.benchmark_group("compute_op_flags"); + group.measurement_time(Duration::from_secs(10)); + group.bench_function("deserialize_std_lib", |bench| { + bench.iter(|| { + // Serialize + let bundle = Assembler::new(context.source_manager()) + .assemble_library(modules.iter().cloned()) + .unwrap(); + + // Deserialize + let mut bytes = Vec::new(); + bundle.write_into(&mut bytes); + let deserialized = Library::read_from(&mut SliceReader::new(&bytes)).unwrap(); + assert_eq!(bundle, deserialized); + }); + }); + + group.finish(); + Ok(()) +} + +// TODO(serge): fix clippy nouse complaint +criterion_group!(op_flags_group, deserialize_std_lib); +criterion_main!(op_flags_group); diff --git a/assembly/src/lib.rs b/assembly/src/lib.rs index 2dc9eae32..6ef9bd6c4 100644 --- a/assembly/src/lib.rs +++ b/assembly/src/lib.rs @@ -7,14 +7,10 @@ extern crate alloc; #[cfg(any(test, feature = "std"))] extern crate std; -use vm_core::{ - crypto::hash::RpoDigest, - prettier, - utils::{ - ByteReader, ByteWriter, Deserializable, DeserializationError, DisplayHex, Serializable, - }, - Felt, Word, ONE, ZERO, +pub use vm_core::utils::{ + ByteReader, ByteWriter, Deserializable, DeserializationError, DisplayHex, Serializable, }; +use vm_core::{crypto::hash::RpoDigest, prettier, Felt, Word, ONE, ZERO}; mod assembler; pub mod ast; From f2078d59bf20d8085a6a71f3ec461bac005d9a49 Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 15 Aug 2024 19:44:03 +1200 Subject: [PATCH 04/18] rename group --- assembly/benches/deserialize_std_lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assembly/benches/deserialize_std_lib.rs b/assembly/benches/deserialize_std_lib.rs index aeb6eb827..76df66a41 100644 --- a/assembly/benches/deserialize_std_lib.rs +++ b/assembly/benches/deserialize_std_lib.rs @@ -65,6 +65,6 @@ fn deserialize_std_lib(c: &mut Criterion) -> Result<(), Report> { Ok(()) } -// TODO(serge): fix clippy nouse complaint -criterion_group!(op_flags_group, deserialize_std_lib); -criterion_main!(op_flags_group); +// TODO(serge): fix clippy no use complaint +criterion_group!(std_lib_group, deserialize_std_lib); +criterion_main!(std_lib_group); From 5b39f380313a37482ea9981c379ef441d64b91c1 Mon Sep 17 00:00:00 2001 From: sergerad Date: Fri, 16 Aug 2024 06:03:43 +1200 Subject: [PATCH 05/18] rm digest check --- core/src/mast/serialization/info.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/core/src/mast/serialization/info.rs b/core/src/mast/serialization/info.rs index 652d35d84..715a4ce1f 100644 --- a/core/src/mast/serialization/info.rs +++ b/core/src/mast/serialization/info.rs @@ -32,7 +32,7 @@ impl MastNodeInfo { mast_forest: &MastForest, basic_block_data_decoder: &BasicBlockDataDecoder, ) -> Result { - let mast_node = match self.ty { + match self.ty { MastNodeType::Block { offset, len: num_operations_and_decorators, @@ -71,16 +71,6 @@ impl MastNodeInfo { }, MastNodeType::Dyn => Ok(MastNode::new_dyn()), MastNodeType::External => Ok(MastNode::new_external(self.digest)), - }?; - - if mast_node.digest() == self.digest { - Ok(mast_node) - } else { - Err(DeserializationError::InvalidValue(format!( - "MastNodeInfo's digest '{}' doesn't match deserialized MastNode's digest '{}'", - self.digest, - mast_node.digest() - ))) } } } From aa366c4f09fb2c83e7004b5931607aed765c8861 Mon Sep 17 00:00:00 2001 From: sergerad Date: Fri, 16 Aug 2024 06:09:53 +1200 Subject: [PATCH 06/18] split one liner --- core/src/mast/serialization/info.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/core/src/mast/serialization/info.rs b/core/src/mast/serialization/info.rs index 715a4ce1f..d26543720 100644 --- a/core/src/mast/serialization/info.rs +++ b/core/src/mast/serialization/info.rs @@ -39,35 +39,35 @@ impl MastNodeInfo { } => { let (operations, decorators) = basic_block_data_decoder .decode_operations_and_decorators(offset, num_operations_and_decorators)?; - - Ok(MastNode::Block(BasicBlockNode::new_unsafe(operations, decorators, self.digest))) + let block = BasicBlockNode::new_unsafe(operations, decorators, self.digest); + Ok(MastNode::Block(block)) }, MastNodeType::Join { left_child_id, right_child_id } => { let left_child = MastNodeId::from_u32_safe(left_child_id, mast_forest)?; let right_child = MastNodeId::from_u32_safe(right_child_id, mast_forest)?; - - Ok(MastNode::Join(JoinNode::new_unsafe([left_child, right_child], self.digest))) + let join = JoinNode::new_unsafe([left_child, right_child], self.digest); + Ok(MastNode::Join(join)) }, MastNodeType::Split { if_branch_id, else_branch_id } => { let if_branch = MastNodeId::from_u32_safe(if_branch_id, mast_forest)?; let else_branch = MastNodeId::from_u32_safe(else_branch_id, mast_forest)?; - - Ok(MastNode::Split(SplitNode::new_unsafe([if_branch, else_branch], self.digest))) + let split = SplitNode::new_unsafe([if_branch, else_branch], self.digest); + Ok(MastNode::Split(split)) }, MastNodeType::Loop { body_id } => { let body_id = MastNodeId::from_u32_safe(body_id, mast_forest)?; - - Ok(MastNode::Loop(LoopNode::new_unsafe(body_id, self.digest))) + let loop_node = LoopNode::new_unsafe(body_id, self.digest); + Ok(MastNode::Loop(loop_node)) }, MastNodeType::Call { callee_id } => { let callee_id = MastNodeId::from_u32_safe(callee_id, mast_forest)?; - - Ok(MastNode::Call(CallNode::new_unsafe(callee_id, self.digest))) + let call = CallNode::new_unsafe(callee_id, self.digest); + Ok(MastNode::Call(call)) }, MastNodeType::SysCall { callee_id } => { let callee_id = MastNodeId::from_u32_safe(callee_id, mast_forest)?; - - Ok(MastNode::Call(CallNode::new_syscall_unsafe(callee_id, self.digest))) + let syscall = CallNode::new_syscall_unsafe(callee_id, self.digest); + Ok(MastNode::Call(syscall)) }, MastNodeType::Dyn => Ok(MastNode::new_dyn()), MastNodeType::External => Ok(MastNode::new_external(self.digest)), From e7bcf21caa73cae90e3297242f17cf5b8e4fdaae Mon Sep 17 00:00:00 2001 From: sergerad Date: Fri, 16 Aug 2024 21:07:07 +1200 Subject: [PATCH 07/18] update bench impl --- assembly/benches/deserialize_std_lib.rs | 67 +++++-------------------- assembly/src/lib.rs | 10 ++-- 2 files changed, 19 insertions(+), 58 deletions(-) diff --git a/assembly/benches/deserialize_std_lib.rs b/assembly/benches/deserialize_std_lib.rs index 76df66a41..823bd4fa4 100644 --- a/assembly/benches/deserialize_std_lib.rs +++ b/assembly/benches/deserialize_std_lib.rs @@ -1,70 +1,27 @@ -use std::time::Duration; +use std::{path::Path, time::Duration}; use criterion::{criterion_group, criterion_main, Criterion}; -use miden_assembly::{ - ast::{Module, ModuleKind}, - diagnostics::{IntoDiagnostic, Report}, - testing::TestContext, - Assembler, Deserializable, Library, LibraryPath, Serializable, -}; -use vm_core::utils::SliceReader; - -// TODO(serge): dedupe copy paste from library/tests.rs -macro_rules! parse_module { - ($context:expr, $path:literal, $source:expr) => {{ - let path = LibraryPath::new($path).into_diagnostic()?; - let source_file = - $context.source_manager().load(concat!("test", line!()), $source.to_string()); - Module::parse(path, ModuleKind::Library, source_file)? - }}; -} - -// TODO(serge): impl proper benchmark and remove return Result -fn deserialize_std_lib(c: &mut Criterion) -> Result<(), Report> { - let context = TestContext::new(); - let foo = r#" - export.foo - add - end - export.foo_mul - mul - end - "#; - let foo = parse_module!(&context, "test::foo", foo); - - // declare bar module - let bar = r#" - export.bar - mtree_get - end - export.bar_mul - mul - end - "#; - let bar = parse_module!(&context, "test::bar", bar); - let modules = [foo, bar]; +use miden_assembly::Library; +fn deserialize_std_lib(c: &mut Criterion) { let mut group = c.benchmark_group("compute_op_flags"); + let manifest_dir = env!("CARGO_MANIFEST_DIR"); group.measurement_time(Duration::from_secs(10)); group.bench_function("deserialize_std_lib", |bench| { bench.iter(|| { - // Serialize - let bundle = Assembler::new(context.source_manager()) - .assemble_library(modules.iter().cloned()) - .unwrap(); - - // Deserialize - let mut bytes = Vec::new(); - bundle.write_into(&mut bytes); - let deserialized = Library::read_from(&mut SliceReader::new(&bytes)).unwrap(); - assert_eq!(bundle, deserialized); + let asm_dir = Path::new(manifest_dir).join("..").join("stdlib").join("asm"); + let paths = [ + asm_dir.clone().join("collections").join("mmr.masm"), + // TODO(serge): Figure out how to create .masl instead + ]; + for path in paths { + let _ = Library::deserialize_from_file(path).unwrap(); + } }); }); group.finish(); - Ok(()) } -// TODO(serge): fix clippy no use complaint criterion_group!(std_lib_group, deserialize_std_lib); criterion_main!(std_lib_group); diff --git a/assembly/src/lib.rs b/assembly/src/lib.rs index 6ef9bd6c4..2dc9eae32 100644 --- a/assembly/src/lib.rs +++ b/assembly/src/lib.rs @@ -7,10 +7,14 @@ extern crate alloc; #[cfg(any(test, feature = "std"))] extern crate std; -pub use vm_core::utils::{ - ByteReader, ByteWriter, Deserializable, DeserializationError, DisplayHex, Serializable, +use vm_core::{ + crypto::hash::RpoDigest, + prettier, + utils::{ + ByteReader, ByteWriter, Deserializable, DeserializationError, DisplayHex, Serializable, + }, + Felt, Word, ONE, ZERO, }; -use vm_core::{crypto::hash::RpoDigest, prettier, Felt, Word, ONE, ZERO}; mod assembler; pub mod ast; From fad447f56ff68cbcc5603849071ed99e85e01ad0 Mon Sep 17 00:00:00 2001 From: sergerad Date: Sat, 17 Aug 2024 20:58:35 +1200 Subject: [PATCH 08/18] replace basic block constructor and add MastNodeError --- assembly/src/assembler/mast_forest_builder.rs | 8 +--- assembly/src/errors.rs | 4 +- core/src/mast/mod.rs | 20 +++++--- core/src/mast/node/basic_block_node/mod.rs | 45 +++++++++--------- core/src/mast/node/basic_block_node/tests.rs | 2 +- core/src/mast/node/mod.rs | 15 +++--- processor/src/chiplets/hasher/tests.rs | 12 +++-- processor/src/decoder/tests.rs | 47 ++++++++++--------- processor/src/trace/tests/decoder.rs | 14 +++--- 9 files changed, 85 insertions(+), 82 deletions(-) diff --git a/assembly/src/assembler/mast_forest_builder.rs b/assembly/src/assembler/mast_forest_builder.rs index 317420684..bca1934ce 100644 --- a/assembly/src/assembler/mast_forest_builder.rs +++ b/assembly/src/assembler/mast_forest_builder.rs @@ -170,12 +170,8 @@ impl MastForestBuilder { operations: Vec, decorators: Option, ) -> Result { - match decorators { - Some(decorators) => { - self.ensure_node(MastNode::new_basic_block_with_decorators(operations, decorators)) - }, - None => self.ensure_node(MastNode::new_basic_block(operations)), - } + let block = MastNode::new_basic_block(operations, decorators)?; + self.ensure_node(block) } /// Adds a join node to the forest, and returns the [`MastNodeId`] associated with it. diff --git a/assembly/src/errors.rs b/assembly/src/errors.rs index 8c4a3d22c..cc79a2d4c 100644 --- a/assembly/src/errors.rs +++ b/assembly/src/errors.rs @@ -1,6 +1,6 @@ use alloc::{string::String, sync::Arc, vec::Vec}; -use vm_core::mast::MastForestError; +use vm_core::mast::{MastForestError, MastNodeError}; use crate::{ ast::QualifiedProcedureName, @@ -76,6 +76,8 @@ pub enum AssemblyError { Other(#[from] RelatedError), #[error(transparent)] Forest(#[from] MastForestError), + #[error(transparent)] + Node(#[from] MastNodeError), } impl From for AssemblyError { diff --git a/core/src/mast/mod.rs b/core/src/mast/mod.rs index b594c0875..f59d90ad7 100644 --- a/core/src/mast/mod.rs +++ b/core/src/mast/mod.rs @@ -68,12 +68,8 @@ impl MastForest { operations: Vec, decorators: Option, ) -> Result { - match decorators { - Some(decorators) => { - self.add_node(MastNode::new_basic_block_with_decorators(operations, decorators)) - }, - None => self.add_node(MastNode::new_basic_block(operations)), - } + let block = MastNode::new_basic_block(operations, decorators)?; + self.add_node(block) } /// Adds a join node to the forest, and returns the [`MastNodeId`] associated with it. @@ -271,4 +267,16 @@ pub enum MastForestError { TooManyNodes, #[error("node id: {0} is greater than or equal to forest length: {1}")] NodeIdOverflow(MastNodeId, usize), + #[error(transparent)] + Node(#[from] MastNodeError), +} + +// MAST NODE ERROR +// ================================================================================================ + +/// Represents the types of errors that can occur when dealing with MAST nodes directly. +#[derive(Debug, thiserror::Error, PartialEq)] +pub enum MastNodeError { + #[error("basic block cannot be created from an empty list of operations")] + EmptyBasicBlock, } diff --git a/core/src/mast/node/basic_block_node/mod.rs b/core/src/mast/node/basic_block_node/mod.rs index 7e487458d..35bf7cd44 100644 --- a/core/src/mast/node/basic_block_node/mod.rs +++ b/core/src/mast/node/basic_block_node/mod.rs @@ -5,7 +5,9 @@ use miden_crypto::{hash::rpo::RpoDigest, Felt, ZERO}; use miden_formatting::prettier::PrettyPrint; use winter_utils::flatten_slice_elements; -use crate::{chiplets::hasher, Decorator, DecoratorIterator, DecoratorList, Operation}; +use crate::{ + chiplets::hasher, mast::MastNodeError, Decorator, DecoratorIterator, DecoratorList, Operation, +}; mod op_batch; pub use op_batch::OpBatch; @@ -77,15 +79,27 @@ impl BasicBlockNode { // ------------------------------------------------------------------------------------------------ /// Constructors impl BasicBlockNode { - /// Returns a new [`BasicBlockNode`] instantiated with the specified operations. + /// Returns a new [`BasicBlockNode`] instantiated with the specified operations and decorators. /// - /// # Errors (TODO) /// Returns an error if: /// - `operations` vector is empty. - /// - `operations` vector contains any number of system operations. - pub fn new(operations: Vec) -> Self { - assert!(!operations.is_empty()); // TODO: return error - Self::with_decorators(operations, DecoratorList::new()) + pub fn new( + operations: Vec, + decorators: Option, + ) -> Result { + if operations.is_empty() { + return Err(MastNodeError::EmptyBasicBlock); + } + + // None is equivalent to an empty list of decorators moving forward. + let decorators = decorators.unwrap_or_default(); + + // Validate decorators list (only in debug mode). + #[cfg(debug_assertions)] + validate_decorators(&operations, &decorators); + + let (op_batches, digest) = batch_and_hash_ops(operations); + Ok(Self { op_batches, digest, decorators }) } /// Returns a new [`BasicBlockNode`] from values that are assumed to be correct. @@ -98,23 +112,6 @@ impl BasicBlockNode { let (op_batches, _) = batch_ops(operations); Self { op_batches, digest, decorators } } - - /// Returns a new [`BasicBlockNode`] instantiated with the specified operations and decorators. - /// - /// # Errors (TODO) - /// Returns an error if: - /// - `operations` vector is empty. - /// - `operations` vector contains any number of system operations. - pub fn with_decorators(operations: Vec, decorators: DecoratorList) -> Self { - assert!(!operations.is_empty()); // TODO: return error - - // validate decorators list (only in debug mode) - #[cfg(debug_assertions)] - validate_decorators(&operations, &decorators); - - let (op_batches, digest) = batch_and_hash_ops(operations); - Self { op_batches, digest, decorators } - } } // ------------------------------------------------------------------------------------------------ diff --git a/core/src/mast/node/basic_block_node/tests.rs b/core/src/mast/node/basic_block_node/tests.rs index 1826be788..b44b3f1fd 100644 --- a/core/src/mast/node/basic_block_node/tests.rs +++ b/core/src/mast/node/basic_block_node/tests.rs @@ -306,7 +306,7 @@ fn operation_or_decorator_iterator() { (4, Decorator::Event(4)), ]; - let node = BasicBlockNode::with_decorators(operations, decorators); + let node = BasicBlockNode::new(operations, Some(decorators)).unwrap(); let mut iterator = node.iter(); diff --git a/core/src/mast/node/mod.rs b/core/src/mast/node/mod.rs index 57f4327e1..b7c80da09 100644 --- a/core/src/mast/node/mod.rs +++ b/core/src/mast/node/mod.rs @@ -27,7 +27,7 @@ pub use split_node::SplitNode; mod loop_node; pub use loop_node::LoopNode; -use super::MastForestError; +use super::{MastForestError, MastNodeError}; use crate::{ mast::{MastForest, MastNodeId}, DecoratorList, Operation, @@ -50,15 +50,12 @@ pub enum MastNode { // ------------------------------------------------------------------------------------------------ /// Constructors impl MastNode { - pub fn new_basic_block(operations: Vec) -> Self { - Self::Block(BasicBlockNode::new(operations)) - } - - pub fn new_basic_block_with_decorators( + pub fn new_basic_block( operations: Vec, - decorators: DecoratorList, - ) -> Self { - Self::Block(BasicBlockNode::with_decorators(operations, decorators)) + decorators: Option, + ) -> Result { + let block = BasicBlockNode::new(operations, decorators)?; + Ok(Self::Block(block)) } pub fn new_join( diff --git a/processor/src/chiplets/hasher/tests.rs b/processor/src/chiplets/hasher/tests.rs index 190d5ca85..1d90d3951 100644 --- a/processor/src/chiplets/hasher/tests.rs +++ b/processor/src/chiplets/hasher/tests.rs @@ -249,10 +249,10 @@ fn hash_memoization_control_blocks() { let mut mast_forest = MastForest::new(); - let t_branch = MastNode::new_basic_block(vec![Operation::Push(ZERO)]); + let t_branch = MastNode::new_basic_block(vec![Operation::Push(ZERO)], None).unwrap(); let t_branch_id = mast_forest.add_node(t_branch.clone()).unwrap(); - let f_branch = MastNode::new_basic_block(vec![Operation::Push(ONE)]); + let f_branch = MastNode::new_basic_block(vec![Operation::Push(ONE)], None).unwrap(); let f_branch_id = mast_forest.add_node(f_branch.clone()).unwrap(); let split1 = MastNode::new_split(t_branch_id, f_branch_id, &mast_forest).unwrap(); @@ -350,12 +350,13 @@ fn hash_memoization_control_blocks() { fn hash_memoization_basic_blocks() { // --- basic block with 1 batch ---------------------------------------------------------------- let basic_block = - MastNode::new_basic_block(vec![Operation::Push(Felt::new(10)), Operation::Drop]); + MastNode::new_basic_block(vec![Operation::Push(Felt::new(10)), Operation::Drop], None) + .unwrap(); hash_memoization_basic_blocks_check(basic_block); // --- basic block with multiple batches ------------------------------------------------------- - let basic_block = MastNode::new_basic_block(vec![ + let ops = vec![ Operation::Push(ONE), Operation::Push(Felt::new(2)), Operation::Push(Felt::new(3)), @@ -392,7 +393,8 @@ fn hash_memoization_basic_blocks() { Operation::Drop, Operation::Drop, Operation::Drop, - ]); + ]; + let basic_block = MastNode::new_basic_block(ops, None).unwrap(); hash_memoization_basic_blocks_check(basic_block); } diff --git a/processor/src/decoder/tests.rs b/processor/src/decoder/tests.rs index 6e7d74228..f17f94d1b 100644 --- a/processor/src/decoder/tests.rs +++ b/processor/src/decoder/tests.rs @@ -47,7 +47,7 @@ type DecoderTrace = [Vec; DECODER_TRACE_WIDTH]; #[test] fn basic_block_one_group() { let ops = vec![Operation::Pad, Operation::Add, Operation::Mul]; - let basic_block = BasicBlockNode::new(ops.clone()); + let basic_block = BasicBlockNode::new(ops.clone(), None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -93,7 +93,7 @@ fn basic_block_one_group() { fn basic_block_small() { let iv = [ONE, TWO]; let ops = vec![Operation::Push(iv[0]), Operation::Push(iv[1]), Operation::Add]; - let basic_block = BasicBlockNode::new(ops.clone()); + let basic_block = BasicBlockNode::new(ops.clone(), None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -156,7 +156,7 @@ fn basic_block() { Operation::Add, Operation::Inv, ]; - let basic_block = BasicBlockNode::new(ops.clone()); + let basic_block = BasicBlockNode::new(ops.clone(), None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -248,7 +248,7 @@ fn span_block_with_respan() { Operation::Add, Operation::Push(iv[8]), ]; - let basic_block = BasicBlockNode::new(ops.clone()); + let basic_block = BasicBlockNode::new(ops.clone(), None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -321,8 +321,8 @@ fn span_block_with_respan() { #[test] fn join_node() { - let basic_block1 = MastNode::new_basic_block(vec![Operation::Mul]); - let basic_block2 = MastNode::new_basic_block(vec![Operation::Add]); + let basic_block1 = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); + let basic_block2 = MastNode::new_basic_block(vec![Operation::Add], None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -386,8 +386,8 @@ fn join_node() { #[test] fn split_node_true() { - let basic_block1 = MastNode::new_basic_block(vec![Operation::Mul]); - let basic_block2 = MastNode::new_basic_block(vec![Operation::Add]); + let basic_block1 = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); + let basic_block2 = MastNode::new_basic_block(vec![Operation::Add], None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -438,8 +438,8 @@ fn split_node_true() { #[test] fn split_node_false() { - let basic_block1 = MastNode::new_basic_block(vec![Operation::Mul]); - let basic_block2 = MastNode::new_basic_block(vec![Operation::Add]); + let basic_block1 = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); + let basic_block2 = MastNode::new_basic_block(vec![Operation::Add], None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -493,7 +493,7 @@ fn split_node_false() { #[test] fn loop_node() { - let loop_body = MastNode::new_basic_block(vec![Operation::Pad, Operation::Drop]); + let loop_body = MastNode::new_basic_block(vec![Operation::Pad, Operation::Drop], None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -545,7 +545,7 @@ fn loop_node() { #[test] fn loop_node_skip() { - let loop_body = MastNode::new_basic_block(vec![Operation::Pad, Operation::Drop]); + let loop_body = MastNode::new_basic_block(vec![Operation::Pad, Operation::Drop], None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -587,7 +587,7 @@ fn loop_node_skip() { #[test] fn loop_node_repeat() { - let loop_body = MastNode::new_basic_block(vec![Operation::Pad, Operation::Drop]); + let loop_body = MastNode::new_basic_block(vec![Operation::Pad, Operation::Drop], None).unwrap(); let program = { let mut mast_forest = MastForest::new(); @@ -678,15 +678,15 @@ fn call_block() { Operation::Push(TWO), Operation::FmpUpdate, Operation::Pad, - ]); + ], None).unwrap(); let first_basic_block_id = mast_forest.add_node(first_basic_block.clone()).unwrap(); let foo_root_node = MastNode::new_basic_block(vec![ Operation::Push(ONE), Operation::FmpUpdate - ]); + ], None).unwrap(); let foo_root_node_id = mast_forest.add_node(foo_root_node.clone()).unwrap(); - let last_basic_block = MastNode::new_basic_block(vec![Operation::FmpAdd]); + let last_basic_block = MastNode::new_basic_block(vec![Operation::FmpAdd], None).unwrap(); let last_basic_block_id = mast_forest.add_node(last_basic_block.clone()).unwrap(); let foo_call_node = MastNode::new_call(foo_root_node_id, &mast_forest).unwrap(); @@ -887,13 +887,13 @@ fn syscall_block() { let mut mast_forest = MastForest::new(); // build foo procedure body - let foo_root = MastNode::new_basic_block(vec![Operation::Push(THREE), Operation::FmpUpdate]); + let foo_root = MastNode::new_basic_block(vec![Operation::Push(THREE), Operation::FmpUpdate], None).unwrap(); let foo_root_id = mast_forest.add_node(foo_root.clone()).unwrap(); mast_forest.make_root(foo_root_id); let kernel = Kernel::new(&[foo_root.digest()]).unwrap(); // build bar procedure body - let bar_basic_block = MastNode::new_basic_block(vec![Operation::Push(TWO), Operation::FmpUpdate]); + let bar_basic_block = MastNode::new_basic_block(vec![Operation::Push(TWO), Operation::FmpUpdate], None).unwrap(); let bar_basic_block_id = mast_forest.add_node(bar_basic_block.clone()).unwrap(); let foo_call_node = MastNode::new_syscall(foo_root_id, &mast_forest).unwrap(); @@ -908,10 +908,10 @@ fn syscall_block() { Operation::Push(ONE), Operation::FmpUpdate, Operation::Pad, - ]); + ], None).unwrap(); let first_basic_block_id = mast_forest.add_node(first_basic_block.clone()).unwrap(); - let last_basic_block = MastNode::new_basic_block(vec![Operation::FmpAdd]); + let last_basic_block = MastNode::new_basic_block(vec![Operation::FmpAdd], None).unwrap(); let last_basic_block_id = mast_forest.add_node(last_basic_block.clone()).unwrap(); let bar_call_node = MastNode::new_call(bar_root_node_id, &mast_forest).unwrap(); @@ -1175,14 +1175,15 @@ fn dyn_block() { let mut mast_forest = MastForest::new(); - let foo_root_node = MastNode::new_basic_block(vec![Operation::Push(ONE), Operation::Add]); + let foo_root_node = + MastNode::new_basic_block(vec![Operation::Push(ONE), Operation::Add], None).unwrap(); let foo_root_node_id = mast_forest.add_node(foo_root_node.clone()).unwrap(); mast_forest.make_root(foo_root_node_id); - let mul_bb_node = MastNode::new_basic_block(vec![Operation::Mul]); + let mul_bb_node = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); let mul_bb_node_id = mast_forest.add_node(mul_bb_node.clone()).unwrap(); - let save_bb_node = MastNode::new_basic_block(vec![Operation::MovDn4]); + let save_bb_node = MastNode::new_basic_block(vec![Operation::MovDn4], None).unwrap(); let save_bb_node_id = mast_forest.add_node(save_bb_node.clone()).unwrap(); let join_node = MastNode::new_join(mul_bb_node_id, save_bb_node_id, &mast_forest).unwrap(); diff --git a/processor/src/trace/tests/decoder.rs b/processor/src/trace/tests/decoder.rs index 56ff5cb96..1213b05dd 100644 --- a/processor/src/trace/tests/decoder.rs +++ b/processor/src/trace/tests/decoder.rs @@ -358,10 +358,10 @@ fn decoder_p2_span_with_respan() { fn decoder_p2_join() { let mut mast_forest = MastForest::new(); - let basic_block_1 = MastNode::new_basic_block(vec![Operation::Mul]); + let basic_block_1 = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); let basic_block_1_id = mast_forest.add_node(basic_block_1.clone()).unwrap(); - let basic_block_2 = MastNode::new_basic_block(vec![Operation::Add]); + let basic_block_2 = MastNode::new_basic_block(vec![Operation::Add], None).unwrap(); let basic_block_2_id = mast_forest.add_node(basic_block_2.clone()).unwrap(); let join = MastNode::new_join(basic_block_1_id, basic_block_2_id, &mast_forest).unwrap(); @@ -423,7 +423,7 @@ fn decoder_p2_split_true() { // build program let mut mast_forest = MastForest::new(); - let basic_block_1 = MastNode::new_basic_block(vec![Operation::Mul]); + let basic_block_1 = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); let basic_block_1_id = mast_forest.add_node(basic_block_1.clone()).unwrap(); let basic_block_2_id = mast_forest.add_block(vec![Operation::Add], None).unwrap(); @@ -477,10 +477,10 @@ fn decoder_p2_split_false() { // build program let mut mast_forest = MastForest::new(); - let basic_block_1 = MastNode::new_basic_block(vec![Operation::Mul]); + let basic_block_1 = MastNode::new_basic_block(vec![Operation::Mul], None).unwrap(); let basic_block_1_id = mast_forest.add_node(basic_block_1.clone()).unwrap(); - let basic_block_2 = MastNode::new_basic_block(vec![Operation::Add]); + let basic_block_2 = MastNode::new_basic_block(vec![Operation::Add], None).unwrap(); let basic_block_2_id = mast_forest.add_node(basic_block_2.clone()).unwrap(); let split_id = mast_forest.add_split(basic_block_1_id, basic_block_2_id).unwrap(); @@ -532,10 +532,10 @@ fn decoder_p2_loop_with_repeat() { // build program let mut mast_forest = MastForest::new(); - let basic_block_1 = MastNode::new_basic_block(vec![Operation::Pad]); + let basic_block_1 = MastNode::new_basic_block(vec![Operation::Pad], None).unwrap(); let basic_block_1_id = mast_forest.add_node(basic_block_1.clone()).unwrap(); - let basic_block_2 = MastNode::new_basic_block(vec![Operation::Drop]); + let basic_block_2 = MastNode::new_basic_block(vec![Operation::Drop], None).unwrap(); let basic_block_2_id = mast_forest.add_node(basic_block_2.clone()).unwrap(); let join = MastNode::new_join(basic_block_1_id, basic_block_2_id, &mast_forest).unwrap(); From 447a03c0bf004ccae4ccecb73b214d412932d444 Mon Sep 17 00:00:00 2001 From: sergerad Date: Sun, 18 Aug 2024 20:01:49 +1200 Subject: [PATCH 09/18] rm comment --- core/src/mast/node/join_node.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/mast/node/join_node.rs b/core/src/mast/node/join_node.rs index 5411c431f..cb58008cb 100644 --- a/core/src/mast/node/join_node.rs +++ b/core/src/mast/node/join_node.rs @@ -52,7 +52,6 @@ impl JoinNode { /// Returns a new [`JoinNode`] from values that are assumed to be correct. /// Should only be used when the source of the inputs is trusted (e.g. deserialization). pub fn new_unsafe(children: [MastNodeId; 2], digest: RpoDigest) -> Self { - // TODO(serge): debug_assert worthwhile? Need to pass in forest length to check children len Self { children, digest } } } From 6b2b93e1a145299765f7b81a0ba41b88401e6365 Mon Sep 17 00:00:00 2001 From: sergerad Date: Sun, 18 Aug 2024 20:07:50 +1200 Subject: [PATCH 10/18] move bench --- Cargo.lock | 1 - assembly/Cargo.toml | 5 ----- assembly/benches/deserialize_std_lib.rs | 27 ------------------------- miden/Cargo.toml | 4 ++++ miden/benches/deserialize_std_lib.rs | 18 +++++++++++++++++ 5 files changed, 22 insertions(+), 33 deletions(-) delete mode 100644 assembly/benches/deserialize_std_lib.rs create mode 100644 miden/benches/deserialize_std_lib.rs diff --git a/Cargo.lock b/Cargo.lock index d3c42bd4c..db15dfcc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1016,7 +1016,6 @@ name = "miden-assembly" version = "0.11.0" dependencies = [ "aho-corasick", - "criterion", "lalrpop", "lalrpop-util", "miden-core", diff --git a/assembly/Cargo.toml b/assembly/Cargo.toml index 163997f89..2b69b65d1 100644 --- a/assembly/Cargo.toml +++ b/assembly/Cargo.toml @@ -17,10 +17,6 @@ edition.workspace = true bench = false doctest = false -[[bench]] -name = "deserialize_std_lib" -harness = false - [features] default = ["std"] std = [ @@ -58,7 +54,6 @@ vm-core = { package = "miden-core", path = "../core", version = "0.11", default- ] } [dev-dependencies] -criterion = "0.5" pretty_assertions = "1.4" regex = { version = "1.10", default-features = false, features = [ "unicode", diff --git a/assembly/benches/deserialize_std_lib.rs b/assembly/benches/deserialize_std_lib.rs deleted file mode 100644 index 823bd4fa4..000000000 --- a/assembly/benches/deserialize_std_lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::{path::Path, time::Duration}; - -use criterion::{criterion_group, criterion_main, Criterion}; -use miden_assembly::Library; - -fn deserialize_std_lib(c: &mut Criterion) { - let mut group = c.benchmark_group("compute_op_flags"); - let manifest_dir = env!("CARGO_MANIFEST_DIR"); - group.measurement_time(Duration::from_secs(10)); - group.bench_function("deserialize_std_lib", |bench| { - bench.iter(|| { - let asm_dir = Path::new(manifest_dir).join("..").join("stdlib").join("asm"); - let paths = [ - asm_dir.clone().join("collections").join("mmr.masm"), - // TODO(serge): Figure out how to create .masl instead - ]; - for path in paths { - let _ = Library::deserialize_from_file(path).unwrap(); - } - }); - }); - - group.finish(); -} - -criterion_group!(std_lib_group, deserialize_std_lib); -criterion_main!(std_lib_group); diff --git a/miden/Cargo.toml b/miden/Cargo.toml index 84790fbae..70d675245 100644 --- a/miden/Cargo.toml +++ b/miden/Cargo.toml @@ -33,6 +33,10 @@ harness = false name = "program_execution" harness = false +[[bench]] +name = "deserialize_std_lib" +harness = false + [[test]] name = "miden" path = "tests/integration/main.rs" diff --git a/miden/benches/deserialize_std_lib.rs b/miden/benches/deserialize_std_lib.rs new file mode 100644 index 000000000..c8c93c0ad --- /dev/null +++ b/miden/benches/deserialize_std_lib.rs @@ -0,0 +1,18 @@ +use std::time::Duration; + +use criterion::{criterion_group, criterion_main, Criterion}; + +fn deserialize_std_lib(c: &mut Criterion) { + let mut group = c.benchmark_group("deserialize_std_lib"); + group.measurement_time(Duration::from_secs(10)); + group.bench_function("read_from_bytes", |bench| { + bench.iter(|| { + // TODO(serge): impl + }); + }); + + group.finish(); +} + +criterion_group!(std_lib_group, deserialize_std_lib); +criterion_main!(std_lib_group); From da5ec1f509636208030b04ac8ca1205d548f62cb Mon Sep 17 00:00:00 2001 From: sergerad Date: Sun, 18 Aug 2024 20:39:03 +1200 Subject: [PATCH 11/18] move bench to stdlib --- Cargo.lock | 1 + miden/Cargo.toml | 7 +++---- stdlib/Cargo.toml | 5 +++++ {miden => stdlib}/benches/deserialize_std_lib.rs | 7 ++++++- 4 files changed, 15 insertions(+), 5 deletions(-) rename {miden => stdlib}/benches/deserialize_std_lib.rs (59%) diff --git a/Cargo.lock b/Cargo.lock index db15dfcc0..8d05f9160 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1163,6 +1163,7 @@ name = "miden-stdlib" version = "0.11.0" dependencies = [ "blake3", + "criterion", "miden-air", "miden-assembly", "miden-processor", diff --git a/miden/Cargo.toml b/miden/Cargo.toml index 70d675245..3a3e6f880 100644 --- a/miden/Cargo.toml +++ b/miden/Cargo.toml @@ -33,10 +33,6 @@ harness = false name = "program_execution" harness = false -[[bench]] -name = "deserialize_std_lib" -harness = false - [[test]] name = "miden" path = "tests/integration/main.rs" @@ -96,3 +92,6 @@ test-utils = { package = "miden-test-utils", path = "../test-utils" } vm-core = { package = "miden-core", path = "../core", version = "0.11" } winter-fri = { package = "winter-fri", version = "0.9" } rand_chacha = "0.3.1" + +[build-dependencies] +assembly = { package = "miden-assembly", path = "../assembly", version = "0.11" } diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index 14952aa97..ad430c1bd 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -21,6 +21,10 @@ doctest = false name = "stdlib" path = "tests/main.rs" +[[bench]] +name = "deserialize_std_lib" +harness = false + [features] default = ["std"] std = ["assembly/std"] @@ -31,6 +35,7 @@ assembly = { package = "miden-assembly", path = "../assembly", version = "0.11", [dev-dependencies] blake3 = "1.5" +criterion = "0.5" miden-air = { package = "miden-air", path = "../air", version = "0.11", default-features = false } num = "0.4.1" num-bigint = "0.4" diff --git a/miden/benches/deserialize_std_lib.rs b/stdlib/benches/deserialize_std_lib.rs similarity index 59% rename from miden/benches/deserialize_std_lib.rs rename to stdlib/benches/deserialize_std_lib.rs index c8c93c0ad..fbfdfc280 100644 --- a/miden/benches/deserialize_std_lib.rs +++ b/stdlib/benches/deserialize_std_lib.rs @@ -1,13 +1,18 @@ use std::time::Duration; +use assembly::{utils::Deserializable, Library}; use criterion::{criterion_group, criterion_main, Criterion}; fn deserialize_std_lib(c: &mut Criterion) { + // Load the standard library from the compiled assets. + let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/std.masl")); + + // Setup and run the benchmarks. let mut group = c.benchmark_group("deserialize_std_lib"); group.measurement_time(Duration::from_secs(10)); group.bench_function("read_from_bytes", |bench| { bench.iter(|| { - // TODO(serge): impl + let _ = Library::read_from_bytes(bytes).expect("failed to read std masl!"); }); }); From 60f5a33332ab030532f0c07835198f31b820577d Mon Sep 17 00:00:00 2001 From: sergerad Date: Sun, 18 Aug 2024 20:49:52 +1200 Subject: [PATCH 12/18] update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a4c11317..b1b8e4e27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ## 0.11.0 (TBD) +#### Enhancements + +- Updated `MastForest::read_from` to deserialize without computing node hashes unnecessarily (#1453). + +#### Changes + +- Added `new_unsafe()` constructors to MAST node types which do not compute node hashes (#1453). +- Consolidated `BasicBlockNode` constructors and converted assert flow to new error type `MastNodeError` (#1453). + ## 0.10.3 (2024-08-12) #### Enhancements From d6e20c7d968e3cb81952277d9373f72dd0339c5a Mon Sep 17 00:00:00 2001 From: sergerad Date: Sun, 18 Aug 2024 21:02:23 +1200 Subject: [PATCH 13/18] increase measurement time --- stdlib/benches/deserialize_std_lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/benches/deserialize_std_lib.rs b/stdlib/benches/deserialize_std_lib.rs index fbfdfc280..8930f031b 100644 --- a/stdlib/benches/deserialize_std_lib.rs +++ b/stdlib/benches/deserialize_std_lib.rs @@ -9,7 +9,7 @@ fn deserialize_std_lib(c: &mut Criterion) { // Setup and run the benchmarks. let mut group = c.benchmark_group("deserialize_std_lib"); - group.measurement_time(Duration::from_secs(10)); + group.measurement_time(Duration::from_secs(15)); group.bench_function("read_from_bytes", |bench| { bench.iter(|| { let _ = Library::read_from_bytes(bytes).expect("failed to read std masl!"); From d84b5aa7bd34c592f6326e8f0d5348d13238b507 Mon Sep 17 00:00:00 2001 From: sergerad Date: Sun, 18 Aug 2024 21:04:41 +1200 Subject: [PATCH 14/18] rm build dep --- miden/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/miden/Cargo.toml b/miden/Cargo.toml index 3a3e6f880..84790fbae 100644 --- a/miden/Cargo.toml +++ b/miden/Cargo.toml @@ -92,6 +92,3 @@ test-utils = { package = "miden-test-utils", path = "../test-utils" } vm-core = { package = "miden-core", path = "../core", version = "0.11" } winter-fri = { package = "winter-fri", version = "0.9" } rand_chacha = "0.3.1" - -[build-dependencies] -assembly = { package = "miden-assembly", path = "../assembly", version = "0.11" } From 6353631607c348a9ff9b7e5851a13e27abe61213 Mon Sep 17 00:00:00 2001 From: sergerad Date: Mon, 19 Aug 2024 08:17:40 +1200 Subject: [PATCH 15/18] move bench to miden crate --- Cargo.lock | 1 - miden/Cargo.toml | 4 ++++ {stdlib => miden}/benches/deserialize_std_lib.rs | 8 +++----- stdlib/Cargo.toml | 5 ----- stdlib/src/lib.rs | 9 +++++++-- 5 files changed, 14 insertions(+), 13 deletions(-) rename {stdlib => miden}/benches/deserialize_std_lib.rs (65%) diff --git a/Cargo.lock b/Cargo.lock index 8d05f9160..db15dfcc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1163,7 +1163,6 @@ name = "miden-stdlib" version = "0.11.0" dependencies = [ "blake3", - "criterion", "miden-air", "miden-assembly", "miden-processor", diff --git a/miden/Cargo.toml b/miden/Cargo.toml index 84790fbae..70d675245 100644 --- a/miden/Cargo.toml +++ b/miden/Cargo.toml @@ -33,6 +33,10 @@ harness = false name = "program_execution" harness = false +[[bench]] +name = "deserialize_std_lib" +harness = false + [[test]] name = "miden" path = "tests/integration/main.rs" diff --git a/stdlib/benches/deserialize_std_lib.rs b/miden/benches/deserialize_std_lib.rs similarity index 65% rename from stdlib/benches/deserialize_std_lib.rs rename to miden/benches/deserialize_std_lib.rs index 8930f031b..2cd833194 100644 --- a/stdlib/benches/deserialize_std_lib.rs +++ b/miden/benches/deserialize_std_lib.rs @@ -2,17 +2,15 @@ use std::time::Duration; use assembly::{utils::Deserializable, Library}; use criterion::{criterion_group, criterion_main, Criterion}; +use stdlib::StdLibrary; fn deserialize_std_lib(c: &mut Criterion) { - // Load the standard library from the compiled assets. - let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/std.masl")); - - // Setup and run the benchmarks. let mut group = c.benchmark_group("deserialize_std_lib"); group.measurement_time(Duration::from_secs(15)); group.bench_function("read_from_bytes", |bench| { bench.iter(|| { - let _ = Library::read_from_bytes(bytes).expect("failed to read std masl!"); + let _ = + Library::read_from_bytes(StdLibrary::SERIALIZED).expect("failed to read std masl!"); }); }); diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index ad430c1bd..14952aa97 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -21,10 +21,6 @@ doctest = false name = "stdlib" path = "tests/main.rs" -[[bench]] -name = "deserialize_std_lib" -harness = false - [features] default = ["std"] std = ["assembly/std"] @@ -35,7 +31,6 @@ assembly = { package = "miden-assembly", path = "../assembly", version = "0.11", [dev-dependencies] blake3 = "1.5" -criterion = "0.5" miden-air = { package = "miden-air", path = "../air", version = "0.11", default-features = false } num = "0.4.1" num-bigint = "0.4" diff --git a/stdlib/src/lib.rs b/stdlib/src/lib.rs index 9441e201b..9637aff89 100644 --- a/stdlib/src/lib.rs +++ b/stdlib/src/lib.rs @@ -28,10 +28,15 @@ impl From for MastForest { } } +impl StdLibrary { + pub const SERIALIZED: &'static [u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/assets/std.masl")); +} + impl Default for StdLibrary { fn default() -> Self { - let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/std.masl")); - let contents = Library::read_from_bytes(bytes).expect("failed to read std masl!"); + let contents = + Library::read_from_bytes(Self::SERIALIZED).expect("failed to read std masl!"); Self(contents) } } From 277f49141dd5bf1f522b240eb9539dac20c3b224 Mon Sep 17 00:00:00 2001 From: sergerad Date: Mon, 19 Aug 2024 08:29:44 +1200 Subject: [PATCH 16/18] rm MastNodeError --- CHANGELOG.md | 2 +- assembly/src/errors.rs | 4 +--- core/src/mast/mod.rs | 10 ---------- core/src/mast/node/basic_block_node/mod.rs | 6 +++--- core/src/mast/node/mod.rs | 4 ++-- 5 files changed, 7 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1b8e4e27..fa9f3b0ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ #### Changes - Added `new_unsafe()` constructors to MAST node types which do not compute node hashes (#1453). -- Consolidated `BasicBlockNode` constructors and converted assert flow to new error type `MastNodeError` (#1453). +- Consolidated `BasicBlockNode` constructors and converted assert flow to `MastForestError::EmptyBasicBlock` (#1453). ## 0.10.3 (2024-08-12) diff --git a/assembly/src/errors.rs b/assembly/src/errors.rs index cc79a2d4c..8c4a3d22c 100644 --- a/assembly/src/errors.rs +++ b/assembly/src/errors.rs @@ -1,6 +1,6 @@ use alloc::{string::String, sync::Arc, vec::Vec}; -use vm_core::mast::{MastForestError, MastNodeError}; +use vm_core::mast::MastForestError; use crate::{ ast::QualifiedProcedureName, @@ -76,8 +76,6 @@ pub enum AssemblyError { Other(#[from] RelatedError), #[error(transparent)] Forest(#[from] MastForestError), - #[error(transparent)] - Node(#[from] MastNodeError), } impl From for AssemblyError { diff --git a/core/src/mast/mod.rs b/core/src/mast/mod.rs index f59d90ad7..30b1ec1d7 100644 --- a/core/src/mast/mod.rs +++ b/core/src/mast/mod.rs @@ -267,16 +267,6 @@ pub enum MastForestError { TooManyNodes, #[error("node id: {0} is greater than or equal to forest length: {1}")] NodeIdOverflow(MastNodeId, usize), - #[error(transparent)] - Node(#[from] MastNodeError), -} - -// MAST NODE ERROR -// ================================================================================================ - -/// Represents the types of errors that can occur when dealing with MAST nodes directly. -#[derive(Debug, thiserror::Error, PartialEq)] -pub enum MastNodeError { #[error("basic block cannot be created from an empty list of operations")] EmptyBasicBlock, } diff --git a/core/src/mast/node/basic_block_node/mod.rs b/core/src/mast/node/basic_block_node/mod.rs index 35bf7cd44..0cdcbff75 100644 --- a/core/src/mast/node/basic_block_node/mod.rs +++ b/core/src/mast/node/basic_block_node/mod.rs @@ -6,7 +6,7 @@ use miden_formatting::prettier::PrettyPrint; use winter_utils::flatten_slice_elements; use crate::{ - chiplets::hasher, mast::MastNodeError, Decorator, DecoratorIterator, DecoratorList, Operation, + chiplets::hasher, mast::MastForestError, Decorator, DecoratorIterator, DecoratorList, Operation, }; mod op_batch; @@ -86,9 +86,9 @@ impl BasicBlockNode { pub fn new( operations: Vec, decorators: Option, - ) -> Result { + ) -> Result { if operations.is_empty() { - return Err(MastNodeError::EmptyBasicBlock); + return Err(MastForestError::EmptyBasicBlock); } // None is equivalent to an empty list of decorators moving forward. diff --git a/core/src/mast/node/mod.rs b/core/src/mast/node/mod.rs index b7c80da09..ecfffaaaa 100644 --- a/core/src/mast/node/mod.rs +++ b/core/src/mast/node/mod.rs @@ -27,7 +27,7 @@ pub use split_node::SplitNode; mod loop_node; pub use loop_node::LoopNode; -use super::{MastForestError, MastNodeError}; +use super::MastForestError; use crate::{ mast::{MastForest, MastNodeId}, DecoratorList, Operation, @@ -53,7 +53,7 @@ impl MastNode { pub fn new_basic_block( operations: Vec, decorators: Option, - ) -> Result { + ) -> Result { let block = BasicBlockNode::new(operations, decorators)?; Ok(Self::Block(block)) } From 9f7d5b104dc952b50454c23cc3926f0349ed9c70 Mon Sep 17 00:00:00 2001 From: sergerad Date: Mon, 19 Aug 2024 08:31:25 +1200 Subject: [PATCH 17/18] add assert --- core/src/mast/node/basic_block_node/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mast/node/basic_block_node/mod.rs b/core/src/mast/node/basic_block_node/mod.rs index 0cdcbff75..a049c9ffa 100644 --- a/core/src/mast/node/basic_block_node/mod.rs +++ b/core/src/mast/node/basic_block_node/mod.rs @@ -109,6 +109,7 @@ impl BasicBlockNode { decorators: DecoratorList, digest: RpoDigest, ) -> Self { + assert!(!operations.is_empty()); let (op_batches, _) = batch_ops(operations); Self { op_batches, digest, decorators } } From 8f329e856d528dd1b41237a818fbf5f90cf0ca87 Mon Sep 17 00:00:00 2001 From: sergerad Date: Mon, 19 Aug 2024 08:33:13 +1200 Subject: [PATCH 18/18] revert assembly cargo.toml --- assembly/Cargo.toml | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/assembly/Cargo.toml b/assembly/Cargo.toml index 2b69b65d1..ce816d9bf 100644 --- a/assembly/Cargo.toml +++ b/assembly/Cargo.toml @@ -19,13 +19,7 @@ doctest = false [features] default = ["std"] -std = [ - "aho-corasick/std", - "miette/fancy", - "miette/std", - "thiserror/std", - "vm-core/std", -] +std = ["aho-corasick/std", "miette/fancy", "miette/std", "thiserror/std", "vm-core/std"] testing = ["dep:regex"] [dependencies] @@ -33,21 +27,12 @@ aho-corasick = { version = "1.1", default-features = false } lalrpop-util = { version = "0.20", default-features = false } miette = { package = "miden-miette", version = "7.1", default-features = false, features = [ "fancy-no-syscall", - "derive", -] } -regex = { version = "1.10", optional = true, default-features = false, features = [ - "unicode", - "perf", -] } -smallvec = { version = "1.13", features = [ - "union", - "const_generics", - "const_new", + "derive" ] } +regex = { version = "1.10", optional = true, default-features = false, features = ["unicode", "perf"] } +smallvec = { version = "1.13", features = ["union", "const_generics", "const_new"] } thiserror = { package = "miden-thiserror", version = "1.0", default-features = false } -tracing = { version = "0.1", default-features = false, features = [ - "attributes", -] } +tracing = { version = "0.1", default-features = false, features = ["attributes"] } unicode-width = { version = "0.1", features = ["no_std"] } vm-core = { package = "miden-core", path = "../core", version = "0.11", default-features = false, features = [ "diagnostics", @@ -55,10 +40,7 @@ vm-core = { package = "miden-core", path = "../core", version = "0.11", default- [dev-dependencies] pretty_assertions = "1.4" -regex = { version = "1.10", default-features = false, features = [ - "unicode", - "perf", -] } +regex = { version = "1.10", default-features = false, features = [ "unicode", "perf"] } [build-dependencies] lalrpop = { version = "0.20", default-features = false }