From 29005dc58683292b4ccaf03786672a07908e7ff9 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Sat, 21 Oct 2023 11:44:23 -0400 Subject: [PATCH 1/3] Use SUBMOD in Kernel --- .../kernel/asm/curve/bn254/curve_arithmetic/glv.asm | 6 +++--- .../cpu/kernel/asm/curve/secp256k1/curve_add.asm | 5 ++--- evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm | 6 +++--- evm/src/cpu/kernel/interpreter.rs | 13 +++++++++++++ evm/src/cpu/kernel/opcodes.rs | 1 + evm/src/witness/gas.rs | 5 ++++- 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/glv.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/glv.asm index bd903b21..32eb5b6c 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/glv.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/glv.asm @@ -97,9 +97,9 @@ contd: underflowed: // stack: underflow, k, s*k2, N, k2 - // Compute (k-s*k2)%N. TODO: Use SUBMOD here when ready - %stack (u, k, x, N, k2) -> (N, x, k, N, k2, u) - SUB ADDMOD + // Compute (k-s*k2)%N. + %stack (u, k, x, N, k2) -> (k, x, N, k2, u) + SUBMOD %stack (k1, k2, underflow, retdest) -> (retdest, underflow, k1, k2) JUMP diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm index 9e416e66..8664b3e2 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm @@ -208,11 +208,10 @@ global secp_double: %endmacro // Modular subtraction. -// TODO: Use SUBMOD when it's ready %macro submod_secp_base // stack: x, y - %stack (x, y) -> (@SECP_BASE, y, x, @SECP_BASE) - SUB ADDMOD + %stack (x, y) -> (x, y, @SECP_BASE) + SUBMOD %endmacro // Check if (x,y) is a valid curve point. diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm index eee0dc63..26d887f2 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm @@ -84,9 +84,9 @@ global secp_glv_decompose: underflowed: // stack: underflow, k, s*k2, N, k2 - // Compute (k-s*k2)%N. TODO: Use SUBMOD here when ready - %stack (u, k, x, N, k2) -> (N, x, k, N, k2, u) - SUB ADDMOD + // Compute (k-s*k2)%N. + %stack (u, k, x, N, k2) -> (k, x, N, k2, u) + SUBMOD %stack (k1, k2, underflow, retdest) -> (retdest, underflow, k1, k2) JUMP diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 315e93f1..4ba6e9dc 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -349,6 +349,7 @@ impl<'a> Interpreter<'a> { 0x0c => self.run_addfp254(), // "ADDFP254", 0x0d => self.run_mulfp254(), // "MULFP254", 0x0e => self.run_subfp254(), // "SUBFP254", + 0x0f => self.run_submod(), // "SUBMOD", 0x10 => self.run_lt(), // "LT", 0x11 => self.run_gt(), // "GT", 0x12 => self.run_slt(), // "SLT", @@ -583,6 +584,17 @@ impl<'a> Interpreter<'a> { }); } + fn run_submod(&mut self) { + let x = U512::from(self.pop()); + let y = U512::from(self.pop()); + let z = U512::from(self.pop()); + self.push(if z.is_zero() { + U256::zero() + } else { + U256::try_from((z + x - y) % z).unwrap() + }); + } + fn run_mulmod(&mut self) { let x = self.pop(); let y = self.pop(); @@ -1220,6 +1232,7 @@ fn get_mnemonic(opcode: u8) -> &'static str { 0x0c => "ADDFP254", 0x0d => "MULFP254", 0x0e => "SUBFP254", + 0x0f => "SUBMOD", 0x10 => "LT", 0x11 => "GT", 0x12 => "SLT", diff --git a/evm/src/cpu/kernel/opcodes.rs b/evm/src/cpu/kernel/opcodes.rs index 2503a92e..b8732079 100644 --- a/evm/src/cpu/kernel/opcodes.rs +++ b/evm/src/cpu/kernel/opcodes.rs @@ -22,6 +22,7 @@ pub fn get_opcode(mnemonic: &str) -> u8 { "ADDFP254" => 0x0c, "MULFP254" => 0x0d, "SUBFP254" => 0x0e, + "SUBMOD" => 0x0f, "LT" => 0x10, "GT" => 0x11, "SLT" => 0x12, diff --git a/evm/src/witness/gas.rs b/evm/src/witness/gas.rs index aa312078..6f63a979 100644 --- a/evm/src/witness/gas.rs +++ b/evm/src/witness/gas.rs @@ -10,6 +10,7 @@ const G_HIGH: u64 = 10; pub(crate) fn gas_to_charge(op: Operation) -> u64 { use crate::arithmetic::BinaryOperator::*; + use crate::arithmetic::TernaryOperator::*; use crate::witness::operation::Operation::*; match op { Iszero => G_VERYLOW, @@ -30,7 +31,9 @@ pub(crate) fn gas_to_charge(op: Operation) -> u64 { BinaryArithmetic(AddFp254) => KERNEL_ONLY_INSTR, BinaryArithmetic(MulFp254) => KERNEL_ONLY_INSTR, BinaryArithmetic(SubFp254) => KERNEL_ONLY_INSTR, - TernaryArithmetic(_) => G_MID, + TernaryArithmetic(AddMod) => G_MID, + TernaryArithmetic(MulMod) => G_MID, + TernaryArithmetic(SubMod) => KERNEL_ONLY_INSTR, KeccakGeneral => KERNEL_ONLY_INSTR, ProverInput => KERNEL_ONLY_INSTR, Pop => G_BASE, From 6ca9970a3b38251ad89d8307cebb2f963013f0e9 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Sat, 21 Oct 2023 12:17:04 -0400 Subject: [PATCH 2/3] Alter stack to remove SWAPs for SUBMOD --- .../kernel/asm/curve/secp256k1/curve_add.asm | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm index 8664b3e2..e1d6349a 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm @@ -37,17 +37,19 @@ global secp_add_valid_points: global secp_add_valid_points_no_edge_case: // stack: x0, y0, x1, y1, retdest // Compute lambda = (y0 - y1)/(x0 - x1) + %secp_base + // stack: N, x0, y0, x1, y1, retdest + DUP5 DUP4 - // stack: y1, x0, y0, x1, y1, retdest - DUP3 - // stack: y0, y1, x0, y0, x1, y1, retdest - %submod_secp_base + // stack: y0, y1, N, x0, y0, x1, y1, retdest + SUBMOD // stack: y0 - y1, x0, y0, x1, y1, retdest + %secp_base + // stack: N, y0 - y1, x0, y0, x1, y1, retdest + DUP5 DUP4 - // stack: x1, y0 - y1, x0, y0, x1, y1, retdest - DUP3 - // stack: x0, x1, y0 - y1, x0, y0, x1, y1, retdest - %submod_secp_base + // stack: x0, x1, N, y0 - y1, x0, y0, x1, y1, retdest + SUBMOD // stack: x0 - x1, y0 - y1, x0, y0, x1, y1, retdest %moddiv_secp_base // stack: lambda, x0, y0, x1, y1, retdest @@ -93,41 +95,45 @@ secp_add_valid_points_with_lambda: // stack: lambda, x0, y0, x1, y1, retdest // Compute x2 = lambda^2 - x1 - x0 - DUP2 - // stack: x0, lambda, x0, y0, x1, y1, retdest - DUP5 - // stack: x1, x0, lambda, x0, y0, x1, y1, retdest %secp_base - // stack: N, x1, x0, lambda, x0, y0, x1, y1, retdest - DUP4 - // stack: lambda, N, x1, x0, lambda, x0, y0, x1, y1, retdest + // stack: N, lambda, x0, y0, x1, y1, retdest + DUP3 + // stack: x0, N, lambda, x0, y0, x1, y1, retdest + %secp_base + // stack: N, x0, N, lambda, x0, y0, x1, y1, retdest + DUP7 + // stack: x1, N, x0, N, lambda, x0, y0, x1, y1, retdest + %secp_base + // stack: N, x1, N, x0, N, lambda, x0, y0, x1, y1, retdest + DUP6 + // stack: lambda, N, x1, N, x0, N, lambda, x0, y0, x1, y1, retdest DUP1 - // stack: lambda, lambda, N, x1, x0, lambda, x0, y0, x1, y1, retdest + // stack: lambda, lambda, N, x1, N, x0, N, lambda, x0, y0, x1, y1, retdest MULMOD - // stack: lambda^2, x1, x0, lambda, x0, y0, x1, y1, retdest - %submod_secp_base - // stack: lambda^2 - x1, x0, lambda, x0, y0, x1, y1, retdest - %submod_secp_base + // stack: lambda^2, x1, N, x0, N, lambda, x0, y0, x1, y1, retdest + SUBMOD + // stack: lambda^2 - x1, x0, N, lambda, x0, y0, x1, y1, retdest + SUBMOD // stack: x2, lambda, x0, y0, x1, y1, retdest // Compute y2 = lambda*(x1 - x2) - y1 - %secp_base - // stack: N, x2, lambda, x0, y0, x1, y1, retdest - DUP2 - // stack: x2, N, x2, lambda, x0, y0, x1, y1, retdest - DUP7 - // stack: x1, x2, N, x2, lambda, x0, y0, x1, y1, retdest - %submod_secp_base - // stack: x1 - x2, N, x2, lambda, x0, y0, x1, y1, retdest + %secp_base %secp_base %secp_base // Pre-load moduli for incoming SUBMODs + // stack: N, N, N, x2, lambda, x0, y0, x1, y1, retdest DUP4 - // stack: lambda, x1 - x2, N, x2, lambda, x0, y0, x1, y1, retdest + // stack: x2, N, N, N, x2, lambda, x0, y0, x1, y1, retdest + DUP9 + // stack: x1, x2, N, N, N, x2, lambda, x0, y0, x1, y1, retdest + SUBMOD + // stack: x1 - x2, N, N, x2, lambda, x0, y0, x1, y1, retdest + DUP5 + // stack: lambda, x1 - x2, N, N, x2, lambda, x0, y0, x1, y1, retdest MULMOD - // stack: lambda * (x1 - x2), x2, lambda, x0, y0, x1, y1, retdest - DUP7 - // stack: y1, lambda * (x1 - x2), x2, lambda, x0, y0, x1, y1, retdest + // stack: lambda * (x1 - x2), N, x2, lambda, x0, y0, x1, y1, retdest + DUP8 + // stack: y1, lambda * (x1 - x2), N, x2, lambda, x0, y0, x1, y1, retdest SWAP1 - // stack: lambda * (x1 - x2), y1, x2, lambda, x0, y0, x1, y1, retdest - %submod_secp_base + // stack: lambda * (x1 - x2), y1, N, x2, lambda, x0, y0, x1, y1, retdest + SUBMOD // stack: y2, x2, lambda, x0, y0, x1, y1, retdest // Return x2,y2 From 07ffe4f591d651c8acdeecdeeca2fea5f8ee6f42 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Sat, 21 Oct 2023 12:33:09 -0400 Subject: [PATCH 3/3] Combine stack macros for fewer operations --- evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm b/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm index e1d6349a..43c47c50 100644 --- a/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve/secp256k1/curve_add.asm @@ -199,13 +199,13 @@ global secp_double: %jumpi(ec_double_retself) // Compute lambda = 3/2 * x0^2 / y0 - %stack (x, y, retdest) -> (x, x, @SECP_BASE, @SECP_BASE, x, y, retdest) + %stack (x, y, retdest) -> (x, x, @SECP_BASE, @SECP_BASE, x, y, x, y, retdest) MULMOD PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe19 // 3/2 in the base field MULMOD DUP3 %moddiv_secp_base - %stack (lambda, x, y, retdest) -> (lambda, x, y, x, y, retdest) + // stack: lambda, x, y, x, y, retdest %jump(secp_add_valid_points_with_lambda) // Push the order of the Secp256k1 scalar field.