From 9747343ac2b69ca67725ebae48e72f8b988c0958 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 6 Jul 2022 09:25:41 +0200 Subject: [PATCH] PR feedback --- evm/src/cpu/kernel/asm/curve_add.asm | 394 ++++++++++++--------------- evm/src/cpu/kernel/asm/curve_mul.asm | 16 +- 2 files changed, 185 insertions(+), 225 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve_add.asm b/evm/src/cpu/kernel/asm/curve_add.asm index 0f230159..6d69fea9 100644 --- a/evm/src/cpu/kernel/asm/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve_add.asm @@ -13,14 +13,40 @@ global ec_add: // stack: y0, x0, y0, x1, y1, retdest DUP2 // stack: x0, y0, x0, y0, x1, y1, retdest - ISZERO - // stack: x0==0, y0, x0, y0, x1, y1, retdest - SWAP1 - // stack: y0, x0==0, x0, y0, x1, y1, retdest - ISZERO - // stack: y0==0, x0==0, x0, y0, x1, y1, retdest + %ec_check + // stack: isValid(x0, y0), x0, y0, x1, y1, retdest + DUP5 + // stack: x1, isValid(x0, y0), x0, y0, x1, y1, retdest + DUP5 + // stack: x1, y1, isValid(x0, y0), x0, y0, x1, y1, retdest + %ec_check + // stack: isValid(x1, y1), isValid(x0, y0), x0, y0, x1, y1, retdest AND - // stack: y0==0 & x0==0, x0, y0, x1, y1, retdest + // stack: isValid(x1, y1) & isValid(x0, y0), x0, y0, x1, y1, retdest + PUSH ec_add_valid_points + // stack: ec_add_valid_points, isValid(x1, y1) & isValid(x0, y0), x0, y0, x1, y1, retdest + JUMPI + // stack: x0, y0, x1, y1, retdest + POP + // stack: y0, x1, y1, retdest + POP + // stack: x1, y1, retdest + POP + // stack: y1, retdest + POP + // stack: retdest + %ec_invalid_input + +// Assumption: (x0,y0) and (x1,y1) are valid points. +global ec_add_valid_points: + JUMPDEST + // stack: x0, y0, x1, y1, retdest + DUP2 + // stack: y0, x0, y0, x1, y1, retdest + DUP2 + // stack: x0, y0, x0, y0, x1, y1, retdest + %ec_isidentity + // stack: (x0,y0)==(0,0), x0, y0, x1, y1, retdest PUSH ec_add_first_zero // stack: ec_add_first_zero, y0==0 & x0==0, x0, y0, x1, y1, retdest JUMPI @@ -29,165 +55,12 @@ global ec_add: // stack: y1, x0, y0, x1, y1, retdest DUP4 // stack: x1, y1, x0, y0, x1, y1, retdest - ISZERO - // stack: x1==0, y1, x0, y0, x1, y1, retdest - SWAP1 - // stack: y1, x1==0, x0, y0, x1, y1, retdest - ISZERO - // stack: y1==0, x1==0, x0, y0, x1, y1, retdest - AND - // stack: y1==0 & x1==0, x0, y0, x1, y1, retdest + %ec_isidentity + // stack: (x1,y1)==(0,0), x0, y0, x1, y1, retdest PUSH ec_add_snd_zero // stack: ec_add_snd_zero, y1==0 & x1==0, x0, y0, x1, y1, retdest JUMPI // stack: x0, y0, x1, y1, retdest - DUP4 - // stack: y1, x0, y0, x1, y1, retdest - DUP4 - // stack: x1, y1, x0, y0, x1, y1, retdest - DUP4 - // stack: y0, x1, y1, x0, y0, x1, y1, retdest - DUP4 - // stack: x0, y0, x1, y1, x0, y0, x1, y1, retdest - %ec_check - // stack: isValid(x0, y0), x1, y1, x0, y0, x1, y1, retdest - PUSH ec_add_valid_first_point - // stack: ec_add_valid_first_point, isValid(x0, y0), x1, y1, x0, y0, x1, y1, retdest - JUMPI - // stack: x1, y1, x0, y0, x1, y1, retdest - POP - // stack: y1, x0, y0, x1, y1, retdest - POP - // stack: x0, y0, x1, y1, retdest - POP - // stack: y0, x1, y1, retdest - POP - // stack: x1, y1, retdest - POP - // stack: y1, retdest - POP - // stack: retdest - JUMP - -// Assumption: (x0,y0) == (0,0) -ec_add_first_zero: - JUMPDEST - // stack: x0, y0, x1, y1, retdest - POP - // stack: y0, x1, y1, retdest - POP - // stack: x1, y1, retdest - DUP2 - // stack: y1, x1, y1, retdest - DUP2 - // stack: x1, y1, x1, y1, retdest - ISZERO - // stack: x1==0, y1, x1, y1, retdest - SWAP1 - // stack: y1, x1==0, x1, y1, retdest - ISZERO - // stack: y1==0, x1==0, x1, y1, retdest - AND - // stack: y1==0 & x1==0, x1, y1, retdest - PUSH ret_zero - // stack: ret_zero, y1==0 & x1==0, x1, y1, retdest - JUMPI - // stack: x1, y1, retdest - DUP2 - // stack: y1, x1, y1, retdest - DUP2 - // stack: x1, y1, x1, y1, retdest - %ec_check - // stack: isValid(x1, y1), x1, y1, retdest - PUSH ec_noop - // stack: ec_noop, isValid(x1, y1), x1, y1, retdest - JUMPI - // stack: x1, y1, retdest - POP - // stack: y1, retdest - POP - // stack: retdest - JUMP - -// Assumption: (x1,y1) == (0,0) and (x0,y0) != (0,0) -ec_add_snd_zero: - JUMPDEST - // stack: x0, y0, x1, y1, retdest - SWAP2 - // stack: x1, y0, x0, y1, retdest - POP - // stack: y0, x0, y1, retdest - SWAP2 - // stack: y1, x0, y0, retdest - POP - // stack: x0, y0, retdest - DUP2 - // stack: y0, x0, y0, retdest - DUP2 - // stack: x0, y0, x0, y0, retdest - %ec_check - // stack: isValid(x0, y0), x0, y0, retdest - PUSH ec_noop - // stack: ec_noop, isValid(x0, y0), x0, y0, retdest - JUMPI - // stack: x0, y0, retdest - POP - // stack: y0, retdest - POP - // stack: retdest - JUMP - -ec_noop: - JUMPDEST - // x, y, retdest - SWAP1 - // y, x, retdest - SWAP2 - // retdest, x, y - JUMP - -ret_zero: - JUMPDEST - // stack: x, y, retdest - POP - // stack: y, retdest - POP - // stack: retdest - PUSH 0 - // stack: 0, retdest - PUSH 0 - // stack: 0, 0, retdest - SWAP2 - // stack: 0, retdest, 0 - SWAP1 - // stack: retdest, 0, 0 - JUMP - - -// Assumption: (x0,y0) is a valid point. -ec_add_valid_first_point: - JUMPDEST - // stack: x1, y1, x0, y0, x1, y1, retdest - %ec_check - // stack: isValid(x1, y1), x0, y0, x1, y1, retdest - PUSH ec_add_valid_points - // stack: ec_add_valid_points, isValid(x1, y1), x0, y0, x1, y1, retdest - JUMPI - // stack: x0, y0, x1, y1, retdest - POP - // stack: y0, x1, y1, retdest - POP - // stack: x1, y1, retdest - POP - // stack: y1, retdest - POP - // stack: retdest - JUMP - -// Assumption: (x0,y0) and (x1,y1) are valid points. -global ec_add_valid_points: - JUMPDEST - // stack: x0, y0, x1, y1, retdest DUP3 // stack: x1, x0, y0, x1, y1, retdest DUP2 @@ -216,6 +89,63 @@ global ec_add_valid_points: // stack: ec_add_valid_points_with_lambda, lambda, x0, y0, x1, y1, retdest JUMP +// Assumption: (x0,y0) == (0,0) +ec_add_first_zero: + JUMPDEST + // stack: x0, y0, x1, y1, retdest + POP + // stack: y0, x1, y1, retdest + POP + // stack: x1, y1, retdest + DUP2 + // stack: y1, x1, y1, retdest + DUP2 + // stack: x1, y1, x1, y1, retdest + %ec_isidentity + // stack: (x1,y1)==(0,0), x1, y1, retdest + PUSH ret_zero + // stack: ret_zero, (x1,y1)==(0,0), x1, y1, retdest + JUMPI + // stack: x1, y1, retdest + SWAP1 + // stack: y1, x1, retdest + SWAP2 + // stack: retdest, x1, y1 + JUMP + +// Assumption: (x1,y1) == (0,0) and (x0,y0) != (0,0) +ec_add_snd_zero: + JUMPDEST + // stack: x0, y0, x1, y1, retdest + SWAP2 + // stack: x1, y0, x0, y1, retdest + POP + // stack: y0, x0, y1, retdest + SWAP2 + // stack: y1, x0, y0, retdest + POP + // stack: x0, y0, retdest + SWAP1 + // stack: y0, x0, retdest + SWAP2 + // stack: retdest, x0, y0 + JUMP + +ret_zero: + JUMPDEST + // stack: x, y, retdest + POP + // stack: y, retdest + POP + // stack: retdest + PUSH 0 + // stack: 0, retdest + PUSH 0 + // stack: 0, 0, retdest + SWAP2 + // stack: retdest, 0, 0 + JUMP + ec_add_valid_points_with_lambda: JUMPDEST // stack: lambda, x0, y0, x1, y1, retdest @@ -223,7 +153,7 @@ ec_add_valid_points_with_lambda: // stack: x0, lambda, x0, y0, x1, y1, retdest DUP5 // stack: x1, x0, lambda, x0, y0, x1, y1, retdest - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, x1, x0, lambda, x0, y0, x1, y1, retdest DUP4 // stack: lambda, N, x1, x0, lambda, x0, y0, x1, y1, retdest @@ -235,7 +165,7 @@ ec_add_valid_points_with_lambda: // stack: lambda^2 - x1, x0, lambda, x0, y0, x1, y1, retdest %submod // stack: x2, lambda, x0, y0, x1, y1, retdest - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, x2, lambda, x0, y0, x1, y1, retdest DUP2 // stack: x2, N, x2, lambda, x0, y0, x1, y1, retdest @@ -275,7 +205,7 @@ ec_add_valid_points_with_lambda: ec_add_equal_first_coord: JUMPDEST // stack: x0, y0, x1, y1, retdest with x0 == x1 - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, x0, y0, x1, y1, retdest DUP3 // stack: y0, N, x0, y0, x1, y1, retdest @@ -291,16 +221,8 @@ ec_add_equal_first_coord: // stack: y0, x1, y1, retdest POP // stack: x1, y1, retdest - POP - // stack: y1, retdest - POP - // stack: retdest - PUSH 0 - // stack: 0, retdest - PUSH 0 - // stack: 0, 0, retdest - SWAP2 - // stack: retdest, 0, 0 + PUSH ret_zero + // stack: ret_zero, x1, y1, retdest JUMP @@ -308,9 +230,9 @@ ec_add_equal_first_coord: ec_add_equal_points: JUMPDEST // stack: x0, y0, x1, y1, retdest - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, x0, y0, x1, y1, retdest - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, N, x0, y0, x1, y1, retdest DUP3 // stack: x0, N, N, x0, y0, x1, y1, retdest @@ -342,17 +264,22 @@ global ec_double: // stack: ec_add_equal_points, x0, y0, x0, y0, retdest JUMP +// Push the order of the BN254 base field. +%macro bn_base + PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 +%endmacro + // Assumption: x, y < N and 2N < 2^256. // Note: Doesn't hold for Secp256k1 base field. %macro submod // stack: x, y - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, x, y ADD // stack: N + x, y // Doesn't overflow since 2N < 2^256 SUB // stack: N + x - y // Doesn't underflow since y < N - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + %bn_base // stack: N, N + x - y SWAP1 // stack: N + x - y, N @@ -360,58 +287,97 @@ global ec_double: // stack: (N + x - y) % N = (x-y) % N %endmacro +// Check if (x,y) is a valid curve point. +// Puts y^2 % N == (x^3 + 3) % N & (x < N) & (y < N) || (x,y)==(0,0) on top of the stack. %macro ec_check - // stack: x0, y0 - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // stack: N, x0, y0 + // stack: x, y + %bn_base + // stack: N, x, y DUP2 - // stack: x0, N, x0, y0 + // stack: x, N, x, y LT - // stack: x0 < N, x0, y0 - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // stack: N, x0 < N, x0, y0 + // stack: x < N, x, y + %bn_base + // stack: N, x < N, x, y DUP4 - // stack: y0, N, x0 < N, x0, y0 + // stack: y, N, x < N, x, y LT - // stack: y0 < N, x0 < N, x0, y0 + // stack: y < N, x < N, x, y AND - // stack: (y0 < N) & (x0 < N), x0, y0 + // stack: (y < N) & (x < N), x, y SWAP2 - // stack: y0, x0, (y0 < N) & (x0 < N), x0 + // stack: y, x, (y < N) & (x < N), x SWAP1 - // stack: x0, y0, (y0 < N) & (x0 < N) - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // stack: N, x0, y0, b - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // stack: N, N, x0, y0, b - SWAP2 - // stack: x0, N, N, y0, b - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // stack: N, x0, N, N, y0, b + // stack: x, y, (y < N) & (x < N) + %bn_base + // stack: N, x, y, b + %bn_base + // stack: N, N, x, y, b + DUP3 + // stack: x, N, N, x, y, b + %bn_base + // stack: N, x, N, N, x, y, b DUP2 - // stack: x0, N, x0, N, N, y0, b + // stack: x, N, x, N, N, x, y, b DUP1 - // stack: x0, x0, N, x0, N, N, y0, b + // stack: x, x, N, x, N, N, x, y, b MULMOD - // stack: x0^2 % N, x0, N, N, y0, b + // stack: x^2 % N, x, N, N, x, y, b MULMOD - // stack: x0^3 % N, N, y0, b + // stack: x^3 % N, N, x, y, b PUSH 3 - // stack: 3, x0^3 % N, N, y0, b + // stack: 3, x^3 % N, N, x, y, b ADDMOD - // stack: (x0^3 + 3) % N, y0, b + // stack: (x^3 + 3) % N, x, y, b + DUP3 + // stack: y, (x^3 + 3) % N, x, y, b + %bn_base + // stack: N, y, (x^3 + 3) % N, x, y, b SWAP1 - // stack: y0, (x0^3 + 3) % N, b - PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - // stack: N, y0, (x0^3 + 3) % N, b - SWAP1 - // stack: y0, N, (x0^3 + 3) % N, b + // stack: y, N, (x^3 + 3) % N, x, y, b DUP1 - // stack: y0, y0, N, (x0^3 + 3) % N, b + // stack: y, y, N, (x^3 + 3) % N, x, y, b MULMOD - // stack: y0^2 % N, (x0^3 + 3) % N, b + // stack: y^2 % N, (x^3 + 3) % N, x, y, b EQ - // stack: y0^2 % N == (x0^3 + 3) % N, b + // stack: y^2 % N == (x^3 + 3) % N, x, y, b + SWAP2 + // stack: y, x, y^2 % N == (x^3 + 3) % N, b + ISZERO + // stack: y==0, x, y^2 % N == (x^3 + 3) % N, b + SWAP1 + // stack: x, y==0, y^2 % N == (x^3 + 3) % N, b + ISZERO + // stack: x==0, y==0, y^2 % N == (x^3 + 3) % N, b AND - // stack: y0^2 % N == (x0^3 + 3) % N & (x < N) & (y < N) + // stack: (x,y)==(0,0), y^2 % N == (x^3 + 3) % N, b + SWAP2 + // stack: b, y^2 % N == (x^3 + 3) % N, (x,y)==(0,0) + AND + // stack: y^2 % N == (x^3 + 3) % N & (x < N) & (y < N), (x,y)==(0,0) + OR + // stack: y^2 % N == (x^3 + 3) % N & (x < N) & (y < N) || (x,y)==(0,0) %endmacro + +%macro ec_isidentity + // stack: x, y + ISZERO + // stack: x==0, y + SWAP1 + // stack: y, x==0 + ISZERO + // stack: y==0, x==0 + AND + // stack: y==0 & x==0 +%endmacro + +%macro ec_invalid_input + // stack: retdest + PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // stack: u256::MAX, retdest + PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + // stack: u256::MAX, u256::MAX, retdest + SWAP2 + // stack: retdest, u256::MAX, u256::MAX + JUMP +%endmacro \ No newline at end of file diff --git a/evm/src/cpu/kernel/asm/curve_mul.asm b/evm/src/cpu/kernel/asm/curve_mul.asm index 440ebe8b..52e384d5 100644 --- a/evm/src/cpu/kernel/asm/curve_mul.asm +++ b/evm/src/cpu/kernel/asm/curve_mul.asm @@ -10,14 +10,8 @@ global ec_mul: // stack: y, x, y, s, retdest DUP2 // stack: x, y, x, y, s, retdest - ISZERO - // stack: x==0, y, x, y, s, retdest - SWAP1 - // stack: y, x==0, x, y, s, retdest - ISZERO - // stack: y==0, x==0, x, y, s, retdest - AND - // stack: y==0 & x==0, x, y, s, retdest + %ec_isidentity + // stack: (x,y)==(0,0), x, y, s, retdest PUSH ret_zero // stack: ret_zero, y==0 & x==0, x, y, s, retdest JUMPI @@ -38,7 +32,7 @@ global ec_mul: // stack: s, retdest POP // stack: retdest - JUMP + %ec_invalid_input // Same algorithm as in `exp.asm` ec_mul_valid_point: @@ -131,8 +125,8 @@ recursion_return: odd_scalar: JUMPDEST // stack: x', y', x, y, retdest - PUSH ec_add - // stack: ec_add, x', y', x, y, retdest + PUSH ec_add_valid_points + // stack: ec_add_valid_points, x', y', x, y, retdest JUMP ret_zero: