diff --git a/evm/src/bn254.rs b/evm/src/bn254.rs index a86394e6..5c2e34fa 100644 --- a/evm/src/bn254.rs +++ b/evm/src/bn254.rs @@ -15,6 +15,35 @@ pub type Fp2 = [U256; 2]; pub type Fp6 = [Fp2; 3]; pub type Fp12 = [Fp6; 2]; +pub fn fp12_to_vec(f: Fp12) -> Vec { + f.into_iter().flatten().flatten().collect() +} + +pub fn fp12_to_array(f: Fp12) -> [U256; 12] { + let [[[f0, f1], [f2, f3], [f4, f5]], [[f6, f7], [f8, f9], [f10, f11]]] = f; + [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11] +} + +pub fn vec_to_fp12(xs: Vec) -> Fp12 { + let f0 = xs.clone().into_iter().nth(0).unwrap(); + let f1 = xs.clone().into_iter().nth(1).unwrap(); + let f2 = xs.clone().into_iter().nth(2).unwrap(); + let f3 = xs.clone().into_iter().nth(3).unwrap(); + let f4 = xs.clone().into_iter().nth(4).unwrap(); + let f5 = xs.clone().into_iter().nth(5).unwrap(); + let f6 = xs.clone().into_iter().nth(6).unwrap(); + let f7 = xs.clone().into_iter().nth(7).unwrap(); + let f8 = xs.clone().into_iter().nth(8).unwrap(); + let f9 = xs.clone().into_iter().nth(9).unwrap(); + let f10 = xs.clone().into_iter().nth(10).unwrap(); + let f11 = xs.clone().into_iter().nth(11).unwrap(); + + [ + [[f0, f1], [f2, f3], [f4, f5]], + [[f6, f7], [f8, f9], [f10, f11]], + ] +} + pub type Curve = [Fp; 2]; pub type TwistedCurve = [Fp2; 2]; @@ -601,3 +630,32 @@ const EXPS0: [bool; 65] = [ true, true, true, false, true, false, true, true, false, false, true, false, false, false, true, true, true, true, false, false, true, true, false, ]; + +pub fn store_tangent(p: Curve, q: TwistedCurve) -> Fp12 { + let [px, py] = p; + let [qx, qy] = q; + + let cx = neg_fp(mul_fp(U256::from(3), mul_fp(px, px))); + let cy = mul_fp(U256::from(2), py); + + sparse_embed( + sub_fp(mul_fp(py, py), U256::from(9)), + mul_fp2(embed_fp2(cx), qx), + mul_fp2(embed_fp2(cy), qy), + ) +} + +pub fn store_cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { + let [p1x, p1y] = p1; + let [p2x, p2y] = p2; + let [qx, qy] = q; + + let cx = sub_fp(p2y, p1y); + let cy = sub_fp(p1x, p2x); + + sparse_embed( + sub_fp(mul_fp(p1y, p2x), mul_fp(p2y, p1x)), + mul_fp2(embed_fp2(cx), qx), + mul_fp2(embed_fp2(cy), qy), + ) +} diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 580adeb7..40fd7dbc 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -8,7 +8,6 @@ use keccak_hash::keccak; use plonky2::field::goldilocks_field::GoldilocksField; use crate::bn254::BN_BASE; - use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 0f402c25..945925a7 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -4,17 +4,13 @@ use anyhow::Result; use ethereum_types::U256; use crate::bn254::{ - frob_fp12, gen_curve_point, gen_fp12, gen_fp12_sparse, gen_twisted_curve_point, mul_fp12, - power, Fp, Fp12, Fp2, + fp12_to_vec, frob_fp12, gen_curve_point, gen_fp12, gen_fp12_sparse, gen_twisted_curve_point, + mul_fp12, power, store_cord, store_tangent, Curve, Fp12, TwistedCurve, }; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::run_interpreter; -fn fp12_as_stack_input(f: Fp12) -> Vec { - f.into_iter().flatten().flatten().collect() -} - -fn fp12_as_stack_output(f: Fp12) -> Vec { +fn fp12_as_stack(f: Fp12) -> Vec { f.into_iter().flatten().flatten().rev().collect() } @@ -34,9 +30,9 @@ fn make_mul_stack( let mul_dest = U256::from(KERNEL.global_labels[mul_label]); let mut input = vec![in0]; - input.extend(fp12_as_stack_input(f)); + input.extend(fp12_to_vec(f)); input.extend(vec![in1]); - input.extend(fp12_as_stack_input(g)); + input.extend(fp12_to_vec(g)); input.extend(vec![mul_dest, in0, in1, out, ret_stack, out]); input.reverse(); input @@ -62,9 +58,9 @@ fn test_mul_fp12() -> Result<()> { 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 = fp12_as_stack_output(mul_fp12(f, g)); - let exp_sparse: Vec = fp12_as_stack_output(mul_fp12(f, h)); - let exp_square: Vec = fp12_as_stack_output(mul_fp12(f, f)); + let exp_normal: Vec = fp12_as_stack(mul_fp12(f, g)); + let exp_sparse: Vec = fp12_as_stack(mul_fp12(f, h)); + let exp_square: Vec = fp12_as_stack(mul_fp12(f, f)); assert_eq!(out_normal, exp_normal); assert_eq!(out_sparse, exp_sparse); @@ -84,7 +80,7 @@ fn test_frob_fp12() -> Result<()> { let test_frob6 = KERNEL.global_labels["test_frob_fp12_6"]; let mut stack = vec![ptr]; - stack.extend(fp12_as_stack_input(f)); + stack.extend(fp12_to_vec(f)); stack.extend(vec![ptr]); stack.reverse(); @@ -93,10 +89,10 @@ fn test_frob_fp12() -> Result<()> { let out_frob3: Vec = run_interpreter(test_frob3, stack.clone())?.stack().to_vec(); let out_frob6: Vec = run_interpreter(test_frob6, stack)?.stack().to_vec(); - let exp_frob1: Vec = fp12_as_stack_output(frob_fp12(1, f)); - let exp_frob2: Vec = fp12_as_stack_output(frob_fp12(2, f)); - let exp_frob3: Vec = fp12_as_stack_output(frob_fp12(3, f)); - let exp_frob6: Vec = fp12_as_stack_output(frob_fp12(6, f)); + let exp_frob1: Vec = fp12_as_stack(frob_fp12(1, f)); + let exp_frob2: Vec = fp12_as_stack(frob_fp12(2, f)); + let exp_frob3: Vec = fp12_as_stack(frob_fp12(3, f)); + let exp_frob6: Vec = fp12_as_stack(frob_fp12(6, f)); assert_eq!(out_frob1, exp_frob1); assert_eq!(out_frob2, exp_frob2); @@ -116,7 +112,7 @@ fn test_inv_fp12() -> Result<()> { let test_inv = KERNEL.global_labels["test_inv_fp12"]; let mut stack = vec![ptr]; - stack.extend(fp12_as_stack_input(f)); + stack.extend(fp12_to_vec(f)); stack.extend(vec![ptr, inv, U256::from_str("0xdeadbeef").unwrap()]); stack.reverse(); @@ -138,12 +134,61 @@ fn test_pow_fp12() -> Result<()> { let test_pow = KERNEL.global_labels["test_pow"]; let mut stack = vec![ptr]; - stack.extend(fp12_as_stack_input(f)); + stack.extend(fp12_to_vec(f)); stack.extend(vec![ptr, out, ret_stack, out]); stack.reverse(); let output: Vec = run_interpreter(test_pow, stack)?.stack().to_vec(); - let expected: Vec = fp12_as_stack_output(power(f)); + let expected: Vec = fp12_as_stack(power(f)); + + assert_eq!(output, expected); + + Ok(()) +} + +#[test] +fn test_store_tangent() -> Result<()> { + let p: Curve = gen_curve_point(); + let q: TwistedCurve = gen_twisted_curve_point(); + + let p_: Vec = p.into_iter().collect(); + let q_: Vec = q.into_iter().flatten().collect(); + + let test_tan = KERNEL.global_labels["test_store_tangent"]; + + let mut stack = p_; + stack.extend(q_); + stack.reverse(); + + let output: Vec = run_interpreter(test_tan, stack)?.stack().to_vec(); + + let expected = fp12_as_stack(store_tangent(p, q)); + + assert_eq!(output, expected); + + Ok(()) +} + +#[test] +fn test_store_cord() -> Result<()> { + let p1: Curve = gen_curve_point(); + let p2: Curve = gen_curve_point(); + let q: TwistedCurve = gen_twisted_curve_point(); + + let p1_: Vec = p1.into_iter().collect(); + let p2_: Vec = p2.into_iter().collect(); + let q_: Vec = q.into_iter().flatten().collect(); + + let mut stack = p1_; + stack.extend(p2_); + stack.extend(q_); + stack.reverse(); + + let test_cord = KERNEL.global_labels["test_store_cord"]; + + let output: Vec = run_interpreter(test_cord, stack)?.stack().to_vec(); + + let expected = fp12_as_stack(store_cord(p1, p2, q)); assert_eq!(output, expected); @@ -167,110 +212,6 @@ fn test_pow_fp12() -> Result<()> { // input // } -// fn store_tangent(p: [Fp; 2], q: [Fp2; 2]) -> Fp12 { -// let [px, py] = p; -// let [qx, qy] = q; - -// let cx = neg_fp(mul_fp(U256::from(3), mul_fp(px, px))); -// let cy = mul_fp(U256::from(2), py); - -// sparse_embed( -// sub_fp(mul_fp(py, py), U256::from(9)), -// mul_fp2(embed_fp2(cx), qx), -// mul_fp2(embed_fp2(cy), qy), -// ) -// } - -// fn store_cord(p1: [Fp; 2], p2: [Fp; 2], q: [Fp2; 2]) -> Fp12 { -// let [p1x, p1y] = p1; -// let [p2x, p2y] = p2; -// let [qx, qy] = q; - -// let cx = sub_fp(p2y, p1y); -// let cy = sub_fp(p1x, p2x); - -// sparse_embed( -// sub_fp(mul_fp(p1y, p2x), mul_fp(p2y, p1x)), -// mul_fp2(embed_fp2(cx), qx), -// mul_fp2(embed_fp2(cy), qy), -// ) -// } - -// fn make_tan_stack(p: [Fp; 2], q: [Fp2; 2]) -> Vec { -// let p: Vec = p.into_iter().collect(); -// let q: Vec = q.into_iter().flatten().collect(); - -// let mut input = p; -// input.extend(q); -// input.reverse(); -// input -// } - -// fn make_tan_expected(p: [Fp; 2], q: [Fp2; 2]) -> Vec { -// store_tangent(p, q) -// .into_iter() -// .flatten() -// .flatten() -// .rev() -// .collect() -// } - -// #[test] -// fn test_store_tangent() -> Result<()> { -// let p = [gen_fp(), gen_fp()]; -// let q = [[gen_fp(), gen_fp()], [gen_fp(), gen_fp()]]; - -// let expected = make_tan_expected(p, q); - -// let stack = make_tan_stack(p, q); -// let test_tan = KERNEL.global_labels["test_store_tangent"]; - -// let output: Vec = run_interpreter(test_tan, stack)?.stack().to_vec(); - -// assert_eq!(output, expected); - -// Ok(()) -// } - -// fn make_cord_stack(p1: [Fp; 2], p2: [Fp; 2], q: [Fp2; 2]) -> Vec { -// let p1: Vec = p1.into_iter().collect(); -// let p2: Vec = p2.into_iter().collect(); -// let q: Vec = q.into_iter().flatten().collect(); - -// let mut input = p1; -// input.extend(p2); -// input.extend(q); -// input.reverse(); -// input -// } - -// fn make_cord_expected(p1: [Fp; 2], p2: [Fp; 2], q: [Fp2; 2]) -> Vec { -// store_cord(p1, p2, q) -// .into_iter() -// .flatten() -// .flatten() -// .rev() -// .collect() -// } - -// #[test] -// fn test_store_cord() -> Result<()> { -// let p1 = gen_curve_point(); -// let p2 = gen_curve_point(); -// let q = gen_twisted_curve_point(); - -// let expected = make_cord_expected(p1, p2, q); - -// let stack = make_cord_stack(p1, p2, q); -// let test_cord = KERNEL.global_labels["test_store_cord"]; - -// let output: Vec = run_interpreter(test_cord, stack)?.stack().to_vec(); - -// assert_eq!(output, expected); - -// Ok(()) -// } - // #[test] // fn test_miller() -> Result<()> { // let p = [U256::from(1), U256::from(2)]; diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 3fa5a0ed..fdce266d 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -1,10 +1,9 @@ use std::str::FromStr; -use crate::bn254::inv_fp12; - use ethereum_types::{BigEndianHash, H256, U256}; use plonky2::field::types::Field; +use crate::bn254::{fp12_to_array, inv_fp12, vec_to_fp12}; use crate::generation::prover_input::EvmField::{ Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar, }; @@ -239,30 +238,8 @@ impl EvmField { } fn ext_inv(&self, xs: Vec, offset: usize) -> [U256; 12] { - let f0 = xs.clone().into_iter().nth(offset).unwrap(); - let f1 = xs.clone().into_iter().nth(offset + 1).unwrap(); - let f2 = xs.clone().into_iter().nth(offset + 2).unwrap(); - let f3 = xs.clone().into_iter().nth(offset + 3).unwrap(); - let f4 = xs.clone().into_iter().nth(offset + 4).unwrap(); - let f5 = xs.clone().into_iter().nth(offset + 5).unwrap(); - let f6 = xs.clone().into_iter().nth(offset + 6).unwrap(); - let f7 = xs.clone().into_iter().nth(offset + 7).unwrap(); - let f8 = xs.clone().into_iter().nth(offset + 8).unwrap(); - let f9 = xs.clone().into_iter().nth(offset + 9).unwrap(); - let f10 = xs.clone().into_iter().nth(offset + 10).unwrap(); - let f11 = xs.clone().into_iter().nth(offset + 11).unwrap(); - - let f = [ - [[f0, f1], [f2, f3], [f4, f5]], - [[f6, f7], [f8, f9], [f10, f11]], - ]; - - let g = inv_fp12(f); - - [ - g[0][0][0], g[0][0][1], g[0][1][0], g[0][1][1], g[0][2][0], g[0][2][1], g[1][0][0], - g[1][0][1], g[1][1][0], g[1][1][1], g[1][2][0], g[1][2][1], - ] + let vec: Vec = xs[offset..].to_vec(); + fp12_to_array(inv_fp12(vec_to_fp12(vec))) } fn ext_inv0(&self, xs: Vec) -> U256 {