Skip to content

Commit

Permalink
cleanup deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
plafer committed Jul 10, 2024
1 parent 1becb89 commit acc0788
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 167 deletions.
2 changes: 1 addition & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ mod operations;
pub use operations::opcode_constants::*;
pub use operations::{
AdviceInjector, AssemblyOp, DebugOptions, Decorator, DecoratorIterator, DecoratorList,
Operation, OperationData, SignatureKind,
Operation, SignatureKind,
};

pub mod stack;
Expand Down
291 changes: 125 additions & 166 deletions core/src/operations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use super::Felt;
use core::fmt;
mod decorators;
use alloc::string::ToString;
pub use decorators::{
AdviceInjector, AssemblyOp, DebugOptions, Decorator, DecoratorIterator, DecoratorList,
SignatureKind,
};
use miden_crypto::ZERO;
use winter_utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};

// OPERATIONS OP CODES
Expand Down Expand Up @@ -557,148 +555,6 @@ pub enum Operation {
RCombBase = OPCODE_RCOMBBASE,
}

pub enum OperationData {
Felt(Felt),
U32(u32),
None,
}

/// Constructors
impl Operation {
/// Builds an operation from its opcode and inline data (if any).
pub fn with_opcode_and_data(
opcode: u8,
data: OperationData,
) -> Result<Self, DeserializationError> {
match opcode {
0b0000_0000 => Ok(Self::Noop),
0b0000_0001 => Ok(Self::Eqz),
0b0000_0010 => Ok(Self::Neg),
0b0000_0011 => Ok(Self::Inv),
0b0000_0100 => Ok(Self::Incr),
0b0000_0101 => Ok(Self::Not),
0b0000_0110 => Ok(Self::FmpAdd),
0b0000_0111 => Ok(Self::MLoad),
0b0000_1000 => Ok(Self::Swap),
0b0000_1001 => Ok(Self::Caller),
0b0000_1010 => Ok(Self::MovUp2),
0b0000_1011 => Ok(Self::MovDn2),
0b0000_1100 => Ok(Self::MovUp3),
0b0000_1101 => Ok(Self::MovDn3),
0b0000_1110 => Ok(Self::AdvPopW),
0b0000_1111 => Ok(Self::Expacc),

0b0001_0000 => Ok(Self::MovUp4),
0b0001_0001 => Ok(Self::MovDn4),
0b0001_0010 => Ok(Self::MovUp5),
0b0001_0011 => Ok(Self::MovDn5),
0b0001_0100 => Ok(Self::MovUp6),
0b0001_0101 => Ok(Self::MovDn6),
0b0001_0110 => Ok(Self::MovUp7),
0b0001_0111 => Ok(Self::MovDn7),
0b0001_1000 => Ok(Self::SwapW),
0b0001_1001 => Ok(Self::Ext2Mul),
0b0001_1010 => Ok(Self::MovUp8),
0b0001_1011 => Ok(Self::MovDn8),
0b0001_1100 => Ok(Self::SwapW2),
0b0001_1101 => Ok(Self::SwapW3),
0b0001_1110 => Ok(Self::SwapDW),
// 0b0001_1111 => <empty> ,
0b0010_0000 => match data {
OperationData::U32(value) => Ok(Self::Assert(value)),
_ => Err(DeserializationError::InvalidValue(
"Invalid opcode data. 'Assert' opcode provided, hence expected to receive u32 data.".to_string()
)),
},
0b0010_0001 => Ok(Self::Eq),
0b0010_0010 => Ok(Self::Add),
0b0010_0011 => Ok(Self::Mul),
0b0010_0100 => Ok(Self::And),
0b0010_0101 => Ok(Self::Or),
0b0010_0110 => Ok(Self::U32and),
0b0010_0111 => Ok(Self::U32xor),
0b0010_1000 => Ok(Self::FriE2F4),
0b0010_1001 => Ok(Self::Drop),
0b0010_1010 => Ok(Self::CSwap),
0b0010_1011 => Ok(Self::CSwapW),
0b0010_1100 => Ok(Self::MLoadW),
0b0010_1101 => Ok(Self::MStore),
0b0010_1110 => Ok(Self::MStoreW),
0b0010_1111 => Ok(Self::FmpUpdate),

0b0011_0000 => Ok(Self::Pad),
0b0011_0001 => Ok(Self::Dup0),
0b0011_0010 => Ok(Self::Dup1),
0b0011_0011 => Ok(Self::Dup2),
0b0011_0100 => Ok(Self::Dup3),
0b0011_0101 => Ok(Self::Dup4),
0b0011_0110 => Ok(Self::Dup5),
0b0011_0111 => Ok(Self::Dup6),
0b0011_1000 => Ok(Self::Dup7),
0b0011_1001 => Ok(Self::Dup9),
0b0011_1010 => Ok(Self::Dup11),
0b0011_1011 => Ok(Self::Dup13),
0b0011_1100 => Ok(Self::Dup15),
0b0011_1101 => Ok(Self::AdvPop),
0b0011_1110 => Ok(Self::SDepth),
0b0011_1111 => Ok(Self::Clk),

0b0100_0000 => Ok(Self::U32add),
0b0100_0010 => Ok(Self::U32sub),
0b0100_0100 => Ok(Self::U32mul),
0b0100_0110 => Ok(Self::U32div),
0b0100_1000 => Ok(Self::U32split),
0b0100_1010 => match data {
OperationData::U32(value) => Ok(Self::U32assert2(value)),
_ => Err(DeserializationError::InvalidValue(
"Invalid opcode data. 'U32assert2' opcode provided, hence expected to receive u32 data.".to_string()
)),
},
0b0100_1100 => Ok(Self::U32add3),
0b0100_1110 => Ok(Self::U32madd),

0b0101_0000 => Ok(Self::HPerm),
0b0101_0001 => match data {
OperationData::U32(value) => Ok(Self::MpVerify(value)),
_ => Err(DeserializationError::InvalidValue(
"Invalid opcode data. 'MpVerify' opcode provided, hence expected to receive u32 data.".to_string()
)),
},
0b0101_0010 => Ok(Self::Pipe),
0b0101_0011 => Ok(Self::MStream),
0b0101_0100 => Ok(Self::Split),
0b0101_0101 => Ok(Self::Loop),
0b0101_0110 => Ok(Self::Span),
0b0101_0111 => Ok(Self::Join),
0b0101_1000 => Ok(Self::Dyn),
0b0101_1001 => Ok(Self::RCombBase),
// 0b0101_1010 => <empty>,
// 0b0101_1011 => <empty>,
// 0b0101_1100 => <empty>,
// 0b0101_1101 => <empty>,
// 0b0101_1110 => <empty>,
// 0b0101_1111 => <empty>,
0b0110_0000 => Ok(Self::MrUpdate),
0b0110_0100 => match data {
OperationData::Felt(value) => Ok(Self::Push(value)),
_ => Err(DeserializationError::InvalidValue(
"Invalid opcode data. 'Push' opcode provided, hence expected to receive Felt data.".to_string()
)),
},
0b0110_1000 => Ok(Self::SysCall),
0b0110_1100 => Ok(Self::Call),
0b0111_0000 => Ok(Self::End),
0b0111_0100 => Ok(Self::Repeat),
0b0111_1000 => Ok(Self::Respan),
0b0111_1100 => Ok(Self::Halt),

_ => Err(DeserializationError::InvalidValue(format!(
"Invalid opcode {opcode}"
))),
}
}
}

