mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 06:13:07 +00:00
Merge branch 'main' into add_priviledged_opcodes
This commit is contained in:
commit
d53804c66f
@ -21,9 +21,11 @@ rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
rlp = "0.5.1"
|
||||
keccak-rust = { git = "https://github.com/npwardberkeley/keccak-rust" }
|
||||
keccak-hash = "0.9.0"
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.3.4"
|
||||
hex = "0.4.3"
|
||||
|
||||
[features]
|
||||
asmtools = ["hex"]
|
||||
|
||||
@ -28,6 +28,12 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/curve_mul.asm"),
|
||||
include_str!("asm/curve_add.asm"),
|
||||
include_str!("asm/moddiv.asm"),
|
||||
include_str!("asm/secp256k1/curve_mul.asm"),
|
||||
include_str!("asm/secp256k1/curve_add.asm"),
|
||||
include_str!("asm/secp256k1/moddiv.asm"),
|
||||
include_str!("asm/secp256k1/lift_x.asm"),
|
||||
include_str!("asm/secp256k1/inverse_scalar.asm"),
|
||||
include_str!("asm/ecrecover.asm"),
|
||||
include_str!("asm/storage_read.asm"),
|
||||
include_str!("asm/storage_write.asm"),
|
||||
];
|
||||
@ -38,15 +44,9 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use log::debug;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
|
||||
#[test]
|
||||
fn make_kernel() {
|
||||
@ -58,171 +58,4 @@ mod tests {
|
||||
let kernel = combined_kernel();
|
||||
debug!("Total kernel size: {} bytes", kernel.code.len());
|
||||
}
|
||||
|
||||
fn u256ify<'a>(hexes: impl IntoIterator<Item = &'a str>) -> Result<Vec<U256>> {
|
||||
Ok(hexes
|
||||
.into_iter()
|
||||
.map(U256::from_str)
|
||||
.collect::<Result<Vec<_>, _>>()?)
|
||||
}
|
||||
#[test]
|
||||
fn test_exp() -> Result<()> {
|
||||
// Make sure we can parse and assemble the entire kernel.
|
||||
let kernel = combined_kernel();
|
||||
let exp = kernel.global_labels["exp"];
|
||||
let mut rng = thread_rng();
|
||||
let a = U256([0; 4].map(|_| rng.gen()));
|
||||
let b = U256([0; 4].map(|_| rng.gen()));
|
||||
|
||||
// Random input
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, a];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack);
|
||||
let initial_stack = vec![b, a];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack);
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
// 0 base
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, U256::zero()];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack);
|
||||
let initial_stack = vec![b, U256::zero()];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack);
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
// 0 exponent
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, U256::zero(), a];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack);
|
||||
let initial_stack = vec![U256::zero(), a];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack);
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ec_ops() -> Result<()> {
|
||||
// Make sure we can parse and assemble the entire kernel.
|
||||
let kernel = combined_kernel();
|
||||
let ec_add = kernel.global_labels["ec_add"];
|
||||
let ec_double = kernel.global_labels["ec_double"];
|
||||
let ec_mul = kernel.global_labels["ec_mul"];
|
||||
let identity = ("0x0", "0x0");
|
||||
let invalid = ("0x0", "0x3"); // Not on curve
|
||||
let point0 = (
|
||||
"0x1feee7ec986e198890cb83be8b8ba09ee953b3f149db6d9bfdaa5c308a33e58d",
|
||||
"0x2051cc9a9edd46231604fd88f351e95ec72a285be93e289ac59cb48561efb2c6",
|
||||
);
|
||||
let point1 = (
|
||||
"0x15b64d0a5f329fb672029298be8050f444626e6de11903caffa74b388075be1b",
|
||||
"0x2d9e07340bd5cd7b70687b98f2500ff930a89a30d7b6a3e04b1b4d345319d234",
|
||||
);
|
||||
// point2 = point0 + point1
|
||||
let point2 = (
|
||||
"0x18659c0e0a8fedcb8747cf463fc7cfa05f667d84e771d0a9521fc1a550688f0c",
|
||||
"0x283ed10b42703e187e7a808aeb45c6b457bc4cc7d704e53b3348a1e3b0bfa55b",
|
||||
);
|
||||
// point3 = 2 * point0
|
||||
let point3 = (
|
||||
"0x17da2b7b1a01c8dfdf0f5a6415833c7d755d219aa7e2c4cd0ac83d87d0ca4217",
|
||||
"0xc9ace9de14aac8114541b50c19320eb40f0eeac3621526d9e34dbcf4c3a6c0f",
|
||||
);
|
||||
let s = "0xabb2a34c0e7956cfe6cef9ddb7e810c45ea19a6ebadd79c21959af09f5ba480a";
|
||||
// point4 = s * point0
|
||||
let point4 = (
|
||||
"0xe519344959cc17021fe98878f947f5c1b1675325533a620c1684cfa6367e6c0",
|
||||
"0x7496a7575b0b6a821e19ce780ecc3e0b156e605327798693defeb9f265b7a6f",
|
||||
);
|
||||
|
||||
// Standard addition #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
// Standard addition #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
|
||||
// Standard doubling #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_double, initial_stack);
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack);
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
|
||||
// Addition with identity #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #3
|
||||
let initial_stack =
|
||||
u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Addition with invalid point(s) #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
|
||||
// Scalar multiplication #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack);
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
// Scalar multiplication #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack);
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack);
|
||||
assert_eq!(stack, u256ify([point0.1, point0.0])?);
|
||||
// Scalar multiplication #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack);
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #5
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack);
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
|
||||
// Multiple calls
|
||||
let ec_mul_hex = format!("0x{:x}", ec_mul);
|
||||
let initial_stack = u256ify([
|
||||
"0xdeadbeef",
|
||||
s,
|
||||
&ec_mul_hex,
|
||||
identity.1,
|
||||
identity.0,
|
||||
point0.1,
|
||||
point0.0,
|
||||
])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack);
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +47,26 @@
|
||||
// stack: (pred != 0) * nz + (pred == 0) * z
|
||||
%endmacro
|
||||
|
||||
// If pred, yields z; otherwise, yields nz
|
||||
// Assumes pred is boolean (either 0 or 1).
|
||||
%macro select_bool
|
||||
// stack: pred, nz, z
|
||||
dup1
|
||||
// stack: pred, pred, nz, z
|
||||
iszero
|
||||
// stack: notpred, pred, nz, z
|
||||
swap3
|
||||
// stack: z, pred, nz, notpred
|
||||
mul
|
||||
// stack: pred * z, nz, notpred
|
||||
swap2
|
||||
// stack: notpred, nz, pred * z
|
||||
mul
|
||||
// stack: notpred * nz, pred * z
|
||||
add
|
||||
// stack: notpred * nz + pred * z
|
||||
%endmacro
|
||||
|
||||
%macro square
|
||||
// stack: x
|
||||
dup1
|
||||
|
||||
@ -14,7 +14,7 @@ global ec_mul:
|
||||
// stack: x, y, x, y, s, retdest
|
||||
%ec_isidentity
|
||||
// stack: (x,y)==(0,0), x, y, s, retdest
|
||||
%jumpi(ret_zero)
|
||||
%jumpi(ret_zero_ec_mul)
|
||||
// stack: x, y, s, retdest
|
||||
DUP2
|
||||
// stack: y, x, y, s, retdest
|
||||
@ -35,7 +35,7 @@ ec_mul_valid_point:
|
||||
// stack: s, x, y, s, retdest
|
||||
%jumpi(step_case)
|
||||
// stack: x, y, s, retdest
|
||||
%jump(ret_zero)
|
||||
%jump(ret_zero_ec_mul)
|
||||
|
||||
step_case:
|
||||
JUMPDEST
|
||||
@ -100,7 +100,7 @@ odd_scalar:
|
||||
// stack: x', y', x, y, retdest
|
||||
%jump(ec_add_valid_points)
|
||||
|
||||
ret_zero:
|
||||
global ret_zero_ec_mul:
|
||||
JUMPDEST
|
||||
// stack: x, y, s, retdest
|
||||
%pop3
|
||||
|
||||
205
evm/src/cpu/kernel/asm/ecrecover.asm
Normal file
205
evm/src/cpu/kernel/asm/ecrecover.asm
Normal file
@ -0,0 +1,205 @@
|
||||
// ecrecover precompile.
|
||||
global ecrecover:
|
||||
JUMPDEST
|
||||
// stack: hash, v, r, s, retdest
|
||||
|
||||
// Check if inputs are valid.
|
||||
%ecrecover_input_check
|
||||
// stack: isValid(v,r,s), hash, v, r, s, retdest
|
||||
|
||||
// Lift r to an elliptic curve point if possible.
|
||||
SWAP2
|
||||
// stack: v, hash, isValid(v,r,s), r, s, retdest
|
||||
DUP4
|
||||
// stack: r, v, hash, isValid(v,r,s), r, s, retdest
|
||||
|
||||
// Compute v-27 which gives the parity of the y-coordinate of the lifted point.
|
||||
SWAP1
|
||||
// stack: v, r, hash, isValid(v,r,s), r, s, retdest
|
||||
PUSH 27
|
||||
// stack: 27, v, r, hash, isValid(v,r,s), r, s, retdest
|
||||
SWAP1
|
||||
// stack: v, 27, r, hash, isValid(v,r,s), r, s, retdest
|
||||
SUB
|
||||
// stack: v - 27, r, hash, isValid(v,r,s), r, s, retdest
|
||||
SWAP1
|
||||
// stack: r, v - 27, hash, isValid(v,r,s), r, s, retdest
|
||||
%secp_lift_x
|
||||
// stack: y, sqrtOk, hash, isValid(v,r,s), r, s, retdest
|
||||
|
||||
// If inputs are invalid or lifting fails, abort.
|
||||
SWAP3
|
||||
// stack: isValid(v,r,s), sqrtOk, hash, y, r, s, retdest
|
||||
AND
|
||||
// stack: isValid(v,r,s) & sqrtOk, hash, y, r, s, retdest
|
||||
%jumpi(ecrecover_valid_input)
|
||||
// stack: hash, y, r, s, retdest
|
||||
%pop4
|
||||
// stack: retdest
|
||||
%ecrecover_invalid_input
|
||||
|
||||
// ecrecover precompile.
|
||||
// Assumption: Inputs are valid.
|
||||
// Pseudo-code:
|
||||
// let P = lift_x(r, recovery_id);
|
||||
// let r_inv = r.inverse();
|
||||
// let u1 = s * r_inv;
|
||||
// let u2 = -hash * r_inv;
|
||||
// return u1*P + u2*GENERATOR;
|
||||
ecrecover_valid_input:
|
||||
JUMPDEST
|
||||
// stack: hash, y, r, s, retdest
|
||||
|
||||
// Compute u1 = s * r^(-1)
|
||||
SWAP1
|
||||
// stack: y, hash, r, s, retdest
|
||||
DUP3
|
||||
// stack: r, y, hash, x, s, retdest (r=x)
|
||||
%inverse_secp_scalar
|
||||
// stack: r^(-1), y, hash, x, s, retdest
|
||||
DUP1
|
||||
// stack: r^(-1), r^(-1), y, hash, x, s, retdest
|
||||
SWAP5
|
||||
// stack: s, r^(-1), y, hash, x, r^(-1), retdest
|
||||
%mulmodn_secp_scalar
|
||||
// stack: u1, y, hash, x, r^(-1), retdest
|
||||
|
||||
|
||||
// Compute (X,Y) = u1 * (x,y)
|
||||
PUSH ecrecover_with_first_point
|
||||
// stack: ecrecover_with_first_point, u1, y, hash, x, r^(-1), retdest
|
||||
SWAP1
|
||||
// stack: u1, ecrecover_with_first_point, y, hash, x, r^(-1), retdest
|
||||
SWAP2
|
||||
// stack: y, ecrecover_with_first_point, u1, hash, x, r^(-1), retdest
|
||||
SWAP1
|
||||
// stack: ecrecover_with_first_point, y, u1, hash, x, r^(-1), retdest
|
||||
SWAP3
|
||||
// stack: hash, y, u1, ecrecover_with_first_point, x, r^(-1), retdest
|
||||
SWAP4
|
||||
// stack: x, y, u1, ecrecover_with_first_point, hash, r^(-1), retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
|
||||
// ecrecover precompile.
|
||||
// Assumption: (X,Y) = u1 * P. Result is (X,Y) + u2*GENERATOR
|
||||
ecrecover_with_first_point:
|
||||
JUMPDEST
|
||||
// stack: X, Y, hash, r^(-1), retdest
|
||||
%secp_scalar
|
||||
// stack: p, X, Y, hash, r^(-1), retdest
|
||||
SWAP1
|
||||
// stack: X, p, Y, hash, r^(-1), retdest
|
||||
SWAP4
|
||||
// stack: r^(-1), p, Y, hash, X, retdest
|
||||
SWAP2
|
||||
// stack: Y, p, r^(-1), hash, X, retdest
|
||||
SWAP3
|
||||
// stack: hash, p, r^(-1), Y, X, retdest
|
||||
|
||||
// Compute u2 = -hash * r^(-1)
|
||||
MOD
|
||||
// stack: hash%p, r^(-1), Y, X, retdest
|
||||
%secp_scalar
|
||||
// stack: p, hash%p, r^(-1), Y, X, retdest
|
||||
SUB
|
||||
// stack: -hash, r^(-1), Y, X, retdest
|
||||
%mulmodn_secp_scalar
|
||||
// stack: u2, Y, X, retdest
|
||||
|
||||
// Compute u2 * GENERATOR and chain the call to `ec_mul` with a call to `ec_add` to compute PUBKEY = (X,Y) + u2 * GENERATOR,
|
||||
// and a call to `final_hashing` to get the final result `SHA3(PUBKEY)[-20:]`.
|
||||
PUSH final_hashing
|
||||
// stack: final_hashing, u2, Y, X, retdest
|
||||
SWAP3
|
||||
// stack: X, u2, Y, final_hashing, retdest
|
||||
PUSH ec_add_valid_points_secp
|
||||
// stack: ec_add_valid_points_secp, X, u2, Y, final_hashing, retdest
|
||||
SWAP1
|
||||
// stack: X, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
PUSH 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 // x-coordinate of generator
|
||||
// stack: Gx, X, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
SWAP1
|
||||
// stack: X, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
PUSH 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 // y-coordinate of generator
|
||||
// stack: Gy, X, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
SWAP1
|
||||
// stack: X, Gy, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest
|
||||
SWAP4
|
||||
// stack: u2, Gy, Gx, ec_add_valid_points_secp, X, Y, final_hashing, retdest
|
||||
SWAP2
|
||||
// stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, final_hashing, retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
|
||||
// TODO
|
||||
final_hashing:
|
||||
JUMPDEST
|
||||
PUSH 0xdeadbeef
|
||||
JUMP
|
||||
|
||||
// Check if v, r, and s are in correct form.
|
||||
// Returns r < N & r!=0 & s < N & s!=0 & (v==28 || v==27).
|
||||
%macro ecrecover_input_check
|
||||
// stack: hash, v, r, s, retdest
|
||||
DUP2
|
||||
// stack: v, hash, v, r, s, retdest
|
||||
PUSH 27
|
||||
// stack: 27, v, hash, v, r, s, retdest
|
||||
EQ
|
||||
// stack: v==27, hash, v, r, s, retdest
|
||||
DUP3
|
||||
// stack: v, v==27, hash, v, r, s, retdest
|
||||
PUSH 28
|
||||
// stack: 28, v, v==27, hash, v, r, s, retdest
|
||||
EQ
|
||||
// stack: v==28, v==27, hash, v, r, s, retdest
|
||||
OR
|
||||
// stack: (v==28 || v==27), hash, v, r, s, retdest
|
||||
DUP5
|
||||
// stack: s, (v==28 || v==27), hash, v, r, s, retdest
|
||||
%secp_is_out_of_bounds
|
||||
// stack: (s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest
|
||||
DUP5
|
||||
// stack: r, (s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest
|
||||
%secp_is_out_of_bounds
|
||||
// stack: (r >= N || r==0), (s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest
|
||||
OR
|
||||
// stack: (r >= N || r==0 || s >= N || s==0), (v==28 || v==27), hash, v, r, s, retdest
|
||||
ISZERO
|
||||
// stack: (r < N & r!=0 & s < N & s!=0), (v==28 || v==27), hash, v, r, s, retdest
|
||||
AND
|
||||
// stack: r < N & r!=0 & s < N & s!=0 & (v==28 || v==27), hash, v, r, s, retdest
|
||||
%endmacro
|
||||
|
||||
%macro secp_is_out_of_bounds
|
||||
// stack: x
|
||||
DUP1
|
||||
// stack: x, x
|
||||
ISZERO
|
||||
// stack: x==0, x
|
||||
SWAP1
|
||||
// stack: x, x==0
|
||||
%secp_scalar
|
||||
// stack: N, x, x==0
|
||||
SWAP1
|
||||
// stack: x, N, x==0
|
||||
LT
|
||||
// stack: x < N, x==0
|
||||
ISZERO
|
||||
// stack: x >= N, x==0
|
||||
OR
|
||||
// stack: x >= N || x==0
|
||||
%endmacro
|
||||
|
||||
%macro secp_scalar
|
||||
PUSH 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
|
||||
%endmacro
|
||||
|
||||
// Return u256::MAX which is used to indicate the input was invalid.
|
||||
%macro ecrecover_invalid_input
|
||||
// stack: retdest
|
||||
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
// stack: u256::MAX, retdest
|
||||
SWAP1
|
||||
// stack: retdest, u256::MAX
|
||||
JUMP
|
||||
%endmacro
|
||||
310
evm/src/cpu/kernel/asm/secp256k1/curve_add.asm
Normal file
310
evm/src/cpu/kernel/asm/secp256k1/curve_add.asm
Normal file
@ -0,0 +1,310 @@
|
||||
// #define N 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 // Secp256k1 scalar field order
|
||||
|
||||
// Secp256k1 elliptic curve addition.
|
||||
// Assumption: (x0,y0) and (x1,y1) are valid points.
|
||||
global ec_add_valid_points_secp:
|
||||
JUMPDEST
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Check if the first point is the identity.
|
||||
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
|
||||
%jumpi(ec_add_first_zero)
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Check if the first point is the identity.
|
||||
DUP4
|
||||
// stack: y1, x0, y0, x1, y1, retdest
|
||||
DUP4
|
||||
// stack: x1, y1, x0, y0, x1, y1, retdest
|
||||
%ec_isidentity
|
||||
// stack: (x1,y1)==(0,0), x0, y0, x1, y1, retdest
|
||||
%jumpi(ec_add_snd_zero)
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Check if both points have the same x-coordinate.
|
||||
DUP3
|
||||
// stack: x1, x0, y0, x1, y1, retdest
|
||||
DUP2
|
||||
// stack: x0, x1, x0, y0, x1, y1, retdest
|
||||
EQ
|
||||
// stack: x0 == x1, x0, y0, x1, y1, retdest
|
||||
%jumpi(ec_add_equal_first_coord)
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Otherwise, we can use the standard formula.
|
||||
// Compute lambda = (y0 - y1)/(x0 - x1)
|
||||
DUP4
|
||||
// stack: y1, x0, y0, x1, y1, retdest
|
||||
DUP3
|
||||
// stack: y0, y1, x0, y0, x1, y1, retdest
|
||||
%submod_secp_base
|
||||
// stack: y0 - y1, x0, y0, x1, y1, retdest
|
||||
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, y0 - y1, x0, y0, x1, y1, retdest
|
||||
%moddiv_secp_base
|
||||
// stack: lambda, x0, y0, x1, y1, retdest
|
||||
%jump(ec_add_valid_points_with_lambda)
|
||||
|
||||
// Secp256k1 elliptic curve addition.
|
||||
// Assumption: (x0,y0) == (0,0)
|
||||
ec_add_first_zero:
|
||||
JUMPDEST
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Just return (x1,y1)
|
||||
%pop2
|
||||
// stack: x1, y1, retdest
|
||||
SWAP1
|
||||
// stack: y1, x1, retdest
|
||||
SWAP2
|
||||
// stack: retdest, x1, y1
|
||||
JUMP
|
||||
|
||||
// Secp256k1 elliptic curve addition.
|
||||
// Assumption: (x1,y1) == (0,0)
|
||||
ec_add_snd_zero:
|
||||
JUMPDEST
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Just return (x1,y1)
|
||||
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
|
||||
|
||||
// Secp256k1 elliptic curve addition.
|
||||
// Assumption: lambda = (y0 - y1)/(x0 - x1)
|
||||
ec_add_valid_points_with_lambda:
|
||||
JUMPDEST
|
||||
// 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
|
||||
DUP1
|
||||
// stack: lambda, lambda, N, x1, x0, 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: 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
|
||||
DUP4
|
||||
// stack: lambda, x1 - x2, 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
|
||||
SWAP1
|
||||
// stack: lambda * (x1 - x2), y1, x2, lambda, x0, y0, x1, y1, retdest
|
||||
%submod_secp_base
|
||||
// stack: y2, x2, lambda, x0, y0, x1, y1, retdest
|
||||
|
||||
// Return x2,y2
|
||||
SWAP5
|
||||
// stack: x1, x2, lambda, x0, y0, y2, y1, retdest
|
||||
POP
|
||||
// stack: x2, lambda, x0, y0, y2, y1, retdest
|
||||
SWAP5
|
||||
// stack: y1, lambda, x0, y0, y2, x2, retdest
|
||||
%pop4
|
||||
// stack: y2, x2, retdest
|
||||
SWAP2
|
||||
// stack: retdest, x2, y2
|
||||
JUMP
|
||||
|
||||
// Secp256k1 elliptic curve addition.
|
||||
// Assumption: (x0,y0) and (x1,y1) are valid points and x0 == x1
|
||||
ec_add_equal_first_coord:
|
||||
JUMPDEST
|
||||
// stack: x0, y0, x1, y1, retdest with x0 == x1
|
||||
|
||||
// Check if the points are equal
|
||||
DUP2
|
||||
// stack: y0, x0, y0, x1, y1, retdest
|
||||
DUP5
|
||||
// stack: y1, y0, x0, y0, x1, y1, retdest
|
||||
EQ
|
||||
// stack: y1 == y0, x0, y0, x1, y1, retdest
|
||||
%jumpi(ec_add_equal_points)
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Otherwise, one is the negation of the other so we can return (0,0).
|
||||
%pop4
|
||||
// stack: retdest
|
||||
PUSH 0
|
||||
// stack: 0, retdest
|
||||
PUSH 0
|
||||
// stack: 0, 0, retdest
|
||||
SWAP2
|
||||
// stack: retdest, 0, 0
|
||||
JUMP
|
||||
|
||||
|
||||
// Secp256k1 elliptic curve addition.
|
||||
// Assumption: x0 == x1 and y0 == y1
|
||||
// Standard doubling formula.
|
||||
ec_add_equal_points:
|
||||
JUMPDEST
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Compute lambda = 3/2 * x0^2 / y0
|
||||
%secp_base
|
||||
// stack: N, x0, y0, x1, y1, retdest
|
||||
%secp_base
|
||||
// stack: N, N, x0, y0, x1, y1, retdest
|
||||
DUP3
|
||||
// stack: x0, N, N, x0, y0, x1, y1, retdest
|
||||
DUP1
|
||||
// stack: x0, x0, N, N, x0, y0, x1, y1, retdest
|
||||
MULMOD
|
||||
// stack: x0^2, N, x0, y0, x1, y1, retdest with
|
||||
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe19 // 3/2 in the base field
|
||||
// stack: 3/2, x0^2, N, x0, y0, x1, y1, retdest
|
||||
MULMOD
|
||||
// stack: 3/2 * x0^2, x0, y0, x1, y1, retdest
|
||||
DUP3
|
||||
// stack: y0, 3/2 * x0^2, x0, y0, x1, y1, retdest
|
||||
%moddiv_secp_base
|
||||
// stack: lambda, x0, y0, x1, y1, retdest
|
||||
%jump(ec_add_valid_points_with_lambda)
|
||||
|
||||
// Secp256k1 elliptic curve doubling.
|
||||
// Assumption: (x0,y0) is a valid point.
|
||||
// Standard doubling formula.
|
||||
global ec_double_secp:
|
||||
JUMPDEST
|
||||
// stack: x0, y0, retdest
|
||||
DUP2
|
||||
// stack: y0, x0, y0, retdest
|
||||
DUP2
|
||||
// stack: x0, y0, x0, y0, retdest
|
||||
%jump(ec_add_equal_points)
|
||||
|
||||
// Push the order of the Secp256k1 scalar field.
|
||||
%macro secp_base
|
||||
PUSH 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
|
||||
%endmacro
|
||||
|
||||
// Modular subtraction. Subtraction x-y underflows iff x<x-y, so can be computed as N*(x<x-y) + x-y.
|
||||
%macro submod_secp_base
|
||||
// stack: x, y
|
||||
SWAP1
|
||||
// stack: y, x
|
||||
DUP2
|
||||
// stack: x, y, x
|
||||
SUB
|
||||
// stack: x - y, x
|
||||
DUP1
|
||||
// stack: x - y, x - y, x
|
||||
SWAP2
|
||||
// stack: x, x - y, x - y
|
||||
LT
|
||||
// stack: x < x - y, x - y
|
||||
%secp_base
|
||||
// stack: N, x < x - y, x - y
|
||||
MUL
|
||||
// stack: N * (x < x - y), x - y
|
||||
ADD
|
||||
// (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_secp
|
||||
// stack: x, y
|
||||
%secp_base
|
||||
// stack: N, x, y
|
||||
DUP2
|
||||
// stack: x, N, x, y
|
||||
LT
|
||||
// stack: x < N, x, y
|
||||
%secp_base
|
||||
// stack: N, x < N, x, y
|
||||
DUP4
|
||||
// stack: y, N, x < N, x, y
|
||||
LT
|
||||
// stack: y < N, x < N, x, y
|
||||
AND
|
||||
// stack: (y < N) & (x < N), x, y
|
||||
SWAP2
|
||||
// stack: y, x, (y < N) & (x < N), x
|
||||
SWAP1
|
||||
// stack: x, y, (y < N) & (x < N)
|
||||
%secp_base
|
||||
// stack: N, x, y, b
|
||||
%secp_base
|
||||
// stack: N, N, x, y, b
|
||||
DUP3
|
||||
// stack: x, N, N, x, y, b
|
||||
%secp_base
|
||||
// stack: N, x, N, N, x, y, b
|
||||
DUP2
|
||||
// stack: x, N, x, N, N, x, y, b
|
||||
DUP1
|
||||
// stack: x, x, N, x, N, N, x, y, b
|
||||
MULMOD
|
||||
// stack: x^2 % N, x, N, N, x, y, b
|
||||
MULMOD
|
||||
// stack: x^3 % N, N, x, y, b
|
||||
PUSH 7
|
||||
// stack: 7, x^3 % N, N, x, y, b
|
||||
ADDMOD
|
||||
// stack: (x^3 + 7) % N, x, y, b
|
||||
DUP3
|
||||
// stack: y, (x^3 + 7) % N, x, y, b
|
||||
%secp_base
|
||||
// stack: N, y, (x^3 + 7) % N, x, y, b
|
||||
SWAP1
|
||||
// stack: y, N, (x^3 + 7) % N, x, y, b
|
||||
DUP1
|
||||
// stack: y, y, N, (x^3 + 7) % N, x, y, b
|
||||
MULMOD
|
||||
// stack: y^2 % N, (x^3 + 7) % N, x, y, b
|
||||
EQ
|
||||
// stack: y^2 % N == (x^3 + 7) % N, x, y, b
|
||||
SWAP2
|
||||
// stack: y, x, y^2 % N == (x^3 + 7) % N, b
|
||||
%ec_isidentity
|
||||
// stack: (x,y)==(0,0), y^2 % N == (x^3 + 7) % N, b
|
||||
SWAP2
|
||||
// stack: b, y^2 % N == (x^3 + 7) % N, (x,y)==(0,0)
|
||||
AND
|
||||
// stack: y^2 % N == (x^3 + 7) % N & (x < N) & (y < N), (x,y)==(0,0)
|
||||
OR
|
||||
// stack: y^2 % N == (x^3 + 7) % N & (x < N) & (y < N) || (x,y)==(0,0)
|
||||
%endmacro
|
||||
72
evm/src/cpu/kernel/asm/secp256k1/curve_mul.asm
Normal file
72
evm/src/cpu/kernel/asm/secp256k1/curve_mul.asm
Normal file
@ -0,0 +1,72 @@
|
||||
// Same algorithm as in `exp.asm`
|
||||
global ec_mul_valid_point_secp:
|
||||
JUMPDEST
|
||||
// stack: x, y, s, retdest
|
||||
DUP3
|
||||
// stack: s, x, y, s, retdest
|
||||
%jumpi(step_case)
|
||||
// stack: x, y, s, retdest
|
||||
%jump(ret_zero_ec_mul)
|
||||
|
||||
step_case:
|
||||
JUMPDEST
|
||||
// stack: x, y, s, retdest
|
||||
PUSH recursion_return
|
||||
// stack: recursion_return, x, y, s, retdest
|
||||
PUSH 2
|
||||
// stack: 2, recursion_return, x, y, s, retdest
|
||||
DUP5
|
||||
// stack: s, 2, recursion_return, x, y, s, retdest
|
||||
DIV
|
||||
// stack: s / 2, recursion_return, x, y, s, retdest
|
||||
PUSH step_case_contd
|
||||
// stack: step_case_contd, s / 2, recursion_return, x, y, s, retdest
|
||||
DUP5
|
||||
// stack: y, step_case_contd, s / 2, recursion_return, x, y, s, retdest
|
||||
DUP5
|
||||
// stack: x, y, step_case_contd, s / 2, recursion_return, x, y, s, retdest
|
||||
%jump(ec_double_secp)
|
||||
|
||||
// Assumption: 2(x,y) = (x',y')
|
||||
step_case_contd:
|
||||
JUMPDEST
|
||||
// stack: x', y', s / 2, recursion_return, x, y, s, retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
|
||||
recursion_return:
|
||||
JUMPDEST
|
||||
// stack: x', y', x, y, s, retdest
|
||||
SWAP4
|
||||
// stack: s, y', x, y, x', retdest
|
||||
PUSH 1
|
||||
// stack: 1, s, y', x, y, x', retdest
|
||||
AND
|
||||
// stack: s & 1, y', x, y, x', retdest
|
||||
SWAP1
|
||||
// stack: y', s & 1, x, y, x', retdest
|
||||
SWAP2
|
||||
// stack: x, s & 1, y', y, x', retdest
|
||||
SWAP3
|
||||
// stack: y, s & 1, y', x, x', retdest
|
||||
SWAP4
|
||||
// stack: x', s & 1, y', x, y, retdest
|
||||
SWAP1
|
||||
// stack: s & 1, x', y', x, y, retdest
|
||||
%jumpi(odd_scalar)
|
||||
// stack: x', y', x, y, retdest
|
||||
SWAP3
|
||||
// stack: y, y', x, x', retdest
|
||||
POP
|
||||
// stack: y', x, x', retdest
|
||||
SWAP1
|
||||
// stack: x, y', x', retdest
|
||||
POP
|
||||
// stack: y', x', retdest
|
||||
SWAP2
|
||||
// stack: retdest, x', y'
|
||||
JUMP
|
||||
|
||||
odd_scalar:
|
||||
JUMPDEST
|
||||
// stack: x', y', x, y, retdest
|
||||
%jump(ec_add_valid_points_secp)
|
||||
672
evm/src/cpu/kernel/asm/secp256k1/inverse_scalar.asm
Normal file
672
evm/src/cpu/kernel/asm/secp256k1/inverse_scalar.asm
Normal file
@ -0,0 +1,672 @@
|
||||
/// Division modulo 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141, the Secp256k1 scalar field order
|
||||
/// To replace with more efficient method using non-determinism later.
|
||||
|
||||
%macro mulmodn_secp_scalar
|
||||
// stack: x, y
|
||||
%secp_scalar
|
||||
// stack: N, x, y
|
||||
SWAP2
|
||||
// stack: y, x, N
|
||||
MULMOD
|
||||
%endmacro
|
||||
|
||||
%macro squaremodn_secp_scalar
|
||||
// stack: x
|
||||
DUP1
|
||||
// stack: x, x
|
||||
%mulmodn_secp_scalar
|
||||
%endmacro
|
||||
|
||||
// Computes the inverse modulo N using x^-1 = x^(N-2) mod N and square-and-multiply modular exponentiation.
|
||||
%macro inverse_secp_scalar
|
||||
DUP1
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
%squaremodn_secp_scalar
|
||||
DUP2
|
||||
%mulmodn_secp_scalar
|
||||
SWAP1
|
||||
// stack: x, x^-1
|
||||
POP
|
||||
// stack: x^-1
|
||||
%endmacro
|
||||
818
evm/src/cpu/kernel/asm/secp256k1/lift_x.asm
Normal file
818
evm/src/cpu/kernel/asm/secp256k1/lift_x.asm
Normal file
@ -0,0 +1,818 @@
|
||||
// Returns y such that (x,y) is on Secp256k1 and y&1 = parity,
|
||||
// as well as a flag indicating whether such a y exists.
|
||||
%macro secp_lift_x
|
||||
// stack: x, parity
|
||||
%cubemodn_secp_base
|
||||
// stack: x^3, parity
|
||||
PUSH 7
|
||||
// stack: 7, x^3, parity
|
||||
%addmodn_secp_base
|
||||
// stack: x^3+7, x, parity
|
||||
DUP1
|
||||
// stack: x^3+7, x^3+7, parity
|
||||
%sqrt_secp_base
|
||||
// stack: y, x^3+7, x, parity
|
||||
SWAP1
|
||||
// stack: x^3+7, y, parity
|
||||
DUP2
|
||||
// stack: y, x^3+7, y, parity
|
||||
%squaremodn_secp_base
|
||||
// stack: y^2, x^3+7, y, parity
|
||||
EQ
|
||||
// stack: sqrtOk, y, parity
|
||||
SWAP2
|
||||
// stack: parity, y, sqrtOk
|
||||
DUP2
|
||||
// stack: y, parity, y, sqrtOk
|
||||
PUSH 1
|
||||
// stack: 1, y, parity, y, sqrtOk
|
||||
AND
|
||||
// stack: 1 & y, parity, y, sqrtOk
|
||||
EQ
|
||||
// stack: correctParity, y, sqrtOk
|
||||
DUP2
|
||||
// stack: y, correctParity, y, sqrtOk
|
||||
%secp_base
|
||||
// stack: N, y, correctParity, y, sqrtOk
|
||||
SUB
|
||||
// stack: N - y, correctParity, y, sqrtOk
|
||||
SWAP1
|
||||
// stack: correctParity, N - y, y, sqrtOk
|
||||
%select_bool
|
||||
// stack: goody, sqrtOk
|
||||
%endmacro
|
||||
|
||||
%macro cubemodn_secp_base
|
||||
// stack: x
|
||||
DUP1
|
||||
// stack: x, x
|
||||
%squaremodn_secp_base
|
||||
// stack: x^2, x
|
||||
%mulmodn_secp_base
|
||||
%endmacro
|
||||
|
||||
%macro addmodn_secp_base
|
||||
// stack: x, y
|
||||
%secp_base
|
||||
// stack: N, x, y
|
||||
SWAP2
|
||||
// stack: y, x, N
|
||||
ADDMOD
|
||||
%endmacro
|
||||
|
||||
// Returns a square root of x if one exists, otherwise an undefined value.
|
||||
// Computed as x^(q+1)/4, with q the Secp base field order.
|
||||
// To replace with more efficient method using non-determinism later.
|
||||
%macro sqrt_secp_base
|
||||
// stack: x
|
||||
DUP1
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
SWAP1
|
||||
// stack: x, x^-1
|
||||
POP
|
||||
// stack: x^-1
|
||||
%endmacro
|
||||
786
evm/src/cpu/kernel/asm/secp256k1/moddiv.asm
Normal file
786
evm/src/cpu/kernel/asm/secp256k1/moddiv.asm
Normal file
@ -0,0 +1,786 @@
|
||||
/// Division modulo 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f, the Secp256k1 base field order
|
||||
/// To replace with more efficient method using non-determinism later.
|
||||
|
||||
// Returns y * (x^-1) where the inverse is taken modulo N
|
||||
%macro moddiv_secp_base
|
||||
// stack: x, y
|
||||
%inverse_secp_base
|
||||
// stack: x^-1, y
|
||||
%mulmodn_secp_base
|
||||
%endmacro
|
||||
|
||||
%macro mulmodn_secp_base
|
||||
// stack: x, y
|
||||
%secp_base
|
||||
// stack: N, x, y
|
||||
SWAP2
|
||||
// stack: y, x, N
|
||||
MULMOD
|
||||
%endmacro
|
||||
|
||||
%macro squaremodn_secp_base
|
||||
// stack: x
|
||||
DUP1
|
||||
// stack: x, x
|
||||
%mulmodn_secp_base
|
||||
%endmacro
|
||||
|
||||
// Computes the inverse modulo N using x^-1 = x^(N-2) mod N and square-and-multiply modular exponentiation.
|
||||
%macro inverse_secp_base
|
||||
DUP1
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
%squaremodn_secp_base
|
||||
DUP2
|
||||
%mulmodn_secp_base
|
||||
SWAP1
|
||||
// stack: x, x^-1
|
||||
POP
|
||||
// stack: x^-1
|
||||
%endmacro
|
||||
@ -3,20 +3,61 @@ use ethereum_types::{U256, U512};
|
||||
/// Halt interpreter execution whenever a jump to this offset is done.
|
||||
const HALT_OFFSET: usize = 0xdeadbeef;
|
||||
|
||||
struct Interpreter<'a> {
|
||||
#[derive(Debug, Default)]
|
||||
pub(crate) struct EvmMemory {
|
||||
memory: Vec<u8>,
|
||||
}
|
||||
|
||||
impl EvmMemory {
|
||||
fn len(&self) -> usize {
|
||||
self.memory.len()
|
||||
}
|
||||
|
||||
/// Expand memory until `self.len() >= offset`.
|
||||
fn expand(&mut self, offset: usize) {
|
||||
while self.len() < offset {
|
||||
self.memory.extend([0; 32]);
|
||||
}
|
||||
}
|
||||
|
||||
fn mload(&mut self, offset: usize) -> U256 {
|
||||
self.expand(offset + 32);
|
||||
U256::from_big_endian(&self.memory[offset..offset + 32])
|
||||
}
|
||||
|
||||
fn mstore(&mut self, offset: usize, value: U256) {
|
||||
self.expand(offset + 32);
|
||||
let value_be = {
|
||||
let mut tmp = [0; 32];
|
||||
value.to_big_endian(&mut tmp);
|
||||
tmp
|
||||
};
|
||||
self.memory[offset..offset + 32].copy_from_slice(&value_be);
|
||||
}
|
||||
|
||||
fn mstore8(&mut self, offset: usize, value: U256) {
|
||||
self.expand(offset + 1);
|
||||
let value_byte = value.0[0] as u8;
|
||||
self.memory[offset] = value_byte;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Interpreter<'a> {
|
||||
code: &'a [u8],
|
||||
jumpdests: Vec<usize>,
|
||||
offset: usize,
|
||||
stack: Vec<U256>,
|
||||
pub(crate) stack: Vec<U256>,
|
||||
pub(crate) memory: EvmMemory,
|
||||
running: bool,
|
||||
}
|
||||
|
||||
pub fn run(code: &[u8], initial_offset: usize, initial_stack: Vec<U256>) -> Vec<U256> {
|
||||
pub(crate) fn run(code: &[u8], initial_offset: usize, initial_stack: Vec<U256>) -> Interpreter {
|
||||
let mut interpreter = Interpreter {
|
||||
code,
|
||||
jumpdests: find_jumpdests(code),
|
||||
offset: initial_offset,
|
||||
stack: initial_stack,
|
||||
memory: EvmMemory::default(),
|
||||
running: true,
|
||||
};
|
||||
|
||||
@ -24,7 +65,7 @@ pub fn run(code: &[u8], initial_offset: usize, initial_stack: Vec<U256>) -> Vec<
|
||||
interpreter.run_opcode();
|
||||
}
|
||||
|
||||
interpreter.stack
|
||||
interpreter
|
||||
}
|
||||
|
||||
impl<'a> Interpreter<'a> {
|
||||
@ -104,9 +145,9 @@ impl<'a> Interpreter<'a> {
|
||||
0x46 => todo!(), // "CHAINID",
|
||||
0x48 => todo!(), // "BASEFEE",
|
||||
0x50 => self.run_pop(), // "POP",
|
||||
0x51 => todo!(), // "MLOAD",
|
||||
0x52 => todo!(), // "MSTORE",
|
||||
0x53 => todo!(), // "MSTORE8",
|
||||
0x51 => self.run_mload(), // "MLOAD",
|
||||
0x52 => self.run_mstore(), // "MSTORE",
|
||||
0x53 => self.run_mstore8(), // "MSTORE8",
|
||||
0x54 => todo!(), // "SLOAD",
|
||||
0x55 => todo!(), // "SSTORE",
|
||||
0x56 => self.run_jump(), // "JUMP",
|
||||
@ -260,6 +301,24 @@ impl<'a> Interpreter<'a> {
|
||||
self.pop();
|
||||
}
|
||||
|
||||
fn run_mload(&mut self) {
|
||||
let offset = self.pop();
|
||||
let value = self.memory.mload(offset.as_usize());
|
||||
self.push(value);
|
||||
}
|
||||
|
||||
fn run_mstore(&mut self) {
|
||||
let offset = self.pop();
|
||||
let value = self.pop();
|
||||
self.memory.mstore(offset.as_usize(), value);
|
||||
}
|
||||
|
||||
fn run_mstore8(&mut self) {
|
||||
let offset = self.pop();
|
||||
let value = self.pop();
|
||||
self.memory.mstore8(offset.as_usize(), value);
|
||||
}
|
||||
|
||||
fn run_jump(&mut self) {
|
||||
let x = self.pop().as_usize();
|
||||
self.offset = x;
|
||||
@ -317,13 +376,40 @@ fn find_jumpdests(code: &[u8]) -> Vec<usize> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
use hex_literal::hex;
|
||||
|
||||
use crate::cpu::kernel::interpreter::{run, Interpreter};
|
||||
|
||||
#[test]
|
||||
fn test_run() {
|
||||
let code = vec![
|
||||
0x60, 0x1, 0x60, 0x2, 0x1, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56,
|
||||
]; // PUSH1, 1, PUSH1, 2, ADD, PUSH4 deadbeef, JUMP
|
||||
assert_eq!(run(&code, 0, vec![]), vec![0x3.into()]);
|
||||
assert_eq!(run(&code, 0, vec![]).stack, vec![0x3.into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_with_memory() {
|
||||
// PUSH1 0xff
|
||||
// PUSH1 0
|
||||
// MSTORE
|
||||
|
||||
// PUSH1 0
|
||||
// MLOAD
|
||||
|
||||
// PUSH1 1
|
||||
// MLOAD
|
||||
|
||||
// PUSH1 0x42
|
||||
// PUSH1 0x27
|
||||
// MSTORE8
|
||||
let code = vec![
|
||||
0x60, 0xff, 0x60, 0x0, 0x52, 0x60, 0, 0x51, 0x60, 0x1, 0x51, 0x60, 0x42, 0x60, 0x27,
|
||||
0x53,
|
||||
];
|
||||
let run = run(&code, 0, vec![]);
|
||||
let Interpreter { stack, memory, .. } = run;
|
||||
assert_eq!(stack, vec![0xff.into(), 0xff00.into()]);
|
||||
assert_eq!(&memory.memory, &hex!("00000000000000000000000000000000000000000000000000000000000000ff0000000000000042000000000000000000000000000000000000000000000000"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ mod parser;
|
||||
|
||||
#[cfg(test)]
|
||||
mod interpreter;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use assembler::assemble;
|
||||
use parser::parse;
|
||||
|
||||
246
evm/src/cpu/kernel/tests/curve_ops.rs
Normal file
246
evm/src/cpu/kernel/tests/curve_ops.rs
Normal file
@ -0,0 +1,246 @@
|
||||
#[cfg(test)]
|
||||
mod bn {
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
use crate::cpu::kernel::tests::u256ify;
|
||||
|
||||
#[test]
|
||||
fn test_ec_ops() -> Result<()> {
|
||||
// Make sure we can parse and assemble the entire kernel.
|
||||
let kernel = combined_kernel();
|
||||
let ec_add = kernel.global_labels["ec_add"];
|
||||
let ec_double = kernel.global_labels["ec_double"];
|
||||
let ec_mul = kernel.global_labels["ec_mul"];
|
||||
let identity = ("0x0", "0x0");
|
||||
let invalid = ("0x0", "0x3"); // Not on curve
|
||||
let point0 = (
|
||||
"0x1feee7ec986e198890cb83be8b8ba09ee953b3f149db6d9bfdaa5c308a33e58d",
|
||||
"0x2051cc9a9edd46231604fd88f351e95ec72a285be93e289ac59cb48561efb2c6",
|
||||
);
|
||||
let point1 = (
|
||||
"0x15b64d0a5f329fb672029298be8050f444626e6de11903caffa74b388075be1b",
|
||||
"0x2d9e07340bd5cd7b70687b98f2500ff930a89a30d7b6a3e04b1b4d345319d234",
|
||||
);
|
||||
// point2 = point0 + point1
|
||||
let point2 = (
|
||||
"0x18659c0e0a8fedcb8747cf463fc7cfa05f667d84e771d0a9521fc1a550688f0c",
|
||||
"0x283ed10b42703e187e7a808aeb45c6b457bc4cc7d704e53b3348a1e3b0bfa55b",
|
||||
);
|
||||
// point3 = 2 * point0
|
||||
let point3 = (
|
||||
"0x17da2b7b1a01c8dfdf0f5a6415833c7d755d219aa7e2c4cd0ac83d87d0ca4217",
|
||||
"0xc9ace9de14aac8114541b50c19320eb40f0eeac3621526d9e34dbcf4c3a6c0f",
|
||||
);
|
||||
let s = "0xabb2a34c0e7956cfe6cef9ddb7e810c45ea19a6ebadd79c21959af09f5ba480a";
|
||||
// point4 = s * point0
|
||||
let point4 = (
|
||||
"0xe519344959cc17021fe98878f947f5c1b1675325533a620c1684cfa6367e6c0",
|
||||
"0x7496a7575b0b6a821e19ce780ecc3e0b156e605327798693defeb9f265b7a6f",
|
||||
);
|
||||
|
||||
// Standard addition #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
// Standard addition #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
|
||||
// Standard doubling #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_double, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
|
||||
// Addition with identity #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #3
|
||||
let initial_stack =
|
||||
u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Addition with invalid point(s) #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
|
||||
// Scalar multiplication #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
// Scalar multiplication #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point0.1, point0.0])?);
|
||||
// Scalar multiplication #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #5
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
|
||||
// Multiple calls
|
||||
let ec_mul_hex = format!("0x{:x}", ec_mul);
|
||||
let initial_stack = u256ify([
|
||||
"0xdeadbeef",
|
||||
s,
|
||||
&ec_mul_hex,
|
||||
identity.1,
|
||||
identity.0,
|
||||
point0.1,
|
||||
point0.0,
|
||||
])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod secp {
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
use crate::cpu::kernel::tests::u256ify;
|
||||
|
||||
#[test]
|
||||
fn test_ec_ops() -> Result<()> {
|
||||
// Make sure we can parse and assemble the entire kernel.
|
||||
let kernel = combined_kernel();
|
||||
let ec_add = kernel.global_labels["ec_add_valid_points_secp"];
|
||||
let ec_double = kernel.global_labels["ec_double_secp"];
|
||||
let ec_mul = kernel.global_labels["ec_mul_valid_point_secp"];
|
||||
let identity = ("0x0", "0x0");
|
||||
let point0 = (
|
||||
"0xc82ccceebd739e646631b7270ed8c33e96c4940b19db91eaf67da6ec92d109b",
|
||||
"0xe0d241d2de832656c3eed78271bb06b5602d6473742c7c48a38b9f0350a76164",
|
||||
);
|
||||
let point1 = (
|
||||
"0xbf26b1a7a46025d0a1787aa050d0bb83b8a4746010f873404389b8b23360919c",
|
||||
"0x65adeff3fed1b22fa10279b5a25b96694a20bcbf6b718c0412f6d34a2e9bb924",
|
||||
);
|
||||
// point2 = point0 + point1
|
||||
let point2 = (
|
||||
"0x191e8183402c6d6f5f22a9fe2a5ce17a7dd5184bd5d359c77189e9f714a18225",
|
||||
"0xe23fbb6913de7449d92e4dfbe278e2874fac80d53bfeb8fb3400462b7bfaec74",
|
||||
);
|
||||
// point3 = 2 * point0
|
||||
let point3 = (
|
||||
"0x7872498939b02197c2b6f0a0f5767f36551e43f910de472fbbff0538b21f5f45",
|
||||
"0x294e15025d935438023a0e4056892abd6405fade13cf2b3131d8755be7cebad",
|
||||
);
|
||||
let s = "0xa72ad7d8ce24135b5138f853d7a9896381c40523b5d1cf03072151f2af10e35e";
|
||||
// point4 = s * point0
|
||||
let point4 = (
|
||||
"0xd8bec38864f0fe56d429540e6de624afb8ddc7fba1f738337913922a30b96c14",
|
||||
"0x5b086b2720ac39d173777bc36a49629c80c3a3e55e1c50527e60016d9be71318",
|
||||
);
|
||||
|
||||
// Standard addition #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
// Standard addition #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
|
||||
// Standard doubling #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_double, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
|
||||
// Addition with identity #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #3
|
||||
let initial_stack =
|
||||
u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Scalar multiplication #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
// Scalar multiplication #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point0.1, point0.0])?);
|
||||
// Scalar multiplication #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Multiple calls
|
||||
let ec_mul_hex = format!("0x{:x}", ec_mul);
|
||||
let initial_stack = u256ify([
|
||||
"0xdeadbeef",
|
||||
s,
|
||||
&ec_mul_hex,
|
||||
identity.1,
|
||||
identity.0,
|
||||
point0.1,
|
||||
point0.0,
|
||||
])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack).stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
103
evm/src/cpu/kernel/tests/ecrecover.rs
Normal file
103
evm/src/cpu/kernel/tests/ecrecover.rs
Normal file
@ -0,0 +1,103 @@
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use keccak_hash::keccak;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::assembler::Kernel;
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
use crate::cpu::kernel::tests::u256ify;
|
||||
|
||||
fn pubkey_to_addr(x: U256, y: U256) -> Vec<u8> {
|
||||
let mut buf = [0; 64];
|
||||
x.to_big_endian(&mut buf[0..32]);
|
||||
y.to_big_endian(&mut buf[32..64]);
|
||||
let hash = keccak(buf);
|
||||
hash.0[12..].to_vec()
|
||||
}
|
||||
|
||||
fn test_valid_ecrecover(
|
||||
hash: &str,
|
||||
v: &str,
|
||||
r: &str,
|
||||
s: &str,
|
||||
expected: &str,
|
||||
kernel: &Kernel,
|
||||
) -> Result<()> {
|
||||
let ecrecover = kernel.global_labels["ecrecover"];
|
||||
let initial_stack = u256ify([s, r, v, hash])?;
|
||||
let stack = run(&kernel.code, ecrecover, initial_stack).stack;
|
||||
let got = pubkey_to_addr(stack[1], stack[0]);
|
||||
assert_eq!(got, hex::decode(&expected[2..]).unwrap());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_invalid_ecrecover(hash: &str, v: &str, r: &str, s: &str, kernel: &Kernel) -> Result<()> {
|
||||
let ecrecover = kernel.global_labels["ecrecover"];
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?;
|
||||
let stack = run(&kernel.code, ecrecover, initial_stack).stack;
|
||||
assert_eq!(stack, vec![U256::MAX]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ecrecover() -> Result<()> {
|
||||
let kernel = combined_kernel();
|
||||
|
||||
test_valid_ecrecover(
|
||||
"0x55f77e8909b1f1c9531c4a309bb2d40388e9ed4b87830c8f90363c6b36255fb9",
|
||||
"0x1b",
|
||||
"0xd667c5a20fa899b253924099e10ae92998626718585b8171eb98de468bbebc",
|
||||
"0x58351f48ce34bf134ee611fb5bf255a5733f0029561d345a7d46bfa344b60ac0",
|
||||
"0x67f3c0Da351384838d7F7641AB0fCAcF853E1844",
|
||||
&kernel,
|
||||
)?;
|
||||
test_valid_ecrecover(
|
||||
"0x55f77e8909b1f1c9531c4a309bb2d40388e9ed4b87830c8f90363c6b36255fb9",
|
||||
"0x1c",
|
||||
"0xd667c5a20fa899b253924099e10ae92998626718585b8171eb98de468bbebc",
|
||||
"0x58351f48ce34bf134ee611fb5bf255a5733f0029561d345a7d46bfa344b60ac0",
|
||||
"0xaA58436DeABb64982a386B2De1A8015AA28fCCc0",
|
||||
&kernel,
|
||||
)?;
|
||||
test_valid_ecrecover(
|
||||
"0x0",
|
||||
"0x1c",
|
||||
"0x1",
|
||||
"0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
|
||||
"0x3344c6f6eeCA588be132142DB0a32C71ABFAAe7B",
|
||||
&kernel,
|
||||
)?;
|
||||
|
||||
test_invalid_ecrecover(
|
||||
"0x0",
|
||||
"0x42", // v not in {27,28}
|
||||
"0x1",
|
||||
"0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
|
||||
&kernel,
|
||||
)?;
|
||||
test_invalid_ecrecover(
|
||||
"0x0",
|
||||
"0x42",
|
||||
"0xd667c5a20fa899b253924099e10ae92998626718585b8171eb98de468bbebc",
|
||||
"0x0", // s=0
|
||||
&kernel,
|
||||
)?;
|
||||
test_invalid_ecrecover(
|
||||
"0x0",
|
||||
"0x42",
|
||||
"0x0", // r=0
|
||||
"0xd667c5a20fa899b253924099e10ae92998626718585b8171eb98de468bbebc",
|
||||
&kernel,
|
||||
)?;
|
||||
test_invalid_ecrecover(
|
||||
"0x0",
|
||||
"0x1c",
|
||||
"0x3a18b21408d275dde53c0ea86f9c1982eca60193db0ce15008fa408d43024847", // r^3 + 7 isn't a square
|
||||
"0x5db9745f44089305b2f2c980276e7025a594828d878e6e36dd2abd34ca6b9e3d",
|
||||
&kernel,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
44
evm/src/cpu/kernel/tests/exp.rs
Normal file
44
evm/src/cpu/kernel/tests/exp.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::run;
|
||||
|
||||
#[test]
|
||||
fn test_exp() -> Result<()> {
|
||||
// Make sure we can parse and assemble the entire kernel.
|
||||
let kernel = combined_kernel();
|
||||
let exp = kernel.global_labels["exp"];
|
||||
let mut rng = thread_rng();
|
||||
let a = U256([0; 4].map(|_| rng.gen()));
|
||||
let b = U256([0; 4].map(|_| rng.gen()));
|
||||
|
||||
// Random input
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, a];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack).stack;
|
||||
let initial_stack = vec![b, a];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack).stack;
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
// 0 base
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, U256::zero()];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack).stack;
|
||||
let initial_stack = vec![b, U256::zero()];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack).stack;
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
// 0 exponent
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, U256::zero(), a];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack).stack;
|
||||
let initial_stack = vec![U256::zero(), a];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack).stack;
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
15
evm/src/cpu/kernel/tests/mod.rs
Normal file
15
evm/src/cpu/kernel/tests/mod.rs
Normal file
@ -0,0 +1,15 @@
|
||||
mod curve_ops;
|
||||
mod ecrecover;
|
||||
mod exp;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
|
||||
pub(crate) fn u256ify<'a>(hexes: impl IntoIterator<Item = &'a str>) -> Result<Vec<U256>> {
|
||||
Ok(hexes
|
||||
.into_iter()
|
||||
.map(U256::from_str)
|
||||
.collect::<Result<Vec<_>, _>>()?)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user