From fd32a69aa99c2a1acf1cdd81cda4dfb8e32d71cf Mon Sep 17 00:00:00 2001 From: Serge Radinovich <47865535+sergerad@users.noreply.github.com> Date: Mon, 19 Aug 2024 09:02:13 +1200 Subject: [PATCH] feat: add unsafe constructors to nodes for deserialization (#1453) --- CHANGELOG.md | 9 +++ assembly/src/assembler/mast_forest_builder.rs | 8 +- core/src/mast/mod.rs | 10 +-- core/src/mast/node/basic_block_node/mod.rs | 79 +++++++++++-------- core/src/mast/node/basic_block_node/tests.rs | 20 ++--- core/src/mast/node/call_node.rs | 12 +++ core/src/mast/node/join_node.rs | 5 +- core/src/mast/node/loop_node.rs | 7 ++ core/src/mast/node/mod.rs | 13 ++- core/src/mast/node/split_node.rs | 5 +- core/src/mast/serialization/info.rs | 42 ++++------ miden/Cargo.toml | 4 + miden/benches/deserialize_std_lib.rs | 21 +++++ processor/src/chiplets/hasher/tests.rs | 12 +-- processor/src/decoder/tests.rs | 47 +++++------ processor/src/trace/tests/decoder.rs | 14 ++-- stdlib/src/lib.rs | 9 ++- 17 files changed, 188 insertions(+), 129 deletions(-) create mode 100644 miden/benches/deserialize_std_lib.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a4c11317e..fa9f3b0ce2 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 `MastForestError::EmptyBasicBlock` (#1453). + ## 0.10.3 (2024-08-12) #### Enhancements diff --git a/assembly/src/assembler/mast_forest_builder.rs b/assembly/src/assembler/mast_forest_builder.rs index 3174206843..bca1934ced 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/core/src/mast/mod.rs b/core/src/mast/mod.rs index b594c08755..30b1ec1d7b 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,6 @@ pub enum MastForestError { TooManyNodes, #[error("node id: {0} is greater than or equal to forest length: {1}")] NodeIdOverflow(MastNodeId, usize), + #[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 8c833da425..a049c9ffa1 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::MastForestError, Decorator, DecoratorIterator, DecoratorList, Operation, +}; mod op_batch; pub use op_batch::OpBatch; @@ -77,31 +79,38 @@ impl BasicBlockNode { // ------------------------------------------------------------------------------------------------ /// Constructors impl BasicBlockNode { - /// Returns a new [`BasicBlockNode`] instantiated with the specified operations. - /// - /// # 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()) - } - /// 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 + pub fn new( + operations: Vec, + decorators: Option, + ) -> Result { + if operations.is_empty() { + return Err(MastForestError::EmptyBasicBlock); + } - // validate decorators list (only in debug mode) + // 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_ops(operations); + 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. + /// 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 { + assert!(!operations.is_empty()); + let (op_batches, _) = batch_ops(operations); Self { op_batches, digest, decorators } } } @@ -292,18 +301,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(); @@ -312,22 +332,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 49a663ae33..b44b3f1fd8 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]; @@ -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/call_node.rs b/core/src/mast/node/call_node.rs index cee4d8c394..f5038dd57c 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 f4f92ff6ac..cb58008cb1 100644 --- a/core/src/mast/node/join_node.rs +++ b/core/src/mast/node/join_node.rs @@ -49,8 +49,9 @@ 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 { Self { children, digest } } } diff --git a/core/src/mast/node/loop_node.rs b/core/src/mast/node/loop_node.rs index dfda217c2c..08e30ca69d 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/mod.rs b/core/src/mast/node/mod.rs index 57f4327e16..ecfffaaaa1 100644 --- a/core/src/mast/node/mod.rs +++ b/core/src/mast/node/mod.rs @@ -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/core/src/mast/node/split_node.rs b/core/src/mast/node/split_node.rs index f6dcaacf83..635049157f 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 3b72a29ea5..d26543720e 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::{MastForest, MastNode, MastNodeId}; +use crate::mast::{ + BasicBlockNode, CallNode, JoinNode, LoopNode, MastForest, MastNode, MastNodeId, SplitNode, +}; // MAST NODE INFO // ================================================================================================ @@ -30,57 +32,45 @@ 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, } => { 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)) + 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::new_join(left_child, right_child, mast_forest) - .expect("invalid node id")) + 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::new_split(if_branch, else_branch, mast_forest) - .expect("invalid node id")) + 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::new_loop(body_id, mast_forest).expect("invalid node id")) + 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::new_call(callee_id, mast_forest).expect("invalid node id")) + 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::new_syscall(callee_id, mast_forest).expect("invalid node id")) + 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)), - }?; - - 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() - ))) } } } diff --git a/miden/Cargo.toml b/miden/Cargo.toml index 84790fbae9..70d6752458 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 0000000000..2cd8331947 --- /dev/null +++ b/miden/benches/deserialize_std_lib.rs @@ -0,0 +1,21 @@ +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) { + 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(StdLibrary::SERIALIZED).expect("failed to read std masl!"); + }); + }); + + group.finish(); +} + +criterion_group!(std_lib_group, deserialize_std_lib); +criterion_main!(std_lib_group); diff --git a/processor/src/chiplets/hasher/tests.rs b/processor/src/chiplets/hasher/tests.rs index 190d5ca85f..1d90d3951f 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 6e7d74228d..f17f94d1bf 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 56ff5cb96e..1213b05dd4 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(); diff --git a/stdlib/src/lib.rs b/stdlib/src/lib.rs index 9441e201b0..9637aff89c 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) } }