impl Operation {
pub const OP_BITS: usize = 7;

Expand Down Expand Up @@ -982,28 +838,131 @@ impl Deserializable for Operation {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let op_code = source.read_u8()?;

let operation = if op_code == Operation::Assert(0).op_code()
|| op_code == Operation::MpVerify(0).op_code()
|| op_code == Operation::U32assert2(0).op_code()
{
let value_le_bytes: [u8; 4] = source.read_array()?;
let value = u32::from_le_bytes(value_le_bytes);

Operation::with_opcode_and_data(op_code, OperationData::U32(value))?
} else if op_code == Operation::Push(ZERO).op_code() {
// Felt operation data
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}"
))
})?;

Operation::with_opcode_and_data(op_code, OperationData::Felt(value_felt))?
} else {
// No operation data
Operation::with_opcode_and_data(op_code, OperationData::None)?
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 value_le_bytes: [u8; 4] = source.read_array()?;
let value = u32::from_le_bytes(value_le_bytes);
Self::Assert(value)
}
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 value_le_bytes: [u8; 4] = source.read_array()?;
let value = u32::from_le_bytes(value_le_bytes);

Self::U32assert2(value)
}
OPCODE_U32ADD3 => Self::U32add3,
OPCODE_U32MADD => Self::U32madd,

OPCODE_HPERM => Self::HPerm,
OPCODE_MPVERIFY => {
let value_le_bytes: [u8; 4] = source.read_array()?;
let value = u32::from_le_bytes(value_le_bytes);

Self::MpVerify(value)
}
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)
Expand Down

0 comments on commit acc0788

Please sign in to comment.