diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/fp12_mul.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/fp12_mul.asm index e879297e..0ba5de5a 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/fp12_mul.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/fp12_mul.asm @@ -2,37 +2,29 @@ /// cost: 220 global test_mul_fp12: - // stack: f, inA , f', g, inB , g', inB, out, inA + // stack: f, inA , f', g, inB , g', mul_dest, inA, inB, out, ret_stack, out DUP7 - // stack: inA, f, inA , f', g, inB , g', inB, out, inA + // stack: inA, f, inA , f', g, inB , g', mul_dest, inA, inB, out, ret_stack, out %store_fp6 - // stack: inA , f', g, inB , g', inB, out, inA + // stack: inA , f', g, inB , g', mul_dest, inA, inB, out, ret_stack, out %offset_fp6 - // stack: inA', f', g, inB , g', inB, out, inA + // stack: inA', f', g, inB , g', mul_dest, inA, inB, out, ret_stack, out %store_fp6 - // stack: g, inB , g', inB, out, inA + // stack: g, inB , g', mul_dest, inA, inB, out, ret_stack, out DUP7 - // stack: inB, g, inB , g', inB, out, inA + // stack: inB, g, inB , g', mul_dest, inA, inB, out, ret_stack, out %store_fp6 - // stack: inB , g', inB, out, inA + // stack: inB , g', mul_dest, inA, inB, out, ret_stack, out %offset_fp6 - // stack: inB', g', inB, out, inA + // stack: inB', g', mul_dest, inA, inB, out, ret_stack, out %store_fp6 - // stack: inB, out, inA - PUSH ret_stack - // stack: ret_stack, inB, out, inA - SWAP3 - // stack: inA, inB, out, ret_stack - %jump(mul_fp12) -ret_stack: + // stack: mul_dest, inA, inB, out, ret_stack, out + JUMP +global ret_stack: // stack: out %load_fp12 %jump(0xdeadbeef) -square_fp12_test: - POP - %jump(square_fp12) - /////////////////////////////////////// ///// GENERAL FP12 MULTIPLICATION ///// @@ -387,6 +379,10 @@ global mul_fp12_sparse: /// /// f, f' consist of six elements on the stack +global square_fp12_test: + POP + %jump(square_fp12) + global square_fp12: // stack: inp, out DUP1 diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/frobenius.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/frobenius.asm index 1b5fec79..7e828784 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/frobenius.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/frobenius.asm @@ -1,3 +1,5 @@ +/// let Z` denote the complex conjugate of Z + /// def frob_fp6_n(C0, C1, C2): /// if n%2: /// D0, D1, D2 = C0`, FROB_t1[n] * C1`, FROB_t2[n] * C2` @@ -13,7 +15,7 @@ // stack: C2 , C1 , D0 %conj // stack: C2`, C1 , D0 - %froby2_1 + %frobt2_1 // stack: D2 , C1 , D0 %swap_fp2_hole_2 // stack: D0 , C1 , D2 @@ -21,7 +23,7 @@ // stack: C1 , D0 , D2 %conj // stack: C1`, D0 , D2 - %froby1_1 + %frobt1_1 // stack: D1 , D0 , D2 %swap_fp2 // stack: D0 , D1 , D2 @@ -31,13 +33,13 @@ // stack: C0, C1, C2 %swap_fp2_hole_2 // stack: C2, C1, C0 - %froby2_2 + %frobt2_2 // stack: D2, C1, C0 %swap_fp2_hole_2 // stack: C0, C1, D2 %swap_fp2 // stack: C1, C0, D2 - %froby1_2 + %frobt1_2 // stack: D1, C0, D2 %swap_fp2 // stack: D0, D1, D2 @@ -51,7 +53,7 @@ // stack: C2 , C1 , D0 %conj // stack: C2`, C1 , D0 - %froby2_3 + %frobt2_3 // stack: D2 , C1 , D0 %swap_fp2_hole_2 // stack: D0 , C1 , D2 @@ -59,7 +61,7 @@ // stack: C1 , D0 , D2 %conj // stack: C1`, D0 , D2 - %froby1_3 + %frobt1_3 // stack: D1 , D0 , D2 %swap_fp2 // stack: D0 , D1 , D2 @@ -183,36 +185,36 @@ %endmacro -%macro froby1_1 +%macro frobt1_1 PUSH 0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2 PUSH 0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d %mul_fp2 %endmacro -%macro froby2_1 +%macro frobt2_1 PUSH 0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126 PUSH 0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762 %mul_fp2 %endmacro -%macro froby1_2 +%macro frobt1_2 PUSH 0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48 %mul_fp_fp2 %endmacro -%macro froby2_2 +%macro frobt2_2 PUSH 0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe %mul_fp_fp2 %endmacro -%macro froby1_3 +%macro frobt1_3 PUSH 0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de PUSH 0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d %mul_fp2 %endmacro -%macro froby2_3 +%macro frobt2_3 PUSH 0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f PUSH 0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066 %mul_fp2 diff --git a/evm/src/cpu/kernel/tests/bn254_field.rs b/evm/src/cpu/kernel/tests/bn254_field.rs index 21becba9..b6f2ed65 100644 --- a/evm/src/cpu/kernel/tests/bn254_field.rs +++ b/evm/src/cpu/kernel/tests/bn254_field.rs @@ -21,6 +21,15 @@ fn sub_fp(x: U256, y: U256) -> U256 { (BN_BASE + x - y) % BN_BASE } +fn neg_fp(x: U256) -> U256 { + (BN_BASE - x) % BN_BASE +} + +fn conj_fp2(a: [U256; 2]) -> [U256; 2] { + let [a, a_] = a; + [a, neg_fp(a_)] +} + fn add_fp2(a: [U256; 2], b: [U256; 2]) -> [U256; 2] { let [a, a_] = a; let [b, b_] = b; @@ -51,10 +60,8 @@ fn mul_fp2(a: [U256; 2], b: [U256; 2]) -> [U256; 2] { fn i9(a: [U256; 2]) -> [U256; 2] { let [a, a_] = a; - [ - sub_fp(mul_fp(U256::from(9), a), a_), - add_fp(a, mul_fp(U256::from(9), a_)), - ] + let nine = U256::from(9); + [sub_fp(mul_fp(nine, a), a_), add_fp(a, mul_fp(nine, a_))] } fn add_fp6(c: [[U256; 2]; 3], d: [[U256; 2]; 3]) -> [[U256; 2]; 3] { @@ -106,8 +113,11 @@ fn sh(c: [[U256; 2]; 3]) -> [[U256; 2]; 3] { fn sparse_embed(x: [U256; 5]) -> [[[U256; 2]; 3]; 2] { let [g0, g1, g1_, g2, g2_] = x; - let z = U256::from(0); - [[[g0, z], [g1, g1_], [z, z]], [[z, z], [g2, g2_], [z, z]]] + let zero = U256::from(0); + [ + [[g0, zero], [g1, g1_], [zero, zero]], + [[zero, zero], [g2, g2_], [zero, zero]], + ] } fn mul_fp12(f: [[[U256; 2]; 3]; 2], g: [[[U256; 2]; 3]; 2]) -> [[[U256; 2]; 3]; 2] { @@ -139,18 +149,19 @@ fn gen_fp12_sparse() -> [[[U256; 2]; 3]; 2] { } fn make_initial_stack( + in0: usize, in1: usize, - in2: usize, out: usize, f0: [[U256; 2]; 3], f1: [[U256; 2]; 3], g0: [[U256; 2]; 3], g1: [[U256; 2]; 3], + mul_label: &str, ) -> Vec { // stack: in0, f, in0', f', in1, g, in1', g', in1, out, in0, out + let in0 = U256::from(in0); let in1 = U256::from(in1); - let in2 = U256::from(in2); let out = U256::from(out); let f0: Vec = f0.into_iter().flatten().collect(); @@ -158,100 +169,116 @@ fn make_initial_stack( let g0: Vec = g0.into_iter().flatten().collect(); let g1: Vec = g1.into_iter().flatten().collect(); + let ret_stack = U256::from(KERNEL.global_labels["ret_stack"]); + let mul_dest = U256::from(KERNEL.global_labels[mul_label]); + let mut input = f0; - input.extend(vec![in1]); + input.extend(vec![in0]); input.extend(f1); input.extend(g0); - input.extend(vec![in2]); + input.extend(vec![in1]); input.extend(g1); - input.extend(vec![in2, out, in1, out]); + input.extend(vec![mul_dest, in0, in1, out, ret_stack, out]); input.reverse(); input } +fn make_expected_output(f: [[[U256; 2]; 3]; 2], g: [[[U256; 2]; 3]; 2]) -> Vec { + mul_fp12(f, g) + .into_iter() + .flatten() + .flatten() + .rev() + .collect() +} + #[test] -fn test_fp12() -> Result<()> { - let in1 = 64; - let in2 = 76; +fn test_mul_fp12() -> Result<()> { + let in0 = 64; + let in1 = 76; let out = 88; let f0 = gen_fp6(); let f1 = gen_fp6(); let g0 = gen_fp6(); let g1 = gen_fp6(); + let [h0, h1] = gen_fp12_sparse(); - let initial_offset = KERNEL.global_labels["test_mul_fp12"]; - let initial_stack: Vec = make_initial_stack(in1, in2, out, f0, f1, g0, g1); - let final_stack: Vec = run_interpreter(initial_offset, initial_stack)? - .stack() - .to_vec(); + let test_mul = KERNEL.global_labels["test_mul_fp12"]; - let expected: Vec = mul_fp12([f0, f1], [g0, g1]) - .into_iter() - .flatten() - .flatten() - .rev() - .collect(); + let normal: Vec = make_initial_stack(in0, in1, out, f0, f1, g0, g1, "mul_fp12"); + let sparse: Vec = make_initial_stack(in0, in1, out, f0, f1, h0, h1, "mul_fp12_sparse"); + let square: Vec = make_initial_stack(in0, in1, out, f0, f1, f0, f1, "square_fp12_test"); - assert_eq!(final_stack, expected); + let out_normal: Vec = run_interpreter(test_mul, normal)?.stack().to_vec(); + let out_sparse: Vec = run_interpreter(test_mul, sparse)?.stack().to_vec(); + let out_square: Vec = run_interpreter(test_mul, square)?.stack().to_vec(); + + let exp_normal: Vec = make_expected_output([f0, f1], [g0, g1]); + let exp_sparse: Vec = make_expected_output([f0, f1], [h0, h1]); + let exp_square: Vec = make_expected_output([f0, f1], [f0, f1]); + + assert_eq!(out_normal, exp_normal); + assert_eq!(out_sparse, exp_sparse); + assert_eq!(out_square, exp_square); Ok(()) } -#[test] -#[ignore] -fn test_fp12_sparse() -> Result<()> { - let in1 = 64; - let in2 = 76; - let out = 88; +// #[test] +// #[ignore] +// fn test_fp12_sparse() -> Result<()> { +// let in1 = 64; +// let in2 = 76; +// let out = 88; - let f0 = gen_fp6(); - let f1 = gen_fp6(); - let [g0, g1] = gen_fp12_sparse(); +// let f0 = gen_fp6(); +// let f1 = gen_fp6(); +// let [g0, g1] = gen_fp12_sparse(); - let initial_offset = KERNEL.global_labels["test_mul_fp12"]; - let initial_stack: Vec = make_initial_stack(in1, in2, out, f0, f1, g0, g1); - let final_stack: Vec = run_interpreter(initial_offset, initial_stack)? - .stack() - .to_vec(); +// let initial_offset = KERNEL.global_labels["test_mul_fp12"]; +// let initial_stack: Vec = make_initial_stack(in1, in2, out, f0, f1, g0, g1); +// let final_stack: Vec = run_interpreter(initial_offset, initial_stack)? +// .stack() +// .to_vec(); - let expected: Vec = mul_fp12([f0, f1], [g0, g1]) - .into_iter() - .flatten() - .flatten() - .rev() - .collect(); +// let expected: Vec = mul_fp12([f0, f1], [g0, g1]) +// .into_iter() +// .flatten() +// .flatten() +// .rev() +// .collect(); - assert_eq!(final_stack, expected); +// assert_eq!(final_stack, expected); - Ok(()) -} +// Ok(()) +// } -#[test] -#[ignore] -fn test_fp12_square() -> Result<()> { - let in1 = 64; - let in2 = 76; - let out = 88; +// #[test] +// #[ignore] +// fn test_fp12_square() -> Result<()> { +// let in1 = 64; +// let in2 = 76; +// let out = 88; - let f0 = gen_fp6(); - let f1 = gen_fp6(); +// let f0 = gen_fp6(); +// let f1 = gen_fp6(); - let initial_offset = KERNEL.global_labels["test_mul_fp12"]; - let initial_stack: Vec = make_initial_stack(in1, in2, out, f0, f1, f0, f1); - let final_stack: Vec = run_interpreter(initial_offset, initial_stack)? - .stack() - .to_vec(); +// let initial_offset = KERNEL.global_labels["test_mul_fp12"]; +// let initial_stack: Vec = make_initial_stack(in1, in2, out, f0, f1, f0, f1); +// let final_stack: Vec = run_interpreter(initial_offset, initial_stack)? +// .stack() +// .to_vec(); - let expected: Vec = mul_fp12([f0, f1], [f0, f1]) - .into_iter() - .flatten() - .flatten() - .rev() - .collect(); +// let expected: Vec = mul_fp12([f0, f1], [f0, f1]) +// .into_iter() +// .flatten() +// .flatten() +// .rev() +// .collect(); - assert_eq!(final_stack, expected); +// assert_eq!(final_stack, expected); - Ok(()) -} +// Ok(()) +// } diff --git a/evm/src/cpu/kernel/tests/mod.rs b/evm/src/cpu/kernel/tests/mod.rs index 246b33d2..0f799df1 100644 --- a/evm/src/cpu/kernel/tests/mod.rs +++ b/evm/src/cpu/kernel/tests/mod.rs @@ -1,10 +1,10 @@ mod account_code; mod balance; +mod bn254_field; mod core; mod curve_ops; mod ecrecover; mod exp; -mod bn254_field; mod hash; mod mpt; mod packing;