From bbd3bb7b66ad59c45b09860fb56a8ef51e862408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Laferri=C3=A8re?= Date: Thu, 11 Jul 2024 04:39:07 -0400 Subject: [PATCH] feat: implement serialization/deserialization for `Operation` (#1390) --- core/src/lib.rs | 4 +- core/src/mast/node/call_node.rs | 12 +- core/src/mast/node/dyn_node.rs | 4 +- core/src/mast/node/join_node.rs | 11 +- core/src/mast/node/loop_node.rs | 10 +- core/src/mast/node/split_node.rs | 10 +- core/src/operations/mod.rs | 666 ++++++++++++------ processor/src/chiplets/aux_trace/mod.rs | 59 +- .../src/decoder/aux_trace/block_hash_table.rs | 27 +- .../decoder/aux_trace/block_stack_table.rs | 23 +- processor/src/decoder/aux_trace/mod.rs | 18 +- .../src/decoder/aux_trace/op_group_table.rs | 9 +- 12 files changed, 546 insertions(+), 307 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index 6422eb5725..fa0ad48523 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -101,8 +101,8 @@ pub mod prettier { mod operations; pub use operations::{ - AdviceInjector, AssemblyOp, DebugOptions, Decorator, DecoratorIterator, DecoratorList, - Operation, SignatureKind, + opcode_constants::*, AdviceInjector, AssemblyOp, DebugOptions, Decorator, DecoratorIterator, + DecoratorList, Operation, SignatureKind, }; pub mod stack; diff --git a/core/src/mast/node/call_node.rs b/core/src/mast/node/call_node.rs index c2183ea84d..1f00d74c00 100644 --- a/core/src/mast/node/call_node.rs +++ b/core/src/mast/node/call_node.rs @@ -3,9 +3,11 @@ use core::fmt; use miden_crypto::{hash::rpo::RpoDigest, Felt}; use miden_formatting::prettier::PrettyPrint; -use crate::{chiplets::hasher, Operation}; - -use crate::mast::{MastForest, MastNodeId, MerkleTreeNode}; +use crate::{ + chiplets::hasher, + mast::{MastForest, MastNodeId, MerkleTreeNode}, + OPCODE_CALL, OPCODE_SYSCALL, +}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct CallNode { @@ -17,9 +19,9 @@ pub struct CallNode { /// Constants impl CallNode { /// The domain of the call block (used for control block hashing). - pub const CALL_DOMAIN: Felt = Felt::new(Operation::Call.op_code() as u64); + pub const CALL_DOMAIN: Felt = Felt::new(OPCODE_CALL as u64); /// The domain of the syscall block (used for control block hashing). - pub const SYSCALL_DOMAIN: Felt = Felt::new(Operation::SysCall.op_code() as u64); + pub const SYSCALL_DOMAIN: Felt = Felt::new(OPCODE_SYSCALL as u64); } /// Constructors diff --git a/core/src/mast/node/dyn_node.rs b/core/src/mast/node/dyn_node.rs index c298a03ade..83c46f68fe 100644 --- a/core/src/mast/node/dyn_node.rs +++ b/core/src/mast/node/dyn_node.rs @@ -4,7 +4,7 @@ use miden_crypto::{hash::rpo::RpoDigest, Felt}; use crate::{ mast::{MastForest, MerkleTreeNode}, - Operation, + OPCODE_DYN, }; #[derive(Debug, Clone, Default, PartialEq, Eq)] @@ -13,7 +13,7 @@ pub struct DynNode; /// Constants impl DynNode { /// The domain of the Dyn block (used for control block hashing). - pub const DOMAIN: Felt = Felt::new(Operation::Dyn.op_code() as u64); + pub const DOMAIN: Felt = Felt::new(OPCODE_DYN as u64); } impl MerkleTreeNode for DynNode { diff --git a/core/src/mast/node/join_node.rs b/core/src/mast/node/join_node.rs index 3c4a712655..f1a5417bf9 100644 --- a/core/src/mast/node/join_node.rs +++ b/core/src/mast/node/join_node.rs @@ -2,9 +2,12 @@ use core::fmt; use miden_crypto::{hash::rpo::RpoDigest, Felt}; -use crate::{chiplets::hasher, prettier::PrettyPrint, Operation}; - -use crate::mast::{MastForest, MastNodeId, MerkleTreeNode}; +use crate::{ + chiplets::hasher, + mast::{MastForest, MastNodeId, MerkleTreeNode}, + prettier::PrettyPrint, + OPCODE_JOIN, +}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct JoinNode { @@ -15,7 +18,7 @@ pub struct JoinNode { /// Constants impl JoinNode { /// The domain of the join block (used for control block hashing). - pub const DOMAIN: Felt = Felt::new(Operation::Join.op_code() as u64); + pub const DOMAIN: Felt = Felt::new(OPCODE_JOIN as u64); } /// Constructors diff --git a/core/src/mast/node/loop_node.rs b/core/src/mast/node/loop_node.rs index fc63b11367..1554181b46 100644 --- a/core/src/mast/node/loop_node.rs +++ b/core/src/mast/node/loop_node.rs @@ -3,9 +3,11 @@ use core::fmt; use miden_crypto::{hash::rpo::RpoDigest, Felt}; use miden_formatting::prettier::PrettyPrint; -use crate::{chiplets::hasher, Operation}; - -use crate::mast::{MastForest, MastNodeId, MerkleTreeNode}; +use crate::{ + chiplets::hasher, + mast::{MastForest, MastNodeId, MerkleTreeNode}, + OPCODE_LOOP, +}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct LoopNode { @@ -16,7 +18,7 @@ pub struct LoopNode { /// Constants impl LoopNode { /// The domain of the loop node (used for control block hashing). - pub const DOMAIN: Felt = Felt::new(Operation::Loop.op_code() as u64); + pub const DOMAIN: Felt = Felt::new(OPCODE_LOOP as u64); } /// Constructors diff --git a/core/src/mast/node/split_node.rs b/core/src/mast/node/split_node.rs index ca87501fe3..907820365f 100644 --- a/core/src/mast/node/split_node.rs +++ b/core/src/mast/node/split_node.rs @@ -3,9 +3,11 @@ use core::fmt; use miden_crypto::{hash::rpo::RpoDigest, Felt}; use miden_formatting::prettier::PrettyPrint; -use crate::{chiplets::hasher, Operation}; - -use crate::mast::{MastForest, MastNodeId, MerkleTreeNode}; +use crate::{ + chiplets::hasher, + mast::{MastForest, MastNodeId, MerkleTreeNode}, + OPCODE_SPLIT, +}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct SplitNode { @@ -16,7 +18,7 @@ pub struct SplitNode { /// Constants impl SplitNode { /// The domain of the split node (used for control block hashing). - pub const DOMAIN: Felt = Felt::new(Operation::Split.op_code() as u64); + pub const DOMAIN: Felt = Felt::new(OPCODE_SPLIT as u64); } /// Constructors diff --git a/core/src/operations/mod.rs b/core/src/operations/mod.rs index a66bcec4db..8103d4d2e8 100644 --- a/core/src/operations/mod.rs +++ b/core/src/operations/mod.rs @@ -5,124 +5,238 @@ pub use decorators::{ AdviceInjector, AssemblyOp, DebugOptions, Decorator, DecoratorIterator, DecoratorList, SignatureKind, }; +use winter_utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; + +// OPERATIONS OP CODES +// ================================================================================================ + +use opcode_constants::*; + +/// Opcode patterns have the following meanings: +/// - 00xxxxx operations do not shift the stack; constraint degree can be up to 2. +/// - 010xxxx operations shift the stack the left; constraint degree can be up to 2. +/// - 011xxxx operations shift the stack to the right; constraint degree can be up to 2. +/// - 100xxx-: operations consume 4 range checks; constraint degree can be up to 3. These are used +/// to encode most u32 operations. +/// - 101xxx-: operations where constraint degree can be up to 3. These include control flow +/// operations and some other operations requiring high degree constraints. +/// - 11xxx--: operations where constraint degree can be up to 5. These include control flow +/// operations and some other operations requiring very high degree constraints. +#[rustfmt::skip] +pub(super) mod opcode_constants { + pub const OPCODE_NOOP: u8 = 0b0000_0000; + pub const OPCODE_EQZ: u8 = 0b0000_0001; + pub const OPCODE_NEG: u8 = 0b0000_0010; + pub const OPCODE_INV: u8 = 0b0000_0011; + pub const OPCODE_INCR: u8 = 0b0000_0100; + pub const OPCODE_NOT: u8 = 0b0000_0101; + pub const OPCODE_FMPADD: u8 = 0b0000_0110; + pub const OPCODE_MLOAD: u8 = 0b0000_0111; + pub const OPCODE_SWAP: u8 = 0b0000_1000; + pub const OPCODE_CALLER: u8 = 0b0000_1001; + pub const OPCODE_MOVUP2: u8 = 0b0000_1010; + pub const OPCODE_MOVDN2: u8 = 0b0000_1011; + pub const OPCODE_MOVUP3: u8 = 0b0000_1100; + pub const OPCODE_MOVDN3: u8 = 0b0000_1101; + pub const OPCODE_ADVPOPW: u8 = 0b0000_1110; + pub const OPCODE_EXPACC: u8 = 0b0000_1111; + + pub const OPCODE_MOVUP4: u8 = 0b0001_0000; + pub const OPCODE_MOVDN4: u8 = 0b0001_0001; + pub const OPCODE_MOVUP5: u8 = 0b0001_0010; + pub const OPCODE_MOVDN5: u8 = 0b0001_0011; + pub const OPCODE_MOVUP6: u8 = 0b0001_0100; + pub const OPCODE_MOVDN6: u8 = 0b0001_0101; + pub const OPCODE_MOVUP7: u8 = 0b0001_0110; + pub const OPCODE_MOVDN7: u8 = 0b0001_0111; + pub const OPCODE_SWAPW: u8 = 0b0001_1000; + pub const OPCODE_EXT2MUL: u8 = 0b0001_1001; + pub const OPCODE_MOVUP8: u8 = 0b0001_1010; + pub const OPCODE_MOVDN8: u8 = 0b0001_1011; + pub const OPCODE_SWAPW2: u8 = 0b0001_1100; + pub const OPCODE_SWAPW3: u8 = 0b0001_1101; + pub const OPCODE_SWAPDW: u8 = 0b0001_1110; + + pub const OPCODE_ASSERT: u8 = 0b0010_0000; + pub const OPCODE_EQ: u8 = 0b0010_0001; + pub const OPCODE_ADD: u8 = 0b0010_0010; + pub const OPCODE_MUL: u8 = 0b0010_0011; + pub const OPCODE_AND: u8 = 0b0010_0100; + pub const OPCODE_OR: u8 = 0b0010_0101; + pub const OPCODE_U32AND: u8 = 0b0010_0110; + pub const OPCODE_U32XOR: u8 = 0b0010_0111; + pub const OPCODE_FRIE2F4: u8 = 0b0010_1000; + pub const OPCODE_DROP: u8 = 0b0010_1001; + pub const OPCODE_CSWAP: u8 = 0b0010_1010; + pub const OPCODE_CSWAPW: u8 = 0b0010_1011; + pub const OPCODE_MLOADW: u8 = 0b0010_1100; + pub const OPCODE_MSTORE: u8 = 0b0010_1101; + pub const OPCODE_MSTOREW: u8 = 0b0010_1110; + pub const OPCODE_FMPUPDATE: u8 = 0b0010_1111; + + pub const OPCODE_PAD: u8 = 0b0011_0000; + pub const OPCODE_DUP0: u8 = 0b0011_0001; + pub const OPCODE_DUP1: u8 = 0b0011_0010; + pub const OPCODE_DUP2: u8 = 0b0011_0011; + pub const OPCODE_DUP3: u8 = 0b0011_0100; + pub const OPCODE_DUP4: u8 = 0b0011_0101; + pub const OPCODE_DUP5: u8 = 0b0011_0110; + pub const OPCODE_DUP6: u8 = 0b0011_0111; + pub const OPCODE_DUP7: u8 = 0b0011_1000; + pub const OPCODE_DUP9: u8 = 0b0011_1001; + pub const OPCODE_DUP11: u8 = 0b0011_1010; + pub const OPCODE_DUP13: u8 = 0b0011_1011; + pub const OPCODE_DUP15: u8 = 0b0011_1100; + pub const OPCODE_ADVPOP: u8 = 0b0011_1101; + pub const OPCODE_SDEPTH: u8 = 0b0011_1110; + pub const OPCODE_CLK: u8 = 0b0011_1111; + + pub const OPCODE_U32ADD: u8 = 0b0100_0000; + pub const OPCODE_U32SUB: u8 = 0b0100_0010; + pub const OPCODE_U32MUL: u8 = 0b0100_0100; + pub const OPCODE_U32DIV: u8 = 0b0100_0110; + pub const OPCODE_U32SPLIT: u8 = 0b0100_1000; + pub const OPCODE_U32ASSERT2: u8 = 0b0100_1010; + pub const OPCODE_U32ADD3: u8 = 0b0100_1100; + pub const OPCODE_U32MADD: u8 = 0b0100_1110; + + pub const OPCODE_HPERM: u8 = 0b0101_0000; + pub const OPCODE_MPVERIFY: u8 = 0b0101_0001; + pub const OPCODE_PIPE: u8 = 0b0101_0010; + pub const OPCODE_MSTREAM: u8 = 0b0101_0011; + pub const OPCODE_SPLIT: u8 = 0b0101_0100; + pub const OPCODE_LOOP: u8 = 0b0101_0101; + pub const OPCODE_SPAN: u8 = 0b0101_0110; + pub const OPCODE_JOIN: u8 = 0b0101_0111; + pub const OPCODE_DYN: u8 = 0b0101_1000; + pub const OPCODE_RCOMBBASE: u8 = 0b0101_1001; + + pub const OPCODE_MRUPDATE: u8 = 0b0110_0000; + pub const OPCODE_PUSH: u8 = 0b0110_0100; + pub const OPCODE_SYSCALL: u8 = 0b0110_1000; + pub const OPCODE_CALL: u8 = 0b0110_1100; + pub const OPCODE_END: u8 = 0b0111_0000; + pub const OPCODE_REPEAT: u8 = 0b0111_0100; + pub const OPCODE_RESPAN: u8 = 0b0111_1000; + pub const OPCODE_HALT: u8 = 0b0111_1100; +} // OPERATIONS // ================================================================================================ -/// A set of native VM operations. -/// -/// These operations take exactly one cycle to execute. +/// A set of native VM operations which take exactly one cycle to execute. #[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[repr(u8)] pub enum Operation { // ----- system operations ------------------------------------------------------------------- /// Advances cycle counter, but does not change the state of user stack. - Noop, + Noop = OPCODE_NOOP, /// Pops the stack; if the popped value is not 1, execution fails. /// /// The internal value specifies an error code associated with the error in case when the /// execution fails. - Assert(u32), + Assert(u32) = OPCODE_ASSERT, /// Pops an element off the stack, adds the current value of the `fmp` register to it, and /// pushes the result back onto the stack. - FmpAdd, + FmpAdd = OPCODE_FMPADD, /// Pops an element off the stack and adds it to the current value of `fmp` register. - FmpUpdate, + FmpUpdate = OPCODE_FMPUPDATE, /// Pushes the current depth of the stack onto the stack. - SDepth, + SDepth = OPCODE_SDEPTH, /// Overwrites the top four stack items with the hash of a function which initiated the current /// SYSCALL. Thus, this operation can be executed only inside a SYSCALL code block. - Caller, + Caller = OPCODE_CALLER, /// Pushes the current value of the clock cycle onto the stack. This operation can be used to /// measure the number of cycles it has taken to execute the program up to the current /// instruction. - Clk, + Clk = OPCODE_CLK, // ----- flow control operations ------------------------------------------------------------- /// Marks the beginning of a join block. - Join, + Join = OPCODE_JOIN, /// Marks the beginning of a split block. - Split, + Split = OPCODE_SPLIT, /// Marks the beginning of a loop block. - Loop, + Loop = OPCODE_LOOP, /// Marks the beginning of a function call. - Call, + Call = OPCODE_CALL, /// Marks the beginning of a dynamic code block, where the target is specified by the stack. - Dyn, + Dyn = OPCODE_DYN, /// Marks the beginning of a kernel call. - SysCall, + SysCall = OPCODE_SYSCALL, /// Marks the beginning of a span code block. - Span, + Span = OPCODE_SPAN, /// Marks the end of a program block. - End, + End = OPCODE_END, /// Indicates that body of an executing loop should be executed again. - Repeat, + Repeat = OPCODE_REPEAT, /// Starts processing a new operation batch. - Respan, + Respan = OPCODE_RESPAN, /// Indicates the end of the program. This is used primarily to pad the execution trace to /// the required length. Once HALT operation is executed, no other operations can be executed /// by the VM (HALT operation itself excepted). - Halt, + Halt = OPCODE_HALT, // ----- field operations -------------------------------------------------------------------- /// Pops two elements off the stack, adds them, and pushes the result back onto the stack. - Add, + Add = OPCODE_ADD, /// Pops an element off the stack, negates it, and pushes the result back onto the stack. - Neg, + Neg = OPCODE_NEG, /// Pops two elements off the stack, multiplies them, and pushes the result back onto the /// stack. - Mul, + Mul = OPCODE_MUL, /// Pops an element off the stack, computes its multiplicative inverse, and pushes the result /// back onto the stack. - Inv, + Inv = OPCODE_INV, /// Pops an element off the stack, adds 1 to it, and pushes the result back onto the stack. - Incr, + Incr = OPCODE_INCR, /// Pops two elements off the stack, multiplies them, and pushes the result back onto the /// stack. /// /// If either of the elements is greater than 1, execution fails. This operation is equivalent /// to boolean AND. - And, + And = OPCODE_AND, /// Pops two elements off the stack and subtracts their product from their sum. /// /// If either of the elements is greater than 1, execution fails. This operation is equivalent /// to boolean OR. - Or, + Or = OPCODE_OR, /// Pops an element off the stack and subtracts it from 1. /// /// If the element is greater than one, the execution fails. This operation is equivalent to /// boolean NOT. - Not, + Not = OPCODE_NOT, /// Pops two elements off the stack and compares them. If the elements are equal, pushes 1 /// onto the stack, otherwise pushes 0 onto the stack. - Eq, + Eq = OPCODE_EQ, /// Pops an element off the stack and compares it to 0. If the element is 0, pushes 1 onto /// the stack, otherwise pushes 0 onto the stack. - Eqz, + Eqz = OPCODE_EQZ, /// Computes a single turn of exponent accumulation for the given inputs. This operation can be /// be used to compute a single turn of power of a field element. @@ -137,36 +251,36 @@ pub enum Operation { /// At the end of the operation, exponent is replaced with its square, current value of power /// of base number `a` on exponent is incorporated into the accumulator and the number is /// shifted to the right by one bit. - Expacc, + Expacc = OPCODE_EXPACC, // ----- ext2 operations --------------------------------------------------------------------- /// Computes the product of two elements in the extension field of degree 2 and pushes the /// result back onto the stack as the third and fourth elements. Pushes 0 onto the stack as /// the first and second elements. - Ext2Mul, + Ext2Mul = OPCODE_EXT2MUL, // ----- u32 operations ---------------------------------------------------------------------- /// Pops an element off the stack, splits it into upper and lower 32-bit values, and pushes /// these values back onto the stack. - U32split, + U32split = OPCODE_U32SPLIT, /// Pops two elements off the stack, adds them, and splits the result into upper and lower /// 32-bit values. Then pushes these values back onto the stack. /// /// If either of these elements is greater than or equal to 2^32, the result of this /// operation is undefined. - U32add, + U32add = OPCODE_U32ADD, /// Pops two elements off the stack and checks if each of them represents a 32-bit value. /// If both of them are, they are pushed back onto the stack, otherwise an error is returned. /// /// The internal value specifies an error code associated with the error in case when the /// assertion fails. - U32assert2(Felt), + U32assert2(Felt) = OPCODE_U32ASSERT2, /// Pops three elements off the stack, adds them together, and splits the result into upper /// and lower 32-bit values. Then pushes the result back onto the stack. - U32add3, + U32add3 = OPCODE_U32ADD3, /// Pops two elements off the stack and subtracts the first element from the second. Then, /// the result, together with a flag indicating whether subtraction underflowed is pushed @@ -174,14 +288,14 @@ pub enum Operation { /// /// If their of the values is greater than or equal to 2^32, the result of this operation is /// undefined. - U32sub, + U32sub = OPCODE_U32SUB, /// Pops two elements off the stack, multiplies them, and splits the result into upper and /// lower 32-bit values. Then pushes these values back onto the stack. /// /// If their of the values is greater than or equal to 2^32, the result of this operation is /// undefined. - U32mul, + U32mul = OPCODE_U32MUL, /// Pops two elements off the stack and multiplies them. Then pops the third element off the /// stack, and adds it to the result. Finally, splits the result into upper and lower 32-bit @@ -189,170 +303,170 @@ pub enum Operation { /// /// If any of the three values is greater than or equal to 2^32, the result of this operation /// is undefined. - U32madd, + U32madd = OPCODE_U32MADD, /// Pops two elements off the stack and divides the second element by the first. Then pushes /// the integer result of the division, together with the remainder, onto the stack. /// /// If their of the values is greater than or equal to 2^32, the result of this operation is /// undefined. - U32div, + U32div = OPCODE_U32DIV, /// Pops two elements off the stack, computes their binary AND, and pushes the result back /// onto the stack. /// /// If either of the elements is greater than or equal to 2^32, execution fails. - U32and, + U32and = OPCODE_U32AND, /// Pops two elements off the stack, computes their binary XOR, and pushes the result back /// onto the stack. /// /// If either of the elements is greater than or equal to 2^32, execution fails. - U32xor, + U32xor = OPCODE_U32XOR, // ----- stack manipulation ------------------------------------------------------------------ /// Pushes 0 onto the stack. - Pad, + Pad = OPCODE_PAD, /// Removes to element from the stack. - Drop, + Drop = OPCODE_DROP, /// Pushes a copy of stack element 0 onto the stack. - Dup0, + Dup0 = OPCODE_DUP0, /// Pushes a copy of stack element 1 onto the stack. - Dup1, + Dup1 = OPCODE_DUP1, /// Pushes a copy of stack element 2 onto the stack. - Dup2, + Dup2 = OPCODE_DUP2, /// Pushes a copy of stack element 3 onto the stack. - Dup3, + Dup3 = OPCODE_DUP3, /// Pushes a copy of stack element 4 onto the stack. - Dup4, + Dup4 = OPCODE_DUP4, /// Pushes a copy of stack element 5 onto the stack. - Dup5, + Dup5 = OPCODE_DUP5, /// Pushes a copy of stack element 6 onto the stack. - Dup6, + Dup6 = OPCODE_DUP6, /// Pushes a copy of stack element 7 onto the stack. - Dup7, + Dup7 = OPCODE_DUP7, /// Pushes a copy of stack element 9 onto the stack. - Dup9, + Dup9 = OPCODE_DUP9, /// Pushes a copy of stack element 11 onto the stack. - Dup11, + Dup11 = OPCODE_DUP11, /// Pushes a copy of stack element 13 onto the stack. - Dup13, + Dup13 = OPCODE_DUP13, /// Pushes a copy of stack element 15 onto the stack. - Dup15, + Dup15 = OPCODE_DUP15, /// Swaps stack elements 0 and 1. - Swap, + Swap = OPCODE_SWAP, /// Swaps stack elements 0, 1, 2, and 3 with elements 4, 5, 6, and 7. - SwapW, + SwapW = OPCODE_SWAPW, /// Swaps stack elements 0, 1, 2, and 3 with elements 8, 9, 10, and 11. - SwapW2, + SwapW2 = OPCODE_SWAPW2, /// Swaps stack elements 0, 1, 2, and 3, with elements 12, 13, 14, and 15. - SwapW3, + SwapW3 = OPCODE_SWAPW3, /// Swaps the top two words pair wise. /// /// Input: [D, C, B, A, ...] /// Output: [B, A, D, C, ...] - SwapDW, + SwapDW = OPCODE_SWAPDW, /// Moves stack element 2 to the top of the stack. - MovUp2, + MovUp2 = OPCODE_MOVUP2, /// Moves stack element 3 to the top of the stack. - MovUp3, + MovUp3 = OPCODE_MOVUP3, /// Moves stack element 4 to the top of the stack. - MovUp4, + MovUp4 = OPCODE_MOVUP4, /// Moves stack element 5 to the top of the stack. - MovUp5, + MovUp5 = OPCODE_MOVUP5, /// Moves stack element 6 to the top of the stack. - MovUp6, + MovUp6 = OPCODE_MOVUP6, /// Moves stack element 7 to the top of the stack. - MovUp7, + MovUp7 = OPCODE_MOVUP7, /// Moves stack element 8 to the top of the stack. - MovUp8, + MovUp8 = OPCODE_MOVUP8, /// Moves the top stack element to position 2 on the stack. - MovDn2, + MovDn2 = OPCODE_MOVDN2, /// Moves the top stack element to position 3 on the stack. - MovDn3, + MovDn3 = OPCODE_MOVDN3, /// Moves the top stack element to position 4 on the stack. - MovDn4, + MovDn4 = OPCODE_MOVDN4, /// Moves the top stack element to position 5 on the stack. - MovDn5, + MovDn5 = OPCODE_MOVDN5, /// Moves the top stack element to position 6 on the stack. - MovDn6, + MovDn6 = OPCODE_MOVDN6, /// Moves the top stack element to position 7 on the stack. - MovDn7, + MovDn7 = OPCODE_MOVDN7, /// Moves the top stack element to position 8 on the stack. - MovDn8, + MovDn8 = OPCODE_MOVDN8, /// Pops an element off the stack, and if the element is 1, swaps the top two remaining /// elements on the stack. If the popped element is 0, the stack remains unchanged. /// /// If the popped element is neither 0 nor 1, execution fails. - CSwap, + CSwap = OPCODE_CSWAP, /// Pops an element off the stack, and if the element is 1, swaps the remaining elements /// 0, 1, 2, and 3 with elements 4, 5, 6, and 7. If the popped element is 0, the stack /// remains unchanged. /// /// If the popped element is neither 0 nor 1, execution fails. - CSwapW, + CSwapW = OPCODE_CSWAPW, // ----- input / output ---------------------------------------------------------------------- /// Pushes the immediate value onto the stack. - Push(Felt), + Push(Felt) = OPCODE_PUSH, /// Removes the next element from the advice stack and pushes it onto the operand stack. - AdvPop, + AdvPop = OPCODE_ADVPOP, /// Removes a word (4 elements) from the advice stack and overwrites the top four operand /// stack elements with it. - AdvPopW, + AdvPopW = OPCODE_ADVPOPW, /// Pops an element off the stack, interprets it as a memory address, and replaces the /// remaining 4 elements at the top of the stack with values located at the specified address. - MLoadW, + MLoadW = OPCODE_MLOADW, /// Pops an element off the stack, interprets it as a memory address, and writes the remaining /// 4 elements at the top of the stack into memory at the specified address. - MStoreW, + MStoreW = OPCODE_MSTOREW, /// Pops an element off the stack, interprets it as a memory address, and pushes the first /// element of the word located at the specified address to the stack. - MLoad, + MLoad = OPCODE_MLOAD, /// Pops an element off the stack, interprets it as a memory address, and writes the remaining /// element at the top of the stack into the first element of the word located at the specified /// memory address. The remaining 3 elements of the word are not affected. - MStore, + MStore = OPCODE_MSTORE, /// Loads two words from memory, and replaces the top 8 elements of the stack with them, /// element-wise, in stack order. @@ -364,7 +478,7 @@ pub enum Operation { /// order). /// - Memory address (in position 12) is incremented by 2. /// - All other stack elements remain the same. - MStream, + MStream = OPCODE_MSTREAM, /// Pops two words from the advice stack, writes them to memory, and replaces the top 8 /// elements of the stack with them, element-wise, in stack order. @@ -378,7 +492,7 @@ pub enum Operation { /// order). /// - Memory address (in position 12) is incremented by 2. /// - All other stack elements remain the same. - Pipe, + Pipe = OPCODE_PIPE, // ----- cryptographic operations ------------------------------------------------------------ /// Performs a Rescue Prime Optimized permutation on the top 3 words of the operand stack, @@ -387,7 +501,7 @@ pub enum Operation { /// /// Stack transition: /// [C, B, A, ...] -> [F, E, D, ...] - HPerm, + HPerm = OPCODE_HPERM, /// Verifies that a Merkle path from the specified node resolves to the specified root. This /// operation can be used to prove that the prover knows a path in the specified Merkle tree @@ -405,7 +519,7 @@ pub enum Operation { /// /// The internal value specifies an error code associated with the error in case when the /// assertion fails. - MpVerify(u32), + MpVerify(u32) = OPCODE_MPVERIFY, /// Computes a new root of a Merkle tree where a node at the specified position is updated to /// the specified value. @@ -424,10 +538,10 @@ pub enum Operation { /// /// The tree will always be copied into a new instance, meaning the advice provider will keep /// track of both the old and new Merkle trees. - MrUpdate, + MrUpdate = OPCODE_MRUPDATE, /// TODO: add docs - FriE2F4, + FriE2F4 = OPCODE_FRIE2F4, /// Performs a single step of a random linear combination defining the DEEP composition /// polynomial i.e., the input to the FRI protocol. More precisely, the sum in question is: @@ -438,130 +552,21 @@ pub enum Operation { /// and $\alpha_i \cdot (T_i(x) - T_i(g \cdot z))$ and stores the values in two accumulators /// $r$ and $p$, respectively. This instruction is specialized to main trace columns i.e. /// the values $T_i(x)$ are base field elements. - RCombBase, + RCombBase = OPCODE_RCOMBBASE, } impl Operation { pub const OP_BITS: usize = 7; /// Returns the opcode of this operation. - /// - /// Opcode patterns have the following meanings: - /// - 00xxxxx operations do not shift the stack; constraint degree can be up to 2. - /// - 010xxxx operations shift the stack the left; constraint degree can be up to 2. - /// - 011xxxx operations shift the stack to the right; constraint degree can be up to 2. - /// - 100xxx-: operations consume 4 range checks; constraint degree can be up to 3. These are - /// used to encode most u32 operations. - /// - 101xxx-: operations where constraint degree can be up to 3. These include control flow - /// operations and some other operations requiring high degree constraints. - /// - 11xxx--: operations where constraint degree can be up to 5. These include control flow - /// operations and some other operations requiring very high degree constraints. #[rustfmt::skip] - pub const fn op_code(&self) -> u8 { - match self { - Self::Noop => 0b0000_0000, - Self::Eqz => 0b0000_0001, - Self::Neg => 0b0000_0010, - Self::Inv => 0b0000_0011, - Self::Incr => 0b0000_0100, - Self::Not => 0b0000_0101, - Self::FmpAdd => 0b0000_0110, - Self::MLoad => 0b0000_0111, - Self::Swap => 0b0000_1000, - Self::Caller => 0b0000_1001, - Self::MovUp2 => 0b0000_1010, - Self::MovDn2 => 0b0000_1011, - Self::MovUp3 => 0b0000_1100, - Self::MovDn3 => 0b0000_1101, - Self::AdvPopW => 0b0000_1110, - Self::Expacc => 0b0000_1111, - - Self::MovUp4 => 0b0001_0000, - Self::MovDn4 => 0b0001_0001, - Self::MovUp5 => 0b0001_0010, - Self::MovDn5 => 0b0001_0011, - Self::MovUp6 => 0b0001_0100, - Self::MovDn6 => 0b0001_0101, - Self::MovUp7 => 0b0001_0110, - Self::MovDn7 => 0b0001_0111, - Self::SwapW => 0b0001_1000, - Self::Ext2Mul => 0b0001_1001, - Self::MovUp8 => 0b0001_1010, - Self::MovDn8 => 0b0001_1011, - Self::SwapW2 => 0b0001_1100, - Self::SwapW3 => 0b0001_1101, - Self::SwapDW => 0b0001_1110, - // => 0b0001_1111, - - Self::Assert(_) => 0b0010_0000, - Self::Eq => 0b0010_0001, - Self::Add => 0b0010_0010, - Self::Mul => 0b0010_0011, - Self::And => 0b0010_0100, - Self::Or => 0b0010_0101, - Self::U32and => 0b0010_0110, - Self::U32xor => 0b0010_0111, - Self::FriE2F4 => 0b0010_1000, - Self::Drop => 0b0010_1001, - Self::CSwap => 0b0010_1010, - Self::CSwapW => 0b0010_1011, - Self::MLoadW => 0b0010_1100, - Self::MStore => 0b0010_1101, - Self::MStoreW => 0b0010_1110, - Self::FmpUpdate => 0b0010_1111, - - Self::Pad => 0b0011_0000, - Self::Dup0 => 0b0011_0001, - Self::Dup1 => 0b0011_0010, - Self::Dup2 => 0b0011_0011, - Self::Dup3 => 0b0011_0100, - Self::Dup4 => 0b0011_0101, - Self::Dup5 => 0b0011_0110, - Self::Dup6 => 0b0011_0111, - Self::Dup7 => 0b0011_1000, - Self::Dup9 => 0b0011_1001, - Self::Dup11 => 0b0011_1010, - Self::Dup13 => 0b0011_1011, - Self::Dup15 => 0b0011_1100, - Self::AdvPop => 0b0011_1101, - Self::SDepth => 0b0011_1110, - Self::Clk => 0b0011_1111, - - Self::U32add => 0b0100_0000, - Self::U32sub => 0b0100_0010, - Self::U32mul => 0b0100_0100, - Self::U32div => 0b0100_0110, - Self::U32split => 0b0100_1000, - Self::U32assert2(_) => 0b0100_1010, - Self::U32add3 => 0b0100_1100, - Self::U32madd => 0b0100_1110, - - Self::HPerm => 0b0101_0000, - Self::MpVerify(_) => 0b0101_0001, - Self::Pipe => 0b0101_0010, - Self::MStream => 0b0101_0011, - Self::Split => 0b0101_0100, - Self::Loop => 0b0101_0101, - Self::Span => 0b0101_0110, - Self::Join => 0b0101_0111, - Self::Dyn => 0b0101_1000, - Self::RCombBase => 0b0101_1001, - // => 0b0101_1010, - // => 0b0101_1011, - // => 0b0101_1100, - // => 0b0101_1101, - // => 0b0101_1110, - // => 0b0101_1111, - - Self::MrUpdate => 0b0110_0000, - Self::Push(_) => 0b0110_0100, - Self::SysCall => 0b0110_1000, - Self::Call => 0b0110_1100, - Self::End => 0b0111_0000, - Self::Repeat => 0b0111_0100, - Self::Respan => 0b0111_1000, - Self::Halt => 0b0111_1100, - } + pub fn op_code(&self) -> u8 { + // SAFETY: This is safe because we have given this enum a primitive representation with + // #[repr(u8)], with the first field of the underlying union-of-structs the discriminant. + // + // See the section on "accessing the numeric value of the discriminant" + // here: https://doc.rust-lang.org/std/mem/fn.discriminant.html + unsafe { *<*const _>::from(self).cast::() } } /// Returns an immediate value carried by this operation. @@ -723,3 +728,248 @@ impl fmt::Display for Operation { } } } + +impl Serializable for Operation { + fn write_into(&self, target: &mut W) { + target.write_u8(self.op_code()); + + // For operations that have extra data, encode it in `data`. + match self { + Operation::Assert(err_code) | Operation::MpVerify(err_code) => { + err_code.to_le_bytes().write_into(target) + } + Operation::U32assert2(err_code) => err_code.as_int().write_into(target), + Operation::Push(value) => value.as_int().write_into(target), + + // Note: we explicitly write out all the operations so that whenever we make a + // modification to the `Operation` enum, we get a compile error here. This should help + // us remember to properly encode/decode each operation variant. Remember to also fix + // deserialization! + Operation::Noop + | Operation::FmpAdd + | Operation::FmpUpdate + | Operation::SDepth + | Operation::Caller + | Operation::Clk + | Operation::Join + | Operation::Split + | Operation::Loop + | Operation::Call + | Operation::Dyn + | Operation::SysCall + | Operation::Span + | Operation::End + | Operation::Repeat + | Operation::Respan + | Operation::Halt + | Operation::Add + | Operation::Neg + | Operation::Mul + | Operation::Inv + | Operation::Incr + | Operation::And + | Operation::Or + | Operation::Not + | Operation::Eq + | Operation::Eqz + | Operation::Expacc + | Operation::Ext2Mul + | Operation::U32split + | Operation::U32add + | Operation::U32add3 + | Operation::U32sub + | Operation::U32mul + | Operation::U32madd + | Operation::U32div + | Operation::U32and + | Operation::U32xor + | Operation::Pad + | Operation::Drop + | Operation::Dup0 + | Operation::Dup1 + | Operation::Dup2 + | Operation::Dup3 + | Operation::Dup4 + | Operation::Dup5 + | Operation::Dup6 + | Operation::Dup7 + | Operation::Dup9 + | Operation::Dup11 + | Operation::Dup13 + | Operation::Dup15 + | Operation::Swap + | Operation::SwapW + | Operation::SwapW2 + | Operation::SwapW3 + | Operation::SwapDW + | Operation::MovUp2 + | Operation::MovUp3 + | Operation::MovUp4 + | Operation::MovUp5 + | Operation::MovUp6 + | Operation::MovUp7 + | Operation::MovUp8 + | Operation::MovDn2 + | Operation::MovDn3 + | Operation::MovDn4 + | Operation::MovDn5 + | Operation::MovDn6 + | Operation::MovDn7 + | Operation::MovDn8 + | Operation::CSwap + | Operation::CSwapW + | Operation::AdvPop + | Operation::AdvPopW + | Operation::MLoadW + | Operation::MStoreW + | Operation::MLoad + | Operation::MStore + | Operation::MStream + | Operation::Pipe + | Operation::HPerm + | Operation::MrUpdate + | Operation::FriE2F4 + | Operation::RCombBase => (), + } + } +} + +impl Deserializable for Operation { + fn read_from(source: &mut R) -> Result { + let op_code = source.read_u8()?; + + let operation = match op_code { + OPCODE_NOOP => Self::Noop, + OPCODE_EQZ => Self::Eqz, + OPCODE_NEG => Self::Neg, + OPCODE_INV => Self::Inv, + OPCODE_INCR => Self::Incr, + OPCODE_NOT => Self::Not, + OPCODE_FMPADD => Self::FmpAdd, + OPCODE_MLOAD => Self::MLoad, + OPCODE_SWAP => Self::Swap, + OPCODE_CALLER => Self::Caller, + OPCODE_MOVUP2 => Self::MovUp2, + OPCODE_MOVDN2 => Self::MovDn2, + OPCODE_MOVUP3 => Self::MovUp3, + OPCODE_MOVDN3 => Self::MovDn3, + OPCODE_ADVPOPW => Self::AdvPopW, + OPCODE_EXPACC => Self::Expacc, + + OPCODE_MOVUP4 => Self::MovUp4, + OPCODE_MOVDN4 => Self::MovDn4, + OPCODE_MOVUP5 => Self::MovUp5, + OPCODE_MOVDN5 => Self::MovDn5, + OPCODE_MOVUP6 => Self::MovUp6, + OPCODE_MOVDN6 => Self::MovDn6, + OPCODE_MOVUP7 => Self::MovUp7, + OPCODE_MOVDN7 => Self::MovDn7, + OPCODE_SWAPW => Self::SwapW, + OPCODE_EXT2MUL => Self::Ext2Mul, + OPCODE_MOVUP8 => Self::MovUp8, + OPCODE_MOVDN8 => Self::MovDn8, + OPCODE_SWAPW2 => Self::SwapW2, + OPCODE_SWAPW3 => Self::SwapW3, + OPCODE_SWAPDW => Self::SwapDW, + + OPCODE_ASSERT => { + let err_code_le_bytes: [u8; 4] = source.read_array()?; + let err_code = u32::from_le_bytes(err_code_le_bytes); + Self::Assert(err_code) + } + OPCODE_EQ => Self::Eq, + OPCODE_ADD => Self::Add, + OPCODE_MUL => Self::Mul, + OPCODE_AND => Self::And, + OPCODE_OR => Self::Or, + OPCODE_U32AND => Self::U32and, + OPCODE_U32XOR => Self::U32xor, + OPCODE_FRIE2F4 => Self::FriE2F4, + OPCODE_DROP => Self::Drop, + OPCODE_CSWAP => Self::CSwap, + OPCODE_CSWAPW => Self::CSwapW, + OPCODE_MLOADW => Self::MLoadW, + OPCODE_MSTORE => Self::MStore, + OPCODE_MSTOREW => Self::MStoreW, + OPCODE_FMPUPDATE => Self::FmpUpdate, + + OPCODE_PAD => Self::Pad, + OPCODE_DUP0 => Self::Dup0, + OPCODE_DUP1 => Self::Dup1, + OPCODE_DUP2 => Self::Dup2, + OPCODE_DUP3 => Self::Dup3, + OPCODE_DUP4 => Self::Dup4, + OPCODE_DUP5 => Self::Dup5, + OPCODE_DUP6 => Self::Dup6, + OPCODE_DUP7 => Self::Dup7, + OPCODE_DUP9 => Self::Dup9, + OPCODE_DUP11 => Self::Dup11, + OPCODE_DUP13 => Self::Dup13, + OPCODE_DUP15 => Self::Dup15, + OPCODE_ADVPOP => Self::AdvPop, + OPCODE_SDEPTH => Self::SDepth, + OPCODE_CLK => Self::Clk, + + OPCODE_U32ADD => Self::U32add, + OPCODE_U32SUB => Self::U32sub, + OPCODE_U32MUL => Self::U32mul, + OPCODE_U32DIV => Self::U32div, + OPCODE_U32SPLIT => Self::U32split, + OPCODE_U32ASSERT2 => { + let err_code_le_bytes: [u8; 8] = source.read_array()?; + let err_code_u64 = u64::from_le_bytes(err_code_le_bytes); + let err_code_felt = Felt::try_from(err_code_u64).map_err(|_| { + DeserializationError::InvalidValue(format!( + "Operation associated data doesn't fit in a field element: {err_code_u64}" + )) + })?; + + Self::U32assert2(err_code_felt) + } + OPCODE_U32ADD3 => Self::U32add3, + OPCODE_U32MADD => Self::U32madd, + + OPCODE_HPERM => Self::HPerm, + OPCODE_MPVERIFY => { + let err_code_le_bytes: [u8; 4] = source.read_array()?; + let err_code = u32::from_le_bytes(err_code_le_bytes); + + Self::MpVerify(err_code) + } + OPCODE_PIPE => Self::Pipe, + OPCODE_MSTREAM => Self::MStream, + OPCODE_SPLIT => Self::Split, + OPCODE_LOOP => Self::Loop, + OPCODE_SPAN => Self::Span, + OPCODE_JOIN => Self::Join, + OPCODE_DYN => Self::Dyn, + OPCODE_RCOMBBASE => Self::RCombBase, + + OPCODE_MRUPDATE => Self::MrUpdate, + OPCODE_PUSH => { + let value_le_bytes: [u8; 8] = source.read_array()?; + let value_u64 = u64::from_le_bytes(value_le_bytes); + let value_felt = Felt::try_from(value_u64).map_err(|_| { + DeserializationError::InvalidValue(format!( + "Operation associated data doesn't fit in a field element: {value_u64}" + )) + })?; + + Self::Push(value_felt) + } + OPCODE_SYSCALL => Self::SysCall, + OPCODE_CALL => Self::Call, + OPCODE_END => Self::End, + OPCODE_REPEAT => Self::Repeat, + OPCODE_RESPAN => Self::Respan, + OPCODE_HALT => Self::Halt, + _ => { + return Err(DeserializationError::InvalidValue(format!( + "Invalid opcode '{op_code}'" + ))); + } + }; + + Ok(operation) + } +} diff --git a/processor/src/chiplets/aux_trace/mod.rs b/processor/src/chiplets/aux_trace/mod.rs index eb3dbbb600..fece6d7be2 100644 --- a/processor/src/chiplets/aux_trace/mod.rs +++ b/processor/src/chiplets/aux_trace/mod.rs @@ -12,33 +12,18 @@ use miden_air::trace::{ }, main_trace::MainTrace, }; -use vm_core::{Operation, Word, ONE, ZERO}; +use vm_core::{ + Word, ONE, OPCODE_CALL, OPCODE_DYN, OPCODE_END, OPCODE_HPERM, OPCODE_JOIN, OPCODE_LOOP, + OPCODE_MLOAD, OPCODE_MLOADW, OPCODE_MPVERIFY, OPCODE_MRUPDATE, OPCODE_MSTORE, OPCODE_MSTOREW, + OPCODE_MSTREAM, OPCODE_RCOMBBASE, OPCODE_RESPAN, OPCODE_SPAN, OPCODE_SPLIT, OPCODE_SYSCALL, + OPCODE_U32AND, OPCODE_U32XOR, ZERO, +}; use super::{super::trace::AuxColumnBuilder, Felt, FieldElement}; // CONSTANTS // ================================================================================================ -const JOIN: u8 = Operation::Join.op_code(); -const SPLIT: u8 = Operation::Split.op_code(); -const LOOP: u8 = Operation::Loop.op_code(); -const DYN: u8 = Operation::Dyn.op_code(); -const CALL: u8 = Operation::Call.op_code(); -const SYSCALL: u8 = Operation::SysCall.op_code(); -const SPAN: u8 = Operation::Span.op_code(); -const RESPAN: u8 = Operation::Respan.op_code(); -const END: u8 = Operation::End.op_code(); -const AND: u8 = Operation::U32and.op_code(); -const XOR: u8 = Operation::U32xor.op_code(); -const MLOADW: u8 = Operation::MLoadW.op_code(); -const MSTOREW: u8 = Operation::MStoreW.op_code(); -const MLOAD: u8 = Operation::MLoad.op_code(); -const MSTORE: u8 = Operation::MStore.op_code(); -const MSTREAM: u8 = Operation::MStream.op_code(); -const RCOMBBASE: u8 = Operation::RCombBase.op_code(); -const HPERM: u8 = Operation::HPerm.op_code(); -const MPVERIFY: u8 = Operation::MpVerify(0).op_code(); -const MRUPDATE: u8 = Operation::MrUpdate.op_code(); const NUM_HEADER_ALPHAS: usize = 4; // CHIPLETS AUXILIARY TRACE BUILDER @@ -213,24 +198,24 @@ impl> AuxColumnBuilder for BusColumnBuilder let op_code = op_code_felt.as_int() as u8; match op_code { - JOIN | SPLIT | LOOP | DYN | CALL => { + OPCODE_JOIN | OPCODE_SPLIT | OPCODE_LOOP | OPCODE_DYN | OPCODE_CALL => { build_control_block_request(main_trace, op_code_felt, alphas, row) } - SYSCALL => build_syscall_block_request(main_trace, op_code_felt, alphas, row), - SPAN => build_span_block_request(main_trace, alphas, row), - RESPAN => build_respan_block_request(main_trace, alphas, row), - END => build_end_block_request(main_trace, alphas, row), - AND => build_bitwise_request(main_trace, ZERO, alphas, row), - XOR => build_bitwise_request(main_trace, ONE, alphas, row), - MLOADW => build_mem_request_word(main_trace, MEMORY_READ_LABEL, alphas, row), - MSTOREW => build_mem_request_word(main_trace, MEMORY_WRITE_LABEL, alphas, row), - MLOAD => build_mem_request_element(main_trace, MEMORY_READ_LABEL, alphas, row), - MSTORE => build_mem_request_element(main_trace, MEMORY_WRITE_LABEL, alphas, row), - MSTREAM => build_mstream_request(main_trace, alphas, row), - RCOMBBASE => build_rcomb_base_request(main_trace, alphas, row), - HPERM => build_hperm_request(main_trace, alphas, row), - MPVERIFY => build_mpverify_request(main_trace, alphas, row), - MRUPDATE => build_mrupdate_request(main_trace, alphas, row), + OPCODE_SYSCALL => build_syscall_block_request(main_trace, op_code_felt, alphas, row), + OPCODE_SPAN => build_span_block_request(main_trace, alphas, row), + OPCODE_RESPAN => build_respan_block_request(main_trace, alphas, row), + OPCODE_END => build_end_block_request(main_trace, alphas, row), + OPCODE_U32AND => build_bitwise_request(main_trace, ZERO, alphas, row), + OPCODE_U32XOR => build_bitwise_request(main_trace, ONE, alphas, row), + OPCODE_MLOADW => build_mem_request_word(main_trace, MEMORY_READ_LABEL, alphas, row), + OPCODE_MSTOREW => build_mem_request_word(main_trace, MEMORY_WRITE_LABEL, alphas, row), + OPCODE_MLOAD => build_mem_request_element(main_trace, MEMORY_READ_LABEL, alphas, row), + OPCODE_MSTORE => build_mem_request_element(main_trace, MEMORY_WRITE_LABEL, alphas, row), + OPCODE_MSTREAM => build_mstream_request(main_trace, alphas, row), + OPCODE_RCOMBBASE => build_rcomb_base_request(main_trace, alphas, row), + OPCODE_HPERM => build_hperm_request(main_trace, alphas, row), + OPCODE_MPVERIFY => build_mpverify_request(main_trace, alphas, row), + OPCODE_MRUPDATE => build_mrupdate_request(main_trace, alphas, row), _ => E::ONE, } } diff --git a/processor/src/decoder/aux_trace/block_hash_table.rs b/processor/src/decoder/aux_trace/block_hash_table.rs index 925cae6244..21d2d7a9da 100644 --- a/processor/src/decoder/aux_trace/block_hash_table.rs +++ b/processor/src/decoder/aux_trace/block_hash_table.rs @@ -1,9 +1,10 @@ -use vm_core::{Word, ZERO}; - -use super::{ - AuxColumnBuilder, Felt, FieldElement, MainTrace, DYN, END, HALT, JOIN, LOOP, ONE, REPEAT, SPLIT, +use vm_core::{ + Word, OPCODE_DYN, OPCODE_END, OPCODE_HALT, OPCODE_JOIN, OPCODE_LOOP, OPCODE_REPEAT, + OPCODE_SPLIT, ZERO, }; +use super::{AuxColumnBuilder, Felt, FieldElement, MainTrace, ONE}; + // BLOCK HASH TABLE COLUMN BUILDER // ================================================================================================ @@ -31,7 +32,7 @@ impl> AuxColumnBuilder for BlockHashTableCo let op_code = main_trace.get_op_code(row).as_int() as u8; match op_code { - END => BlockHashTableRow::from_end(main_trace, row).collapse(alphas), + OPCODE_END => BlockHashTableRow::from_end(main_trace, row).collapse(alphas), _ => E::ONE, } } @@ -41,19 +42,19 @@ impl> AuxColumnBuilder for BlockHashTableCo let op_code = main_trace.get_op_code(row).as_int() as u8; match op_code { - JOIN => { + OPCODE_JOIN => { let left_child_row = BlockHashTableRow::from_join(main_trace, row, true); let right_child_row = BlockHashTableRow::from_join(main_trace, row, false); // Note: this adds the 2 rows separately to the block hash table. left_child_row.collapse(alphas) * right_child_row.collapse(alphas) } - SPLIT => BlockHashTableRow::from_split(main_trace, row).collapse(alphas), - LOOP => BlockHashTableRow::from_loop(main_trace, row) + OPCODE_SPLIT => BlockHashTableRow::from_split(main_trace, row).collapse(alphas), + OPCODE_LOOP => BlockHashTableRow::from_loop(main_trace, row) .map(|row| row.collapse(alphas)) .unwrap_or(E::ONE), - REPEAT => BlockHashTableRow::from_repeat(main_trace, row).collapse(alphas), - DYN => BlockHashTableRow::from_dyn(main_trace, row).collapse(alphas), + OPCODE_REPEAT => BlockHashTableRow::from_repeat(main_trace, row).collapse(alphas), + OPCODE_DYN => BlockHashTableRow::from_dyn(main_trace, row).collapse(alphas), _ => E::ONE, } } @@ -88,7 +89,7 @@ impl BlockHashTableRow { pub fn table_init(main_trace: &MainTrace) -> Self { let program_hash = { let row_with_halt = (0..main_trace.num_rows()) - .find(|row| main_trace.get_op_code(*row) == Felt::from(HALT)) + .find(|row| main_trace.get_op_code(*row) == Felt::from(OPCODE_HALT)) .expect("execution trace must include at least one occurrence of HALT"); main_trace.decoder_hasher_state_first_half(row_with_halt) @@ -118,7 +119,9 @@ impl BlockHashTableRow { // "second child" // - HALT: The end of the program, which a first child can't find itself in (since the // second child needs to execute first) - let is_first_child = op_code_next != END && op_code_next != REPEAT && op_code_next != HALT; + let is_first_child = op_code_next != OPCODE_END + && op_code_next != OPCODE_REPEAT + && op_code_next != OPCODE_HALT; let is_loop_body = main_trace .is_loop_body_flag(row) .try_into() diff --git a/processor/src/decoder/aux_trace/block_stack_table.rs b/processor/src/decoder/aux_trace/block_stack_table.rs index bd21450978..ed838bdb97 100644 --- a/processor/src/decoder/aux_trace/block_stack_table.rs +++ b/processor/src/decoder/aux_trace/block_stack_table.rs @@ -1,8 +1,10 @@ -use super::{ - AuxColumnBuilder, Felt, FieldElement, MainTrace, CALL, DYN, END, JOIN, LOOP, ONE, RESPAN, SPAN, - SPLIT, SYSCALL, ZERO, +use vm_core::{ + OPCODE_CALL, OPCODE_DYN, OPCODE_END, OPCODE_JOIN, OPCODE_LOOP, OPCODE_RESPAN, OPCODE_SPAN, + OPCODE_SPLIT, OPCODE_SYSCALL, }; +use super::{AuxColumnBuilder, Felt, FieldElement, MainTrace, ONE, ZERO}; + // BLOCK STACK TABLE COLUMN BUILDER // ================================================================================================ @@ -18,8 +20,10 @@ impl> AuxColumnBuilder for BlockStackColumn let op_code = op_code_felt.as_int() as u8; match op_code { - RESPAN => get_block_stack_table_removal_multiplicand(main_trace, i, true, alphas), - END => get_block_stack_table_removal_multiplicand(main_trace, i, false, alphas), + OPCODE_RESPAN => { + get_block_stack_table_removal_multiplicand(main_trace, i, true, alphas) + } + OPCODE_END => get_block_stack_table_removal_multiplicand(main_trace, i, false, alphas), _ => E::ONE, } } @@ -30,7 +34,8 @@ impl> AuxColumnBuilder for BlockStackColumn let op_code = op_code_felt.as_int() as u8; match op_code { - JOIN | SPLIT | SPAN | DYN | LOOP | RESPAN | CALL | SYSCALL => { + OPCODE_JOIN | OPCODE_SPLIT | OPCODE_SPAN | OPCODE_DYN | OPCODE_LOOP | OPCODE_RESPAN + | OPCODE_CALL | OPCODE_SYSCALL => { get_block_stack_table_inclusion_multiplicand(main_trace, i, alphas, op_code) } _ => E::ONE, @@ -102,17 +107,17 @@ fn get_block_stack_table_inclusion_multiplicand E { let block_id = main_trace.addr(i + 1); - let parent_id = if op_code == RESPAN { + let parent_id = if op_code == OPCODE_RESPAN { main_trace.decoder_hasher_state_element(1, i + 1) } else { main_trace.addr(i) }; - let is_loop = if op_code == LOOP { + let is_loop = if op_code == OPCODE_LOOP { main_trace.stack_element(0, i) } else { ZERO }; - let elements = if op_code == CALL || op_code == SYSCALL { + let elements = if op_code == OPCODE_CALL || op_code == OPCODE_SYSCALL { let parent_ctx = main_trace.ctx(i); let parent_fmp = main_trace.fmp(i); let parent_stack_depth = main_trace.stack_depth(i); diff --git a/processor/src/decoder/aux_trace/mod.rs b/processor/src/decoder/aux_trace/mod.rs index c5e53fff1e..805947189f 100644 --- a/processor/src/decoder/aux_trace/mod.rs +++ b/processor/src/decoder/aux_trace/mod.rs @@ -2,7 +2,7 @@ use super::{Felt, ONE, ZERO}; use crate::trace::AuxColumnBuilder; use alloc::vec::Vec; use miden_air::trace::main_trace::MainTrace; -use vm_core::{FieldElement, Operation}; +use vm_core::FieldElement; mod block_hash_table; use block_hash_table::BlockHashTableColumnBuilder; @@ -16,22 +16,6 @@ use block_stack_table::BlockStackColumnBuilder; mod op_group_table; use op_group_table::OpGroupTableColumnBuilder; -// CONSTANTS -// ================================================================================================ - -const JOIN: u8 = Operation::Join.op_code(); -const SPLIT: u8 = Operation::Split.op_code(); -const LOOP: u8 = Operation::Loop.op_code(); -const REPEAT: u8 = Operation::Repeat.op_code(); -const DYN: u8 = Operation::Dyn.op_code(); -const CALL: u8 = Operation::Call.op_code(); -const SYSCALL: u8 = Operation::SysCall.op_code(); -const SPAN: u8 = Operation::Span.op_code(); -const RESPAN: u8 = Operation::Respan.op_code(); -const PUSH: u8 = Operation::Push(ZERO).op_code(); -const END: u8 = Operation::End.op_code(); -const HALT: u8 = Operation::Halt.op_code(); - // AUXILIARY TRACE BUILDER // ================================================================================================ diff --git a/processor/src/decoder/aux_trace/op_group_table.rs b/processor/src/decoder/aux_trace/op_group_table.rs index 8e780bc343..b921481900 100644 --- a/processor/src/decoder/aux_trace/op_group_table.rs +++ b/processor/src/decoder/aux_trace/op_group_table.rs @@ -1,5 +1,6 @@ -use super::{AuxColumnBuilder, Felt, FieldElement, MainTrace, ONE, PUSH, RESPAN, SPAN}; +use super::{AuxColumnBuilder, Felt, FieldElement, MainTrace, ONE}; use miden_air::trace::decoder::{OP_BATCH_2_GROUPS, OP_BATCH_4_GROUPS, OP_BATCH_8_GROUPS}; +use vm_core::{OPCODE_PUSH, OPCODE_RESPAN, OPCODE_SPAN}; // OP GROUP TABLE COLUMN // ================================================================================================ @@ -27,7 +28,9 @@ impl> AuxColumnBuilder for OpGroupTableColu let op_code = op_code_felt.as_int() as u8; match op_code { - SPAN | RESPAN => get_op_group_table_inclusion_multiplicand(main_trace, i, alphas), + OPCODE_SPAN | OPCODE_RESPAN => { + get_op_group_table_inclusion_multiplicand(main_trace, i, alphas) + } _ => E::ONE, } } @@ -83,7 +86,7 @@ fn get_op_group_table_removal_multiplicand>( let block_id = main_trace.addr(i); let op_code = main_trace.get_op_code(i); - let tmp = if op_code == Felt::from(PUSH) { + let tmp = if op_code == Felt::from(OPCODE_PUSH) { main_trace.stack_element(0, i + 1) } else { let h0 = main_trace.decoder_hasher_state_first_half(i + 1)[0];