use super::types::Type; /// Opcodes supported by the VM #[derive(Copy, Clone, Debug)] #[repr(u8)] pub enum Opcode { /// Elliptic curve addition EcAdd = 0x00, /// Elliptic curve multiplication EcMul = 0x01, /// Elliptic curve multiplication with a Base field element EcMulBase = 0x02, /// Elliptic curve multiplication with a u64 wrapped in a Scalar element EcMulShort = 0x03, /// Get the x coordinate of an elliptic curve point EcGetX = 0x08, /// Get the y coordinate of an elliptic curve point EcGetY = 0x09, /// Poseidon hash of N elements PoseidonHash = 0x10, /// Calculate merkle root given a position, Merkle path, and an element CalculateMerkleRoot = 0x20, /// Base field element addition BaseAdd = 0x30, /// Base field element multiplication BaseMul = 0x31, /// Base field element subtraction BaseSub = 0x32, /// Base field greater than comparison GreaterThan = 0x33, /// Constrain a Base field element to a circuit's public input ConstrainInstance = 0xf0, /// Intermediate opcode for the compiler, should never appear in the result Noop = 0xff, } impl Opcode { /// Return a tuple of vectors of types that are accepted by a specific opcode /// `r.0` is the return type(s) and `r.1` is the argument type(s). pub fn arg_types(&self) -> (Vec, Vec) { match self { // (return_type, opcode_arg_types) Opcode::EcAdd => (vec![Type::EcPoint], vec![Type::EcPoint, Type::EcPoint]), Opcode::EcMul => (vec![Type::EcPoint], vec![Type::Scalar, Type::EcFixedPoint]), Opcode::EcMulBase => (vec![Type::EcPoint], vec![Type::Base, Type::EcFixedPointBase]), Opcode::EcMulShort => (vec![Type::EcPoint], vec![Type::Base, Type::EcFixedPointShort]), Opcode::EcGetX => (vec![Type::Base], vec![Type::EcPoint]), Opcode::EcGetY => (vec![Type::Base], vec![Type::EcPoint]), Opcode::PoseidonHash => (vec![Type::Base], vec![Type::BaseArray]), Opcode::CalculateMerkleRoot => { (vec![Type::Base], vec![Type::Uint32, Type::MerklePath, Type::Base]) } Opcode::BaseAdd => (vec![Type::Base], vec![Type::Base, Type::Base]), Opcode::BaseMul => (vec![Type::Base], vec![Type::Base, Type::Base]), Opcode::BaseSub => (vec![Type::Base], vec![Type::Base, Type::Base]), Opcode::GreaterThan => (vec![Type::Base], vec![Type::Base, Type::Base]), Opcode::ConstrainInstance => (vec![], vec![Type::Base]), Opcode::Noop => (vec![], vec![]), } } pub fn from_repr(b: u8) -> Self { match b { 0x00 => Self::EcAdd, 0x01 => Self::EcMul, 0x02 => Self::EcMulBase, 0x03 => Self::EcMulShort, 0x08 => Self::EcGetX, 0x09 => Self::EcGetY, 0x10 => Self::PoseidonHash, 0x20 => Self::CalculateMerkleRoot, 0x30 => Self::BaseAdd, 0x31 => Self::BaseMul, 0x32 => Self::BaseSub, 0x33 => Self::GreaterThan, 0xf0 => Self::ConstrainInstance, _ => unimplemented!(), } } }