From 0e082432755be00c7e825aabb380369839be7cd7 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 10:40:39 -0700 Subject: [PATCH 01/43] reorg --- evm/src/cpu/kernel/aggregator.rs | 7 ++++--- .../{invariant_exponent.asm => final_exponent.asm} | 0 .../curve_arithmetic/{tate_pairing.asm => miller_loop.asm} | 0 .../kernel/asm/curve/bn254/curve_arithmetic/pairing.asm | 0 4 files changed, 4 insertions(+), 3 deletions(-) rename evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/{invariant_exponent.asm => final_exponent.asm} (100%) rename evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/{tate_pairing.asm => miller_loop.asm} (100%) create mode 100644 evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index c529f5cf..52aa09c3 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -54,15 +54,16 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_mul.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/final_exponent.asm"), include_str!("asm/curve/bn254/curve_arithmetic/glv.asm"), - include_str!("asm/curve/bn254/curve_arithmetic/invariant_exponent.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/miller_loop.asm"), include_str!("asm/curve/bn254/curve_arithmetic/msm.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/pairing.asm"), include_str!("asm/curve/bn254/curve_arithmetic/precomputation.asm"), - include_str!("asm/curve/bn254/curve_arithmetic/tate_pairing.asm"), - include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_6_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_12_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"), + include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"), include_str!("asm/curve/bn254/field_arithmetic/util.asm"), include_str!("asm/curve/common.asm"), include_str!("asm/curve/secp256k1/curve_add.asm"), diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/invariant_exponent.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm similarity index 100% rename from evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/invariant_exponent.asm rename to evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm similarity index 100% rename from evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm rename to evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm new file mode 100644 index 00000000..e69de29b From 9b54ee43db862e373cd71d5b3a9232945e65e09c Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 13:12:47 -0700 Subject: [PATCH 02/43] refactor --- evm/src/bn254_pairing.rs | 4 +- .../bn254/curve_arithmetic/final_exponent.asm | 8 +-- .../bn254/curve_arithmetic/miller_loop.asm | 17 ++--- .../curve/bn254/curve_arithmetic/pairing.asm | 20 ++++++ evm/src/cpu/kernel/tests/bn254.rs | 65 +++++++------------ 5 files changed, 52 insertions(+), 62 deletions(-) diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 7277c2a8..6d2347a9 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -41,7 +41,7 @@ pub struct TwistedCurve { // The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { let miller_output = miller_loop(p, q); - invariant_exponent(miller_output) + final_exponent(miller_output) } /// Standard code for miller loop, can be found on page 99 at this url: @@ -120,7 +120,7 @@ pub fn gen_fp12_sparse(rng: &mut R) -> Fp12 { /// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 /// where 0 < a0, a1, a2 < p. Then the final power is given by /// y = y_3 * (y^a2)_2 * (y^-a1)_1 * (y^-a0) -pub fn invariant_exponent(f: Fp12) -> Fp12 { +pub fn final_exponent(f: Fp12) -> Fp12 { let mut y = f.frob(6) / f; y = y.frob(2) * y; let (y_a2, y_a1, y_a0) = get_custom_powers(y); diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm index 2fcd5d2b..85b1d639 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm @@ -2,18 +2,18 @@ /// (p^12 - 1)/N = (p^6 - 1) * (p^2 + 1) * (p^4 - p^2 + 1)/N /// and thus we can exponentiate by each factor sequentially. /// -/// def bn254_invariant_exponent(y: Fp12): +/// def bn254_final_exponent(y: Fp12): /// y = first_exp(y) /// y = second_exp(y) /// return final_exp(y) -global bn254_invariant_exponent: +global bn254_final_exponent: /// first, exponentiate by (p^6 - 1) via /// def first_exp(y): /// return y.frob(6) / y - // stack: out, retdest {out: y} - %stack (out) -> (out, 0, first_exp, out) + // stack: k, inp, out, retdest {out: y} + %stack (k, inp, out) -> (out, 0, first_exp, out) // stack: out, 0, first_exp, out, retdest {out: y} %jump(inv_fp254_12) first_exp: diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm index f09684bd..0067e0ec 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm @@ -1,12 +1,3 @@ -/// def tate(P: Curve, Q: TwistedCurve) -> Fp12: -/// out = miller_loop(P, Q) -/// return bn254_invariant_exponent(P, Q) -global bn254_tate: - // stack: inp, out, retdest - %stack (inp, out) -> (inp, out, bn254_invariant_exponent, out) - // stack: inp, out, bn254_invariant_exponent, out, retdest - %jump(bn254_miller) - /// def miller(P, Q): /// miller_init() /// miller_loop() @@ -35,13 +26,13 @@ global bn254_tate: /// mul_tangent() global bn254_miller: - // stack: ptr, out, retdest + // stack: ptr, out, retdest %stack (ptr, out) -> (out, 1, ptr, out) - // stack: out, 1, ptr, out, retdest + // stack: out, 1, ptr, out, retdest %mstore_kernel_bn254_pairing - // stack: ptr, out, retdest + // stack: ptr, out, retdest %load_fp254_6 - // stack: P, Q, out, retdest + // stack: P, Q, out, retdest %stack (P: 2) -> (0, 53, P, P) // stack: 0, 53, O, P, Q, out, retdest // the head 0 lets miller_loop start with POP diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index e69de29b..57008494 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -0,0 +1,20 @@ +/// def tate(pairs: List((Curve, TwistedCurve))) -> Fp12: +/// out = 1 +/// for P, Q in pairs: +/// out *= miller_loop(P, Q) +/// return bn254_final_exponent(out) + +global bn254_tate: + // stack: k, inp, out, retdest + DUP1 + ISZERO + // stack: end?, k, inp, out, retdest + %jumpi(bn254_final_exponent) + // stack: k, inp, out, retdest + + + + + %stack (inp, out) -> (inp, out, bn254_final_exponent, out) + // stack: inp, out, bn254_final_exponent, out, retdest + %jump(bn254_miller) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 8e71ffd6..48455b15 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -3,7 +3,7 @@ use ethereum_types::U256; use rand::Rng; use crate::bn254_pairing::{ - gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, + final_exponent, gen_fp12_sparse, miller_loop, tate, Curve, TwistedCurve, }; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, @@ -20,22 +20,21 @@ fn extract_stack(interpreter: Interpreter<'static>) -> Vec { .collect::>() } -fn setup_mul_fp6_test( - f: Fp6, - g: Fp6, - label: &str, -) -> InterpreterMemoryInitialization { +fn run_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> Vec { let mut stack = f.on_stack(); if label == "mul_fp254_6" { stack.extend(g.on_stack()); } stack.push(U256::from(0xdeadbeefu32)); - InterpreterMemoryInitialization { + + let setup = InterpreterMemoryInitialization { label: label.to_string(), stack, segment: BnPairing, memory: vec![], - } + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + extract_stack(interpreter) } #[test] @@ -44,14 +43,8 @@ fn test_mul_fp6() -> Result<()> { let f: Fp6 = rng.gen::>(); let g: Fp6 = rng.gen::>(); - let setup_normal: InterpreterMemoryInitialization = setup_mul_fp6_test(f, g, "mul_fp254_6"); - let setup_square: InterpreterMemoryInitialization = setup_mul_fp6_test(f, f, "square_fp254_6"); - - let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); - let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); - - let out_normal: Vec = extract_stack(intrptr_normal); - let out_square: Vec = extract_stack(intrptr_square); + let out_normal: Vec = run_mul_fp6_test(f, g, "mul_fp254_6"); + let out_square: Vec = run_mul_fp6_test(f, f, "square_fp254_6"); let exp_normal: Vec = (f * g).on_stack(); let exp_square: Vec = (f * f).on_stack(); @@ -62,14 +55,10 @@ fn test_mul_fp6() -> Result<()> { Ok(()) } -fn setup_mul_fp12_test( - out: usize, - f: Fp12, - g: Fp12, - label: &str, -) -> InterpreterMemoryInitialization { +fn run_mul_fp12_test(f: Fp12, g: Fp12, label: &str) -> Vec { let in0: usize = 200; let in1: usize = 212; + let out: usize = 224; let mut stack = vec![ U256::from(in0), @@ -80,37 +69,27 @@ fn setup_mul_fp12_test( if label == "square_fp254_12" { stack.remove(0); } - InterpreterMemoryInitialization { + + let setup = InterpreterMemoryInitialization { label: label.to_string(), stack, segment: BnPairing, memory: vec![(in0, f.on_stack()), (in1, g.on_stack())], - } + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + interpreter.extract_kernel_memory(BnPairing, out..out + 12) } #[test] fn test_mul_fp12() -> Result<()> { - let out: usize = 224; - let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let g: Fp12 = rng.gen::>(); let h: Fp12 = gen_fp12_sparse(&mut rng); - let setup_normal: InterpreterMemoryInitialization = - setup_mul_fp12_test(out, f, g, "mul_fp254_12"); - let setup_sparse: InterpreterMemoryInitialization = - setup_mul_fp12_test(out, f, h, "mul_fp254_12_sparse"); - let setup_square: InterpreterMemoryInitialization = - setup_mul_fp12_test(out, f, f, "square_fp254_12"); - - let intrptr_normal: Interpreter = run_interpreter_with_memory(setup_normal).unwrap(); - let intrptr_sparse: Interpreter = run_interpreter_with_memory(setup_sparse).unwrap(); - let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap(); - - let out_normal: Vec = intrptr_normal.extract_kernel_memory(BnPairing, out..out + 12); - let out_sparse: Vec = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12); - let out_square: Vec = intrptr_square.extract_kernel_memory(BnPairing, out..out + 12); + let out_normal: Vec = run_mul_fp12_test(f, g, "mul_fp254_12"); + let out_sparse: Vec = run_mul_fp12_test(f, h, "mul_fp254_12_sparse"); + let out_square: Vec = run_mul_fp12_test(f, f, "square_fp254_12"); let exp_normal: Vec = (f * g).on_stack(); let exp_sparse: Vec = (f * h).on_stack(); @@ -193,13 +172,13 @@ fn test_inv_fp12() -> Result<()> { } #[test] -fn test_invariant_exponent() -> Result<()> { +fn test_final_exponent() -> Result<()> { let ptr: usize = 200; let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let setup = InterpreterMemoryInitialization { - label: "bn254_invariant_exponent".to_string(), + label: "bn254_final_exponent".to_string(), stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], segment: BnPairing, memory: vec![(ptr, f.on_stack())], @@ -207,7 +186,7 @@ fn test_invariant_exponent() -> Result<()> { let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); - let expected: Vec = invariant_exponent(f).on_stack(); + let expected: Vec = final_exponent(f).on_stack(); assert_eq!(output, expected); From 21a1a98a7d235d914e2cd85b76d3847193cc2483 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 13:19:06 -0700 Subject: [PATCH 03/43] reorg --- evm/src/cpu/kernel/tests/bn254.rs | 39 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 48455b15..7acd20ee 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -102,13 +102,15 @@ fn test_mul_fp12() -> Result<()> { Ok(()) } -fn setup_frob_fp6_test(f: Fp6, n: usize) -> InterpreterMemoryInitialization { - InterpreterMemoryInitialization { - label: String::from("test_frob_fp254_6_") + &(n.to_string()), +fn run_frob_fp6_test(f: Fp6, n: usize) -> Vec { + let setup = InterpreterMemoryInitialization { + label: format!("test_frob_fp254_6_{}", n), stack: f.on_stack(), segment: BnPairing, memory: vec![], - } + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + extract_stack(interpreter) } #[test] @@ -116,35 +118,34 @@ fn test_frob_fp6() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp6 = rng.gen::>(); for n in 1..4 { - let setup_frob = setup_frob_fp6_test(f, n); - let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); - let out_frob: Vec = extract_stack(intrptr_frob); - let exp_frob: Vec = f.frob(n).on_stack(); - assert_eq!(out_frob, exp_frob); + let output: Vec = run_frob_fp6_test(f, n); + let expected: Vec = f.frob(n).on_stack(); + assert_eq!(output, expected); } Ok(()) } -fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryInitialization { - InterpreterMemoryInitialization { - label: String::from("test_frob_fp254_12_") + &(n.to_string()), +fn run_frob_fp12_test(f: Fp12, n: usize) -> Vec { + let ptr: usize = 200; + let setup = InterpreterMemoryInitialization { + label: format!("test_frob_fp254_12_{}", n), stack: vec![U256::from(ptr)], segment: BnPairing, memory: vec![(ptr, f.on_stack())], - } + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12) } #[test] fn test_frob_fp12() -> Result<()> { - let ptr: usize = 200; let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); + for n in [1, 2, 3, 6] { - let setup_frob = setup_frob_fp12_test(ptr, f, n); - let intrptr_frob: Interpreter = run_interpreter_with_memory(setup_frob).unwrap(); - let out_frob: Vec = intrptr_frob.extract_kernel_memory(BnPairing, ptr..ptr + 12); - let exp_frob: Vec = f.frob(n).on_stack(); - assert_eq!(out_frob, exp_frob); + let output = run_frob_fp12_test(f, n); + let expected: Vec = f.frob(n).on_stack(); + assert_eq!(output, expected); } Ok(()) } From 0df18d5ea8af7c231f7f0887fd3dfb9bb75ba98e Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 13:30:03 -0700 Subject: [PATCH 04/43] tests --- evm/src/cpu/kernel/tests/bn254.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 7acd20ee..9c318460 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -20,7 +20,7 @@ fn extract_stack(interpreter: Interpreter<'static>) -> Vec { .collect::>() } -fn run_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> Vec { +fn run_mul_fp6(f: Fp6, g: Fp6, label: &str) -> Vec { let mut stack = f.on_stack(); if label == "mul_fp254_6" { stack.extend(g.on_stack()); @@ -43,8 +43,8 @@ fn test_mul_fp6() -> Result<()> { let f: Fp6 = rng.gen::>(); let g: Fp6 = rng.gen::>(); - let out_normal: Vec = run_mul_fp6_test(f, g, "mul_fp254_6"); - let out_square: Vec = run_mul_fp6_test(f, f, "square_fp254_6"); + let out_normal: Vec = run_mul_fp6(f, g, "mul_fp254_6"); + let out_square: Vec = run_mul_fp6(f, f, "square_fp254_6"); let exp_normal: Vec = (f * g).on_stack(); let exp_square: Vec = (f * f).on_stack(); @@ -55,7 +55,7 @@ fn test_mul_fp6() -> Result<()> { Ok(()) } -fn run_mul_fp12_test(f: Fp12, g: Fp12, label: &str) -> Vec { +fn run_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Vec { let in0: usize = 200; let in1: usize = 212; let out: usize = 224; @@ -87,9 +87,9 @@ fn test_mul_fp12() -> Result<()> { let g: Fp12 = rng.gen::>(); let h: Fp12 = gen_fp12_sparse(&mut rng); - let out_normal: Vec = run_mul_fp12_test(f, g, "mul_fp254_12"); - let out_sparse: Vec = run_mul_fp12_test(f, h, "mul_fp254_12_sparse"); - let out_square: Vec = run_mul_fp12_test(f, f, "square_fp254_12"); + let out_normal: Vec = run_mul_fp12(f, g, "mul_fp254_12"); + let out_sparse: Vec = run_mul_fp12(f, h, "mul_fp254_12_sparse"); + let out_square: Vec = run_mul_fp12(f, f, "square_fp254_12"); let exp_normal: Vec = (f * g).on_stack(); let exp_sparse: Vec = (f * h).on_stack(); @@ -102,7 +102,7 @@ fn test_mul_fp12() -> Result<()> { Ok(()) } -fn run_frob_fp6_test(f: Fp6, n: usize) -> Vec { +fn run_frob_fp6(f: Fp6, n: usize) -> Vec { let setup = InterpreterMemoryInitialization { label: format!("test_frob_fp254_6_{}", n), stack: f.on_stack(), @@ -118,14 +118,14 @@ fn test_frob_fp6() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp6 = rng.gen::>(); for n in 1..4 { - let output: Vec = run_frob_fp6_test(f, n); + let output: Vec = run_frob_fp6(f, n); let expected: Vec = f.frob(n).on_stack(); assert_eq!(output, expected); } Ok(()) } -fn run_frob_fp12_test(f: Fp12, n: usize) -> Vec { +fn run_frob_fp12(f: Fp12, n: usize) -> Vec { let ptr: usize = 200; let setup = InterpreterMemoryInitialization { label: format!("test_frob_fp254_12_{}", n), @@ -143,7 +143,7 @@ fn test_frob_fp12() -> Result<()> { let f: Fp12 = rng.gen::>(); for n in [1, 2, 3, 6] { - let output = run_frob_fp12_test(f, n); + let output = run_frob_fp12(f, n); let expected: Vec = f.frob(n).on_stack(); assert_eq!(output, expected); } @@ -175,12 +175,13 @@ fn test_inv_fp12() -> Result<()> { #[test] fn test_final_exponent() -> Result<()> { let ptr: usize = 200; + let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let setup = InterpreterMemoryInitialization { label: "bn254_final_exponent".to_string(), - stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], + stack: vec![U256::zero(), U256::zero(), U256::from(ptr), U256::from(0xdeadbeefu32)], segment: BnPairing, memory: vec![(ptr, f.on_stack())], }; From d6584dcb7c483a4f961e1e297707bd65b542af4c Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 14:09:05 -0700 Subject: [PATCH 05/43] restructure tate test --- .../curve/bn254/curve_arithmetic/pairing.asm | 18 ++++++++++-------- evm/src/cpu/kernel/tests/bn254.rs | 12 ++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 57008494..56f5f243 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -5,16 +5,18 @@ /// return bn254_final_exponent(out) global bn254_tate: - // stack: k, inp, out, retdest + // stack: k , inp, out, retdest DUP1 ISZERO - // stack: end?, k, inp, out, retdest + // stack: end?, k , inp, out, retdest %jumpi(bn254_final_exponent) - // stack: k, inp, out, retdest - + // stack: k , inp, out, retdest + %sub_const(1) + // stack: k=k-1, inp, out, retdest - - - %stack (inp, out) -> (inp, out, bn254_final_exponent, out) - // stack: inp, out, bn254_final_exponent, out, retdest + %stack (k, inp, out) -> (k, inp, 200, mul_fp254_12, 200, out, out, bn254_tate, k, inp, out) + // stack: k, inp, 200, mul_fp254_12, 200, out, out, bn254_tate, k, inp, out retdest + %mul_const(6) + ADD + // stack: inp_k, 200, mul_fp254_12, 200, out, out, bn254_tate, k, inp, out retdest %jump(bn254_miller) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 9c318460..ad7c94c9 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -276,9 +276,9 @@ fn test_miller() -> Result<()> { } #[test] -fn test_tate() -> Result<()> { - let ptr: usize = 200; - let out: usize = 206; +fn test_pairing() -> Result<()> { + let ptr: usize = 224; + let out: usize = 212; let inputs: Vec = vec![ CURVE_GENERATOR.x.val, CURVE_GENERATOR.y.val, @@ -289,10 +289,10 @@ fn test_tate() -> Result<()> { ]; let setup = InterpreterMemoryInitialization { - label: "bn254_tate".to_string(), - stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], + label: "bn254_pairing".to_string(), + stack: vec![U256::one(), U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], segment: BnPairing, - memory: vec![(ptr, inputs)], + memory: vec![(ptr, inputs), (out, vec![U256::one()])], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); From 3628021a5bdb870f4f686cca1754ef3a66229f54 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 14:45:11 -0700 Subject: [PATCH 06/43] fmt --- evm/src/cpu/kernel/tests/bn254.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index ad7c94c9..1ac239ad 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -181,7 +181,12 @@ fn test_final_exponent() -> Result<()> { let setup = InterpreterMemoryInitialization { label: "bn254_final_exponent".to_string(), - stack: vec![U256::zero(), U256::zero(), U256::from(ptr), U256::from(0xdeadbeefu32)], + stack: vec![ + U256::zero(), + U256::zero(), + U256::from(ptr), + U256::from(0xdeadbeefu32), + ], segment: BnPairing, memory: vec![(ptr, f.on_stack())], }; @@ -290,7 +295,12 @@ fn test_pairing() -> Result<()> { let setup = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), - stack: vec![U256::one(), U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], + stack: vec![ + U256::one(), + U256::from(ptr), + U256::from(out), + U256::from(0xdeadbeefu32), + ], segment: BnPairing, memory: vec![(ptr, inputs), (out, vec![U256::one()])], }; From bbe64674d09d59eb8b3dcca9b1297b1996ba79fd Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 14:51:25 -0700 Subject: [PATCH 07/43] tests passing --- .../curve/bn254/curve_arithmetic/pairing.asm | 8 ++-- evm/src/cpu/kernel/tests/bn254.rs | 42 ++++++++++--------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 56f5f243..829ceff2 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -4,7 +4,7 @@ /// out *= miller_loop(P, Q) /// return bn254_final_exponent(out) -global bn254_tate: +global bn254_pairing: // stack: k , inp, out, retdest DUP1 ISZERO @@ -14,9 +14,9 @@ global bn254_tate: %sub_const(1) // stack: k=k-1, inp, out, retdest - %stack (k, inp, out) -> (k, inp, 200, mul_fp254_12, 200, out, out, bn254_tate, k, inp, out) - // stack: k, inp, 200, mul_fp254_12, 200, out, out, bn254_tate, k, inp, out retdest + %stack (k, inp, out) -> (k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing, k, inp, out) + // stack: k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing, k, inp, out retdest %mul_const(6) ADD - // stack: inp_k, 200, mul_fp254_12, 200, out, out, bn254_tate, k, inp, out retdest + // stack: inp_k, 200, mul_fp254_12, 200, out, out, bn254_pairing, k, inp, out retdest %jump(bn254_miller) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 1ac239ad..38574ca1 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -20,7 +20,7 @@ fn extract_stack(interpreter: Interpreter<'static>) -> Vec { .collect::>() } -fn run_mul_fp6(f: Fp6, g: Fp6, label: &str) -> Vec { +fn run_bn_mul_fp6(f: Fp6, g: Fp6, label: &str) -> Vec { let mut stack = f.on_stack(); if label == "mul_fp254_6" { stack.extend(g.on_stack()); @@ -38,13 +38,13 @@ fn run_mul_fp6(f: Fp6, g: Fp6, label: &str) -> Vec { } #[test] -fn test_mul_fp6() -> Result<()> { +fn test_bn_mul_fp6() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp6 = rng.gen::>(); let g: Fp6 = rng.gen::>(); - let out_normal: Vec = run_mul_fp6(f, g, "mul_fp254_6"); - let out_square: Vec = run_mul_fp6(f, f, "square_fp254_6"); + let out_normal: Vec = run_bn_mul_fp6(f, g, "mul_fp254_6"); + let out_square: Vec = run_bn_mul_fp6(f, f, "square_fp254_6"); let exp_normal: Vec = (f * g).on_stack(); let exp_square: Vec = (f * f).on_stack(); @@ -55,7 +55,7 @@ fn test_mul_fp6() -> Result<()> { Ok(()) } -fn run_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Vec { +fn run_bn_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Vec { let in0: usize = 200; let in1: usize = 212; let out: usize = 224; @@ -81,15 +81,15 @@ fn run_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Vec { } #[test] -fn test_mul_fp12() -> Result<()> { +fn test_bn_mul_fp12() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let g: Fp12 = rng.gen::>(); let h: Fp12 = gen_fp12_sparse(&mut rng); - let out_normal: Vec = run_mul_fp12(f, g, "mul_fp254_12"); - let out_sparse: Vec = run_mul_fp12(f, h, "mul_fp254_12_sparse"); - let out_square: Vec = run_mul_fp12(f, f, "square_fp254_12"); + let out_normal: Vec = run_bn_mul_fp12(f, g, "mul_fp254_12"); + let out_sparse: Vec = run_bn_mul_fp12(f, h, "mul_fp254_12_sparse"); + let out_square: Vec = run_bn_mul_fp12(f, f, "square_fp254_12"); let exp_normal: Vec = (f * g).on_stack(); let exp_sparse: Vec = (f * h).on_stack(); @@ -102,7 +102,7 @@ fn test_mul_fp12() -> Result<()> { Ok(()) } -fn run_frob_fp6(f: Fp6, n: usize) -> Vec { +fn run_bn_frob_fp6(f: Fp6, n: usize) -> Vec { let setup = InterpreterMemoryInitialization { label: format!("test_frob_fp254_6_{}", n), stack: f.on_stack(), @@ -114,18 +114,18 @@ fn run_frob_fp6(f: Fp6, n: usize) -> Vec { } #[test] -fn test_frob_fp6() -> Result<()> { +fn test_bn_frob_fp6() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp6 = rng.gen::>(); for n in 1..4 { - let output: Vec = run_frob_fp6(f, n); + let output: Vec = run_bn_frob_fp6(f, n); let expected: Vec = f.frob(n).on_stack(); assert_eq!(output, expected); } Ok(()) } -fn run_frob_fp12(f: Fp12, n: usize) -> Vec { +fn run_bn_frob_fp12(f: Fp12, n: usize) -> Vec { let ptr: usize = 200; let setup = InterpreterMemoryInitialization { label: format!("test_frob_fp254_12_{}", n), @@ -138,12 +138,12 @@ fn run_frob_fp12(f: Fp12, n: usize) -> Vec { } #[test] -fn test_frob_fp12() -> Result<()> { +fn test_bn_frob_fp12() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); for n in [1, 2, 3, 6] { - let output = run_frob_fp12(f, n); + let output = run_bn_frob_fp12(f, n); let expected: Vec = f.frob(n).on_stack(); assert_eq!(output, expected); } @@ -151,7 +151,7 @@ fn test_frob_fp12() -> Result<()> { } #[test] -fn test_inv_fp12() -> Result<()> { +fn test_bn_inv_fp12() -> Result<()> { let ptr: usize = 200; let inv: usize = 212; let mut rng = rand::thread_rng(); @@ -173,7 +173,7 @@ fn test_inv_fp12() -> Result<()> { } #[test] -fn test_final_exponent() -> Result<()> { +fn test_bn_final_exponent() -> Result<()> { let ptr: usize = 200; let mut rng = rand::thread_rng(); @@ -281,9 +281,11 @@ fn test_miller() -> Result<()> { } #[test] -fn test_pairing() -> Result<()> { - let ptr: usize = 224; +fn test_bn_pairing() -> Result<()> { + let acc: usize = 200; let out: usize = 212; + let ptr: usize = 224; + let inputs: Vec = vec![ CURVE_GENERATOR.x.val, CURVE_GENERATOR.y.val, @@ -302,7 +304,7 @@ fn test_pairing() -> Result<()> { U256::from(0xdeadbeefu32), ], segment: BnPairing, - memory: vec![(ptr, inputs), (out, vec![U256::one()])], + memory: vec![(ptr, inputs), (out, vec![U256::from(acc)])], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); From b661a70904d69f572b8150ec5c49a9e45c1cd032 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 23:06:02 -0700 Subject: [PATCH 08/43] twisted check --- evm/src/cpu/kernel/aggregator.rs | 1 + .../curve/bn254/curve_arithmetic/pairing.asm | 54 ++++++++++- .../bn254/curve_arithmetic/twisted_curve.asm | 94 +++++++++++++++++++ .../asm/curve/bn254/field_arithmetic/util.asm | 50 ++++++++++ evm/src/cpu/kernel/constants/mod.rs | 10 +- 5 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 52aa09c3..2e6c38f1 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -60,6 +60,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/curve/bn254/curve_arithmetic/msm.asm"), include_str!("asm/curve/bn254/curve_arithmetic/pairing.asm"), include_str!("asm/curve/bn254/curve_arithmetic/precomputation.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_6_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_12_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"), diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 829ceff2..5de0e5e0 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -1,10 +1,56 @@ -/// def tate(pairs: List((Curve, TwistedCurve))) -> Fp12: +/// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Fp12: +/// +/// for P, Q in pairs: +/// assert(is_valid(P)) +/// assert(is_valid(Q)) +/// /// out = 1 /// for P, Q in pairs: /// out *= miller_loop(P, Q) +/// /// return bn254_final_exponent(out) global bn254_pairing: + // stack: k, inp, out, retdest + DUP1 + // stack: k, k, inp, out, retdest + +bn254_input_check: + // stack: j , k, inp + DUP1 + ISZERO + // stack: end?, j , k, inp + %jump(bn254_pairing_start) + // stack: j , k, inp + %sub_const(1) + // stack: j=j-1, k, inp + + stack (j, k, inp) -> (j, inp, j, k, inp) + // stack: j, inp, j, k, inp + %mul_const(6) + ADD + // stack: inp_j=inp+6j, j, k, inp + DUP1 + %load_fp254_2 + // stack: P_j, inp_j, j, k, inp + %bn_check + // stack: valid?, inp_j, j, k, inp + %assert_nonzero + // stack: inp_j, j, k, inp + %add_const(2) + %load_fp254_4 + // stack: Q_j, j, k, inp + %bn_check_twisted + // stack: valid?, j, k, inp + %assert_nonzero + // stack: j, k, inp + %jump(bn254_input_check) + +bn254_pairing_start: + // stack: k, k, inp, out, retdest + POP + +bn254_pairing_loop: // stack: k , inp, out, retdest DUP1 ISZERO @@ -14,9 +60,9 @@ global bn254_pairing: %sub_const(1) // stack: k=k-1, inp, out, retdest - %stack (k, inp, out) -> (k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing, k, inp, out) - // stack: k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing, k, inp, out retdest + %stack (k, inp, out) -> (k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing_loop, k, inp, out) + // stack: k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing_loop, k, inp, out retdest %mul_const(6) ADD - // stack: inp_k, 200, mul_fp254_12, 200, out, out, bn254_pairing, k, inp, out retdest + // stack: inp_k, 200, mul_fp254_12, 200, out, out, bn254_pairing_loop, k, inp, out retdest %jump(bn254_miller) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm new file mode 100644 index 00000000..d2029848 --- /dev/null +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -0,0 +1,94 @@ +// Check if (X,Y) is a valid curve point. +// Returns (range & curve) || is_identity +// where +// range = (x < N) & (x_ < N) & (y < N) & (y_ < N) +// curve = Y^2 == X^3 + A +// ident = (x,y) == (0,0) + +%macro bn_check_twisted + // stack: x, x_, y, y_ + %bn_check_twisted_range + // stack: range, x, x_, y, y_ + %bn_check_twisted_curve + // stack: curve , range, x, x_, y, y_ + AND + // stack: curve & range, x, x_, y, y_ + SWAP4 + // stack: y_, x, x_, y, curve & range + %bn_check_twisted_ident + // stack: ident , curve & range + OR + // stack: ident || (curve & range) + +%macro bn_check_twisted_range + // stack: x, x_, y, y_ + PUSH @BN_BASE + // stack: N, x, x_, y, y_ + %stack (N) -> (N, N, N, N) + // stack: N, N, N, N, x, x_, y, y_ + DUP8 + // stack: y_ , N, N, N, N, x, x_, y, y_ + LT + // stack: y_ < N, N, N, N, x, x_, y, y_ + SWAP3 + // stack: N, N, N, y_ < N, x, x_, y, y_ + DUP7 + // stack: y , N, N, N, y_ < N, x, x_, y, y_ + LT + // stack: y < N, N, N, y_ < N, x, x_, y, y_ + SWAP2 + // stack: N, N, y < N, y_ < N, x, x_, y, y_ + DUP6 + // stack: x_ , N, N, y < N, y_ < N, x, x_, y, y_ + LT + // stack: x_ < N, N, y < N, y_ < N, x, x_, y, y_ + SWAP1 + // stack: N, x_ < N, y < N, y_ < N, x, x_, y, y_ + DUP5 + // stack: x , N, x_ < N, y < N, y_ < N, x, x_, y, y_ + LT + // stack: x < N, x_ < N, y < N, y_ < N, x, x_, y, y_ + AND + AND + AND + // stack: range, x, x_, y, y_ +%endmacro + +%macro bn_check_twisted_curve + // stack: range, X, Y + %stack (range, X: 2, Y: 2) -> (Y, Y, range, X) + // stack: Y, Y, range, X, Y + %mul_fp254_2 + // stack: Y^2, range, X, Y + PUSH @BN_TWISTED_IM + PUSH @BN_TWISTED_RE + // stack: A, Y^2, range, X, Y + %stack (A: 2, Y2: 2, range, X: 2) -> (X, X, X, A, Y2, range, X) + // stack: X, X, X, A, Y^2, range, X, Y + %mul_fp254_2 + %mul_fp254_2 + // stack: X^3 , A, Y^2, range, X, Y + %add_fp254_2 + // stack: X^3 + A, Y^2, range, X, Y + %eq_fp254_2 + // stack: curve, range, X, Y +%endmacro + +%macro bn_check_twisted_ident + SWAP2 + // stack: a , b , c , d + ISZERO + SWAP3 + // stack: d , b , c , a==0 + ISZERO + SWAP2 + // stack: c , b , d==0, a==0 + ISZERO + SWAP1 + // stack: b , c==0, d==0, a==0 + ISZERO + // stack: b==0, c==0, d==0, a==0 + AND + AND + AND +%endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm index af074714..82617e8f 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm @@ -67,6 +67,31 @@ // stack: cx, cy %endmacro +%macro eq_fp254_2 + // stack: x, x_, y, y_ + SWAP3 + // stack: y_, x_, y, x + EQ + // stack: y_==x_, y, x + SWAP2 + // stack: x, y, y_==x_ + EQ + // stack: x==y, y_==x_ + AND +%endmacro + +%macro add_fp254_2 + // stack: x, x_, y, y_ + SWAP3 + // stack: y_, x_, y, x + ADDFP254 + // stack: z_, y, x + SWAP2 + // stack: x, y, z_ + ADDFP254 + // stack: z, z_ +%endmacro + /// Given z = x + iy: Fp254_2, return complex conjugate z': Fp254_2 /// where input is represented z.re, z.im and output as z'.im, z'.re /// cost: 9; note this returns y, x for the output x + yi @@ -116,6 +141,31 @@ // stack: ac - bd, bc + ad %endmacro +// load twisted curve + +%macro load_fp254_4 + // stack: ptr + DUP1 + %add_const(2) + // stack: ind2, ptr + %mload_kernel_bn254_pairing + // stack: x2, ptr + DUP2 + %add_const(1) + // stack: ind1, x2, ptr + %mload_kernel_bn254_pairing + // stack: x1, x2, ptr + DUP3 + %add_const(3) + // stack: ind3, x1, x2, ptr + %mload_kernel_bn254_pairing + // stack: x3, x1, x2, ptr + SWAP3 + // stack: ind0, x1, x2, x3 + %mload_kernel_bn254_pairing + // stack: x0, x1, x2, x3 +%endmacro + // fp254_6 macros %macro load_fp254_6 diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index 75a96403..0f64bcc9 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -83,7 +83,7 @@ const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [ ), ]; -const EC_CONSTANTS: [(&str, [u8; 32]); 18] = [ +const EC_CONSTANTS: [(&str, [u8; 32]); 20] = [ ( "U256_MAX", hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), @@ -92,6 +92,14 @@ const EC_CONSTANTS: [(&str, [u8; 32]); 18] = [ "BN_BASE", hex!("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"), ), + ( + "BN_TWISTED_RE", + hex!("2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5"), + ), + ( + "BN_TWISTED_IM", + hex!("009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2"), + ), ( "BN_SCALAR", hex!("30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"), From 82bca7fa340821b484163638be20c86f7b96e902 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 23:09:27 -0700 Subject: [PATCH 09/43] error --- evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm | 2 +- .../kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 5de0e5e0..4f3fca6b 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -25,7 +25,7 @@ bn254_input_check: %sub_const(1) // stack: j=j-1, k, inp - stack (j, k, inp) -> (j, inp, j, k, inp) + %stack (j, k, inp) -> (j, inp, j, k, inp) // stack: j, inp, j, k, inp %mul_const(6) ADD diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm index d2029848..508664db 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -19,6 +19,7 @@ // stack: ident , curve & range OR // stack: ident || (curve & range) +%endmacro %macro bn_check_twisted_range // stack: x, x_, y, y_ From 099c4b9702fa176b6853e6ae5adc780d67af601d Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 19 Apr 2023 23:34:50 -0700 Subject: [PATCH 10/43] msg --- .../cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm | 1 + .../kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 4f3fca6b..00c03051 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -12,6 +12,7 @@ global bn254_pairing: // stack: k, inp, out, retdest + %jump(bn254_pairing_loop) // this short circuits the input checks DUP1 // stack: k, k, inp, out, retdest diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm index 508664db..5b331d68 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -1,9 +1,9 @@ // Check if (X,Y) is a valid curve point. -// Returns (range & curve) || is_identity +// Returns (range & curve) || ident // where // range = (x < N) & (x_ < N) & (y < N) & (y_ < N) // curve = Y^2 == X^3 + A -// ident = (x,y) == (0,0) +// ident = (X,Y) == (0,0) %macro bn_check_twisted // stack: x, x_, y, y_ From 44a623d453f752fb4d46bfbc6077d8c5b397e6e1 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 14:07:45 -0700 Subject: [PATCH 11/43] initialize out in asm --- .../asm/curve/bn254/curve_arithmetic/pairing.asm | 11 ++++++++--- .../curve/bn254/curve_arithmetic/twisted_curve.asm | 2 +- evm/src/cpu/kernel/tests/bn254.rs | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 00c03051..781c81d9 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -1,8 +1,8 @@ /// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Fp12: /// /// for P, Q in pairs: -/// assert(is_valid(P)) -/// assert(is_valid(Q)) +/// assert(P.is_valid) +/// assert(Q.is_valid) /// /// out = 1 /// for P, Q in pairs: @@ -11,7 +11,12 @@ /// return bn254_final_exponent(out) global bn254_pairing: - // stack: k, inp, out, retdest + // stack: k, inp, out, retdest + %stack (k, inp, out) -> (out, 1, k, inp, out) + // stack: out, 1, k, inp, out, retdest + %mstore_kernel_bn254_pairing + // stack: k, inp, out, retdest + %jump(bn254_pairing_loop) // this short circuits the input checks DUP1 // stack: k, k, inp, out, retdest diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm index 5b331d68..579ec212 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -2,7 +2,7 @@ // Returns (range & curve) || ident // where // range = (x < N) & (x_ < N) & (y < N) & (y_ < N) -// curve = Y^2 == X^3 + A +// curve = Y^2 == X^3 + 3/(9+i) // ident = (X,Y) == (0,0) %macro bn_check_twisted diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 38574ca1..c22b114a 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -304,7 +304,7 @@ fn test_bn_pairing() -> Result<()> { U256::from(0xdeadbeefu32), ], segment: BnPairing, - memory: vec![(ptr, inputs), (out, vec![U256::from(acc)])], + memory: vec![(ptr, inputs)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); From c01b2bf2c2cb7491bf06eb17a328beb855ff57ce Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 19:56:54 -0700 Subject: [PATCH 12/43] minor --- .../asm/curve/bn254/curve_arithmetic/curve_add.asm | 4 ++-- .../asm/curve/bn254/curve_arithmetic/pairing.asm | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm index 499d88d5..a43c4047 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm @@ -201,8 +201,8 @@ global bn_double: %jump(bn_add_equal_points) // Check if (x,y) is a valid curve point. -// Returns (range & curve) || is_identity -// where +// Returns (range & curve) || ident +// where // range = (x < N) & (y < N) // curve = y^2 == (x^3 + 3) // ident = (x,y) == (0,0) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 781c81d9..57656259 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -16,17 +16,17 @@ global bn254_pairing: // stack: out, 1, k, inp, out, retdest %mstore_kernel_bn254_pairing // stack: k, inp, out, retdest - - %jump(bn254_pairing_loop) // this short circuits the input checks + + // %jump(bn254_pairing_loop) // this short circuits the input checks DUP1 - // stack: k, k, inp, out, retdest + // stack: k, k, inp, out, retdest bn254_input_check: // stack: j , k, inp DUP1 ISZERO // stack: end?, j , k, inp - %jump(bn254_pairing_start) + %jumpi(bn254_pairing_start) // stack: j , k, inp %sub_const(1) // stack: j=j-1, k, inp @@ -37,6 +37,7 @@ bn254_input_check: ADD // stack: inp_j=inp+6j, j, k, inp DUP1 + // stack: inp_j, inp_j, j, k, inp %load_fp254_2 // stack: P_j, inp_j, j, k, inp %bn_check @@ -46,6 +47,7 @@ bn254_input_check: %add_const(2) %load_fp254_4 // stack: Q_j, j, k, inp + %pop4 %bn_check_twisted // stack: valid?, j, k, inp %assert_nonzero @@ -53,7 +55,7 @@ bn254_input_check: %jump(bn254_input_check) bn254_pairing_start: - // stack: k, k, inp, out, retdest + // stack: 0, k, inp, out, retdest POP bn254_pairing_loop: From f1bbf66cda171f42c7c42561cb045f34fdb8e53a Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 20:02:15 -0700 Subject: [PATCH 13/43] it works --- .../cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm | 1 - .../asm/curve/bn254/curve_arithmetic/twisted_curve.asm | 5 ++--- evm/src/cpu/kernel/tests/bn254.rs | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 57656259..b5e8a034 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -47,7 +47,6 @@ bn254_input_check: %add_const(2) %load_fp254_4 // stack: Q_j, j, k, inp - %pop4 %bn_check_twisted // stack: valid?, j, k, inp %assert_nonzero diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm index 579ec212..b87828de 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -57,12 +57,11 @@ %macro bn_check_twisted_curve // stack: range, X, Y - %stack (range, X: 2, Y: 2) -> (Y, Y, range, X) + %stack (range, X: 2, Y: 2) -> (Y, Y, range, X, Y) // stack: Y, Y, range, X, Y %mul_fp254_2 // stack: Y^2, range, X, Y - PUSH @BN_TWISTED_IM - PUSH @BN_TWISTED_RE + %stack () -> (@BN_TWISTED_RE, @BN_TWISTED_IM) // stack: A, Y^2, range, X, Y %stack (A: 2, Y2: 2, range, X: 2) -> (X, X, X, A, Y2, range, X) // stack: X, X, X, A, Y^2, range, X, Y diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index c22b114a..ecc1ed1d 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -282,7 +282,6 @@ fn test_miller() -> Result<()> { #[test] fn test_bn_pairing() -> Result<()> { - let acc: usize = 200; let out: usize = 212; let ptr: usize = 224; From ff0695d76046ff326e17f669e89fad21ce299b9d Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 20:31:26 -0700 Subject: [PATCH 14/43] renumber memory --- .../bn254/curve_arithmetic/miller_loop.asm | 50 +++++++++---------- .../curve/bn254/curve_arithmetic/pairing.asm | 30 +++++------ 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm index 0067e0ec..ce43d4f1 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm @@ -100,19 +100,19 @@ mul_tangent: // stack: out, out, mul_tangent_1, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out %jump(square_fp254_12) mul_tangent_1: - // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out + // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out DUP13 DUP13 DUP13 DUP13 - // stack: Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out + // stack: Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out DUP11 DUP11 - // stack: O, Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out + // stack: O, Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out %tangent - // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} - %stack (out) -> (out, 0, out) - // stack: out, 0, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} + %stack (out) -> (out, 12, out) + // stack: out, 12, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} %jump(mul_fp254_12_sparse) mul_tangent_2: // stack: retdest, 0xnm, times, O, P, Q, out {0: line} @@ -137,26 +137,26 @@ after_double: /// O += P mul_cord: - // stack: 0xnm, times, O, P, Q, out + // stack: 0xnm, times, O, P, Q, out PUSH mul_cord_1 - // stack: mul_cord_1, 0xnm, times, O, P, Q, out + // stack: mul_cord_1, 0xnm, times, O, P, Q, out DUP11 DUP11 DUP11 DUP11 - // stack: Q, mul_cord_1, 0xnm, times, O, P, Q, out + // stack: Q, mul_cord_1, 0xnm, times, O, P, Q, out DUP9 DUP9 - // stack: O, Q, mul_cord_1, 0xnm, times, O, P, Q, out + // stack: O, Q, mul_cord_1, 0xnm, times, O, P, Q, out DUP13 DUP13 - // stack: P, O, Q, mul_cord_1, 0xnm, times, O, P, Q, out + // stack: P, O, Q, mul_cord_1, 0xnm, times, O, P, Q, out %cord - // stack: mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: mul_cord_1, 0xnm, times, O, P, Q, out {0: line} DUP12 - // stack: out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} - %stack (out) -> (out, 0, out) - // stack: out, 0, out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + %stack (out) -> (out, 12, out) + // stack: out, 12, out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} %jump(mul_fp254_12_sparse) mul_cord_1: // stack: 0xnm, times, O , P, Q, out @@ -193,7 +193,7 @@ after_add: // stack: py^2 , 9, px, py, qx, qx_, qy, qy_ SUBFP254 // stack: py^2 - 9, px, py, qx, qx_, qy, qy_ - %mstore_kernel_bn254_pairing(0) + %mstore_kernel_bn254_pairing(12) // stack: px, py, qx, qx_, qy, qy_ DUP1 MULFP254 @@ -209,7 +209,7 @@ after_add: DUP3 MULFP254 // stack: (-3*px^2)qx, py, -3px^2, qx_, qy, qy_ - %mstore_kernel_bn254_pairing(2) + %mstore_kernel_bn254_pairing(14) // stack: py, -3px^2, qx_, qy, qy_ PUSH 2 MULFP254 @@ -219,15 +219,15 @@ after_add: DUP4 MULFP254 // stack: (2py)qy, -3px^2, qx_, 2py, qy_ - %mstore_kernel_bn254_pairing(8) + %mstore_kernel_bn254_pairing(20) // stack: -3px^2, qx_, 2py, qy_ MULFP254 // stack: (-3px^2)*qx_, 2py, qy_ - %mstore_kernel_bn254_pairing(3) + %mstore_kernel_bn254_pairing(15) // stack: 2py, qy_ MULFP254 // stack: (2py)*qy_ - %mstore_kernel_bn254_pairing(9) + %mstore_kernel_bn254_pairing(21) %endmacro /// def cord(p1x, p1y, p2x, p2y, qx, qy): @@ -249,7 +249,7 @@ after_add: // stack: p1y*p2x , p2y*p1x, p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ SUBFP254 // stack: p1y*p2x - p2y*p1x, p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ - %mstore_kernel_bn254_pairing(0) + %mstore_kernel_bn254_pairing(12) // stack: p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ SWAP3 // stack: p2y , p1y, p2x , p1x, qx, qx_, qy, qy_ @@ -264,20 +264,20 @@ after_add: DUP5 MULFP254 // stack: (p1x - p2x)qy, p2y - p1y, qx, qx_, p1x - p2x, qy_ - %mstore_kernel_bn254_pairing(8) + %mstore_kernel_bn254_pairing(20) // stack: p2y - p1y, qx, qx_, p1x - p2x, qy_ SWAP1 // stack: qx, p2y - p1y, qx_, p1x - p2x, qy_ DUP2 MULFP254 // stack: (p2y - p1y)qx, p2y - p1y, qx_, p1x - p2x, qy_ - %mstore_kernel_bn254_pairing(2) + %mstore_kernel_bn254_pairing(14) // stack: p2y - p1y, qx_, p1x - p2x, qy_ MULFP254 // stack: (p2y - p1y)qx_, p1x - p2x, qy_ - %mstore_kernel_bn254_pairing(3) + %mstore_kernel_bn254_pairing(15) // stack: p1x - p2x, qy_ MULFP254 // stack: (p1x - p2x)*qy_ - %mstore_kernel_bn254_pairing(9) + %mstore_kernel_bn254_pairing(21) %endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index b5e8a034..3c91192b 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -11,15 +11,8 @@ /// return bn254_final_exponent(out) global bn254_pairing: - // stack: k, inp, out, retdest - %stack (k, inp, out) -> (out, 1, k, inp, out) - // stack: out, 1, k, inp, out, retdest - %mstore_kernel_bn254_pairing - // stack: k, inp, out, retdest - - // %jump(bn254_pairing_loop) // this short circuits the input checks + // stack: k, inp, out, retdest DUP1 - // stack: k, k, inp, out, retdest bn254_input_check: // stack: j , k, inp @@ -54,22 +47,25 @@ bn254_input_check: %jump(bn254_input_check) bn254_pairing_start: - // stack: 0, k, inp, out, retdest - POP + // stack: 0, k, inp, out, retdest + %stack (j, k, inp, out) -> (out, 1, k, inp, out) + // stack: out, 1, k, inp, out, retdest + %mstore_kernel_bn254_pairing + // stack: k, inp, out, retdest bn254_pairing_loop: - // stack: k , inp, out, retdest + // stack: k, inp, out, retdest DUP1 ISZERO - // stack: end?, k , inp, out, retdest + // stack: end?, k, inp, out, retdest %jumpi(bn254_final_exponent) - // stack: k , inp, out, retdest + // stack: k, inp, out, retdest %sub_const(1) - // stack: k=k-1, inp, out, retdest + // stack: k=k-1, inp, out, retdest - %stack (k, inp, out) -> (k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing_loop, k, inp, out) - // stack: k, inp, 200, mul_fp254_12, 200, out, out, bn254_pairing_loop, k, inp, out retdest + %stack (k, inp, out) -> (k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out) + // stack: k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out retdest %mul_const(6) ADD - // stack: inp_k, 200, mul_fp254_12, 200, out, out, bn254_pairing_loop, k, inp, out retdest + // stack: inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out retdest %jump(bn254_miller) From 5075224665082d4785ec7442a45d7fecbb80ed71 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 20:33:49 -0700 Subject: [PATCH 15/43] clean --- .../bn254/field_arithmetic/degree_12_mul.asm | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm index 5fd47e80..7c0538f4 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm @@ -2,32 +2,6 @@ ///// GENERAL FP12 MULTIPLICATION ///// /////////////////////////////////////// -/// cost: 1063 - -/// fp254_6 functions: -/// fn | num | ops | cost -/// ------------------------- -/// load | 8 | 40 | 320 -/// store | 5 | 40 | 200 -/// dup | 5 | 6 | 30 -/// swap | 4 | 16 | 64 -/// add | 4 | 16 | 64 -/// subr | 1 | 17 | 17 -/// mul | 3 | 157 | 471 -/// i9 | 1 | 9 | 9 -/// -/// lone stack operations: -/// op | num -/// ------------ -/// ADD | 3 -/// SWAP | 2 -/// DUP | 6 -/// PUSH | 6 -/// POP | 2 -/// JUMP | 6 -/// -/// TOTAL: 1201 - /// inputs: /// F = f + f'z /// G = g + g'z @@ -141,29 +115,6 @@ mul_fp254_12_3: ///// SPARSE FP12 MULTIPLICATION ///// ////////////////////////////////////// -/// cost: 645 - -/// fp254_6 functions: -/// fn | num | ops | cost -/// --------------------------- -/// load | 2 | 40 | 80 -/// store | 2 | 40 | 80 -/// dup | 4 | 6 | 24 -/// swap | 4 | 16 | 64 -/// add | 4 | 16 | 64 -/// mul_fp254_ | 2 | 21 | 42 -/// mul_fp254_2 | 4 | 59 | 236 -/// -/// lone stack operations: -/// op | num -/// ------------ -/// ADD | 6 -/// DUP | 9 -/// PUSH | 6 -/// POP | 5 -/// -/// TOTAL: 618 - /// input: /// F = f + f'z /// G = g0 + (G1)t + (G2)tz @@ -277,32 +228,6 @@ global mul_fp254_12_sparse: ///// FP12 SQUARING ///// ///////////////////////// -/// cost: 646 - -/// fp254_6 functions: -/// fn | num | ops | cost -/// ------------------------- -/// load | 2 | 40 | 80 -/// store | 2 | 40 | 80 -/// dup | 2 | 6 | 12 -/// swap | 2 | 16 | 32 -/// add | 1 | 16 | 16 -/// mul | 1 | 157 | 157 -/// sq | 2 | 101 | 202 -/// dbl | 1 | 13 | 13 -/// -/// lone stack operations: -/// op | num -/// ------------ -/// ADD | 3 -/// SWAP | 4 -/// DUP | 5 -/// PUSH | 6 -/// POP | 3 -/// JUMP | 4 -/// -/// TOTAL: - /// input: /// F = f + f'z /// From 0c55aa04ee041e8e948940b1f6e2dcce5df05769 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 20:35:07 -0700 Subject: [PATCH 16/43] clean --- evm/src/cpu/kernel/tests/bn254.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index ecc1ed1d..148847da 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -253,7 +253,7 @@ pub const TWISTED_GENERATOR: TwistedCurve = { }; #[test] -fn test_miller() -> Result<()> { +fn test_bn_miller() -> Result<()> { let ptr: usize = 200; let out: usize = 206; let inputs: Vec = vec![ @@ -282,8 +282,8 @@ fn test_miller() -> Result<()> { #[test] fn test_bn_pairing() -> Result<()> { - let out: usize = 212; - let ptr: usize = 224; + let out: usize = 200; + let ptr: usize = 212; let inputs: Vec = vec![ CURVE_GENERATOR.x.val, From 26d99a9b151b65ba07e619dd237ad1f388d44bbd Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 20 Apr 2023 20:54:13 -0700 Subject: [PATCH 17/43] memory compress --- .../bn254/curve_arithmetic/final_exponent.asm | 214 +++++++++--------- .../bn254/curve_arithmetic/miller_loop.asm | 10 + .../bn254/field_arithmetic/degree_12_mul.asm | 76 +++---- .../curve/bn254/field_arithmetic/inverse.asm | 9 +- evm/src/cpu/kernel/tests/bn254.rs | 22 +- 5 files changed, 172 insertions(+), 159 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm index 85b1d639..f8e48807 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm @@ -53,18 +53,18 @@ second_exp: final_exp: // stack: val, retdest - %stack (val) -> (val, 12, val) - // stack: val, 12, val, retdest + %stack (val) -> (val, 0, val) + // stack: val, 0, val, retdest %move_fp254_12 - // stack: 12, val, retdest {12: sqr} + // stack: 0, val, retdest {0: sqr} %stack () -> (1, 1, 1) - // stack: 1, 1, 1, 12, val, retdest + // stack: 1, 1, 1, 0, val, retdest + %mstore_kernel_bn254_pairing(12) %mstore_kernel_bn254_pairing(24) - %mstore_kernel_bn254_pairing(36) - %mstore_kernel_bn254_pairing(48) - // stack: 12, val, retdest {12: sqr, 24: y0, 36: y2, 48: y4} + %mstore_kernel_bn254_pairing(36) + // stack: 0, val, retdest {0: sqr, 12: y0, 24: y2, 36: y4} %stack () -> (64, 62, 65) - // stack: 64, 62, 65, 12, val, retdest {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: 64, 62, 65, 0, val, retdest {0: sqr, 12: y0, 24: y2, 36: y4} %jump(power_loop_4) /// After computing the powers @@ -87,49 +87,49 @@ final_exp: /// return y * y2 * y1 * y0 custom_powers: - // stack: val, retdest {24: y0, 36: y2, 48: y4} - %stack () -> (24, 60, make_term_1) - // stack: 24, 60, make_term_1, val, retdest {24: y0, 36: y2, 48: y4} + // stack: val, retdest {12: y0, 24: y2, 36: y4} + %stack () -> (12, 48, make_term_1) + // stack: 12, 48, make_term_1, val, retdest {12: y0, 24: y2, 36: y4} %jump(inv_fp254_12) make_term_1: - // stack: val, retdest {36: y2, 48: y4, 60: y0^-1} - %stack () -> (36, 48, 48, make_term_2) - // stack: 36, 48, 48, make_term_2, val, retdest {36: y2, 48: y4, 60: y0^-1} + // stack: val, retdest {24: y2, 36: y4, 48: y0^-1} + %stack () -> (24, 36, 36, make_term_2) + // stack: 24, 36, 36, make_term_2, val, retdest {24: y2, 36: y4, 48: y0^-1} %jump(mul_fp254_12) make_term_2: - // stack: val, retdest {36: y2, 48: y4 * y2, 60: y0^-1} - %stack () -> (36, 48, 48, make_term_3) - // stack: 36, 48, 48, make_term_3, val, retdest {36: y2, 48: y4 * y2, 60: y0^-1} + // stack: val, retdest {24: y2, 36: y4 * y2, 48: y0^-1} + %stack () -> (24, 36, 36, make_term_3) + // stack: 24, 36, 36, make_term_3, val, retdest {24: y2, 36: y4 * y2, 48: y0^-1} %jump(mul_fp254_12) make_term_3: - // stack: val, retdest {36: y2, 48: y4 * y2^2, 60: y0^-1} - %stack () -> (60, 48, 48, final_power) - // stack: 60, 48, 48, final_power, val, retdest {36: y2, 48: y4 * y2^2, 60: y0^-1} + // stack: val, retdest {24: y2, 36: y4 * y2^2, 48: y0^-1} + %stack () -> (48, 36, 36, final_power) + // stack: 48, 36, 36, final_power, val, retdest {24: y2, 36: y4 * y2^2, 48: y0^-1} %jump(mul_fp254_12) final_power: - // stack: val, retdest {val: y , 36: y^a2 , 48: y^a1 , 60: y^a0} + // stack: val, retdest {val: y , 24: y^a2 , 36: y^a1 , 48: y^a0} %frob_fp254_12_3 - // stack: val, retdest {val: y_3, 36: y^a2 , 48: y^a1 , 60: y^a0} - %stack () -> (36, 36) + // stack: val, retdest {val: y_3, 24: y^a2 , 36: y^a1 , 48: y^a0} + %stack () -> (24, 24) %frob_fp254_12_2_ POP - // stack: val, retdest {val: y_3, 36: (y^a2)_2, 48: y^a1 , 60: y^a0} - PUSH 48 + // stack: val, retdest {val: y_3, 24: (y^a2)_2, 36: y^a1 , 48: y^a0} + PUSH 36 %frob_fp254_12_1 POP - // stack: val, retdest {val: y_3, 36: (y^a2)_2, 48: (y^a1)_1, 60: y^a0} - %stack (val) -> (36, val, val, penult_mul, val) - // stack: 36, val, val, penult_mul, val, retdest {val: y_3, 36: (y^a2)_2, 48: (y^a1)_1, 60: y^a0} + // stack: val, retdest {val: y_3, 24: (y^a2)_2, 36: (y^a1)_1, 48: y^a0} + %stack (val) -> (24, val, val, penult_mul, val) + // stack: 24, val, val, penult_mul, val, retdest {val: y_3, 24: (y^a2)_2, 36: (y^a1)_1, 48: y^a0} %jump(mul_fp254_12) penult_mul: - // stack: val, retdest {val: y_3 * (y^a2)_2, 48: (y^a1)_1, 60: y^a0} - %stack (val) -> (48, val, val, final_mul, val) - // stack: 48, val, val, final_mul, val, retdest {val: y_3 * (y^a2)_2, 48: (y^a1)_1, 60: y^a0} + // stack: val, retdest {val: y_3 * (y^a2)_2, 36: (y^a1)_1, 48: y^a0} + %stack (val) -> (36, val, val, final_mul, val) + // stack: 36, val, val, final_mul, val, retdest {val: y_3 * (y^a2)_2, 36: (y^a1)_1, 48: y^a0} %jump(mul_fp254_12) final_mul: - // stack: val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 60: y^a0} - %stack (val) -> (60, val, val) - // stack: 60, val, val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 60: y^a0} + // stack: val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 48: y^a0} + %stack (val) -> (48, val, val) + // stack: 48, val, val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 48: y^a0} %jump(mul_fp254_12) @@ -164,156 +164,156 @@ final_mul: /// y0 *= acc power_loop_4: - // stack: i , j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: i , j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 ISZERO - // stack: break?, i , j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: break?, i , j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_4_end) - // stack: i , j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: i , j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %sub_const(1) - // stack: i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 %mload_kernel_code(power_data_4) - // stack: abc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: abc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 %lt_const(100) - // stack: skip?, abc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: skip?, abc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_4_b) - // stack: abc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: abc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %sub_const(100) - // stack: bc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (48, 48, power_loop_4_b) - // stack: 48, 48, power_loop_4_b, bc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: bc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (36, 36, power_loop_4_b) + // stack: 36, 36, power_loop_4_b, bc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP8 - // stack: sqr, 48, 48, power_loop_4_b, bc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 36, 36, power_loop_4_b, bc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_4_b: - // stack: bc, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: bc, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 %lt_const(10) - // stack: skip?, bc, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: skip?, bc, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_4_c) - // stack: bc, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: bc, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %sub_const(10) - // stack: c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (36, 36, power_loop_4_c) - // stack: 36, 36, power_loop_4_c, c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (24, 24, power_loop_4_c) + // stack: 24, 24, power_loop_4_c, c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP8 - // stack: sqr, 36, 36, power_loop_4_c, c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 24, 24, power_loop_4_c, c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_4_c: - // stack: c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} ISZERO - // stack: skip?, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: skip?, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_4_sq) - // stack: i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (24, 24, power_loop_4_sq) - // stack: 24, 24, power_loop_4_sq, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (12, 12, power_loop_4_sq) + // stack: 12, 12, power_loop_4_sq, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP7 - // stack: sqr, 24, 24, power_loop_4_sq, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 12, 12, power_loop_4_sq, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_4_sq: - // stack: i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} PUSH power_loop_4 - // stack: power_loop_4, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: power_loop_4, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP5 DUP1 - // stack: sqr, sqr, power_loop_4, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, sqr, power_loop_4, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(square_fp254_12) power_loop_4_end: - // stack: 0, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: 0, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} POP - // stack: j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (48, 48, power_loop_2) - // stack: 48, 48, power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (36, 36, power_loop_2) + // stack: 36, 36, power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP6 - // stack: sqr, 48, 48, power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 36, 36, power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_2: - // stack: j , k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: j , k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 ISZERO - // stack: break?, j , k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: break?, j , k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_2_end) - // stack: j , k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: j , k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %sub_const(1) - // stack: j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 %mload_kernel_code(power_data_2) - // stack: ab, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: ab, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 %lt_const(10) - // stack: skip?, ab, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: skip?, ab, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_2_b) - // stack: ab, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: ab, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %sub_const(10) - // stack: b, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (36, 36, power_loop_2_b) - // stack: 36, 36, power_loop_2_b, b, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: b, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (24, 24, power_loop_2_b) + // stack: 24, 24, power_loop_2_b, b, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP7 - // stack: sqr, 36, 36, power_loop_2_b, b, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 24, 24, power_loop_2_b, b, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_2_b: - // stack: b, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: b, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} ISZERO - // stack: skip?, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: skip?, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_2_sq) - // stack: j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (24, 24, power_loop_2_sq) - // stack: 24, 24, power_loop_2_sq, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (12, 12, power_loop_2_sq) + // stack: 12, 12, power_loop_2_sq, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP6 - // stack: sqr, 24, 24, power_loop_2_sq, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 12, 12, power_loop_2_sq, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_2_sq: - // stack: j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} PUSH power_loop_2 - // stack: power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP4 DUP1 - // stack: sqr, sqr, power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, sqr, power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(square_fp254_12) power_loop_2_end: - // stack: 0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: 0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} POP - // stack: k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (36, 36, power_loop_0) - // stack: 36, 36, power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (24, 24, power_loop_0) + // stack: 24, 24, power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP5 - // stack: sqr, 36, 36, power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 24, 24, power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_0: - // stack: k , sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: k , sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 ISZERO - // stack: break?, k , sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: break?, k , sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_0_end) - // stack: k , sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: k , sqr {0: sqr, 12: y0, 24: y2, 36: y4} %sub_const(1) - // stack: k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP1 %mload_kernel_code(power_data_0) - // stack: a, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: a, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} ISZERO - // stack: skip?, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: skip?, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jumpi(power_loop_0_sq) - // stack: k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (24, 24, power_loop_0_sq) - // stack: 24, 24, power_loop_0_sq, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (12, 12, power_loop_0_sq) + // stack: 12, 12, power_loop_0_sq, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP5 - // stack: sqr, 24, 24, power_loop_0_sq, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, 12, 12, power_loop_0_sq, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) power_loop_0_sq: - // stack: k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} PUSH power_loop_0 - // stack: power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} DUP3 DUP1 - // stack: sqr, sqr, power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: sqr, sqr, power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} %jump(square_fp254_12) power_loop_0_end: - // stack: 0, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack (i, sqr) -> (24, sqr, 24, custom_powers) - // stack: 24, sqr, 24, custom_powers {12: sqr, 24: y0, 36: y2, 48: y4} + // stack: 0, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack (i, sqr) -> (12, sqr, 12, custom_powers) + // stack: 12, sqr, 12, custom_powers {0: sqr, 12: y0, 24: y2, 36: y4} %jump(mul_fp254_12) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm index ce43d4f1..87537bf2 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm @@ -55,6 +55,7 @@ miller_return: // stack: times, O, P, Q, out, retdest %stack (times, O: 2, P: 2, Q: 4, out, retdest) -> (retdest) // stack: retdest + %clear_line JUMP miller_one: @@ -281,3 +282,12 @@ after_add: // stack: (p1x - p2x)*qy_ %mstore_kernel_bn254_pairing(21) %endmacro + +%macro clear_line + %stack () -> (0, 0, 0, 0, 0) + %mstore_kernel_bn254_pairing(12) + %mstore_kernel_bn254_pairing(14) + %mstore_kernel_bn254_pairing(15) + %mstore_kernel_bn254_pairing(20) + %mstore_kernel_bn254_pairing(21) +%endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm index 7c0538f4..ca32a30d 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm @@ -40,73 +40,73 @@ mul_fp254_12_1: // stack: f'g', g' , f', inA, inB, out %dup_fp254_6_0 // stack: f'g', f'g', g' , f', inA, inB, out - %store_fp254_6_sh(84) - // stack: f'g', g' , f', inA, inB, out {84: sh(f'g')} - %store_fp254_6(90) - // stack: g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + %store_fp254_6_sh(60) + // stack: f'g', g' , f', inA, inB, out {60: sh(f'g')} + %store_fp254_6(66) + // stack: g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} DUP13 - // stack: inA, g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: inA, g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} DUP15 - // stack: inB, inA, g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: inB, inA, g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %load_fp254_6 - // stack: g , inA, g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g , inA, g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %stack (f: 6, x, g: 6) -> (g, x, f) - // stack: g', inA, g , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g', inA, g , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %dup_fp254_6_7 - // stack: g,g', inA, g , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g,g', inA, g , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %add_fp254_6 - // stack: g+g', inA, g , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g+g', inA, g , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %stack (f: 6, x, g: 6) -> (g, x, f) - // stack: g, inA, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g, inA, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} PUSH mul_fp254_12_2 - // stack: mul_fp254_12_2, g, inA, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: mul_fp254_12_2, g, inA, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} SWAP7 - // stack: inA, g, mul_fp254_12_2, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: inA, g, mul_fp254_12_2, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} %load_fp254_6 - // stack: f, g, mul_fp254_12_2, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: f, g, mul_fp254_12_2, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} %jump(mul_fp254_6) mul_fp254_12_2: - // stack: fg, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} - %store_fp254_6(96) - // stack: g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: fg, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} + %store_fp254_6(72) + // stack: g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %stack (x: 6, y: 6) -> (y, x) - // stack: f', g+g', inA, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f', g+g', inA, inB, out {60: sh(f'g'), 66: f'g', 72: fg} PUSH mul_fp254_12_3 - // stack: mul_fp254_12_3, f', g+g', inA, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: mul_fp254_12_3, f', g+g', inA, inB, out {60: sh(f'g'), 66: f'g', 72: fg} SWAP13 - // stack: inA, f', g+g', mul_fp254_12_3, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: inA, f', g+g', mul_fp254_12_3, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %load_fp254_6 - // stack: f,f', g+g', mul_fp254_12_3, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f,f', g+g', mul_fp254_12_3, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %add_fp254_6 - // stack: f+f', g+g', mul_fp254_12_3, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f+f', g+g', mul_fp254_12_3, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %jump(mul_fp254_6) mul_fp254_12_3: - // stack: (f+f')(g+g'), inB, out {84: sh(f'g'), 90: f'g', 96: fg} - %load_fp254_6(96) - // stack: fg, (f+f')(g+g'), inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: (f+f')(g+g'), inB, out {60: sh(f'g'), 66: f'g', 72: fg} + %load_fp254_6(72) + // stack: fg, (f+f')(g+g'), inB, out {60: sh(f'g'), 66: f'g', 72: fg} %stack (x: 6, y: 6) -> (y, x) - // stack: (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %dup_fp254_6_6 - // stack: fg, (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} - %load_fp254_6(90) - // stack: f'g',fg, (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: fg, (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} + %load_fp254_6(66) + // stack: f'g',fg, (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %add_fp254_6 - // stack: f'g'+fg, (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f'g'+fg, (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %subr_fp254_6 - // stack: (f+f')(g+g') - (f'g'+fg), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: (f+f')(g+g') - (f'g'+fg), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} DUP14 %add_const(6) - // stack: out', (f+f')(g+g') - (f'g'+fg), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: out', (f+f')(g+g') - (f'g'+fg), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %store_fp254_6 - // stack: fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} - %load_fp254_6(84) - // stack: sh(f'g') , fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} + %load_fp254_6(60) + // stack: sh(f'g') , fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %add_fp254_6 - // stack: sh(f'g') + fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: sh(f'g') + fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} DUP8 - // stack: out, sh(f'g') + fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: out, sh(f'g') + fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %store_fp254_6 - // stack: inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: inB, out {60: sh(f'g'), 66: f'g', 72: fg} %pop2 JUMP diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm index 6214f385..ce4602a9 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm @@ -32,16 +32,19 @@ global inv_fp254_12: // stack: out, f^-1, inp, out, retdest %store_fp254_12 // stack: inp, out, retdest - %stack (inp, out) -> (inp, out, 72, check_inv_fp254_12) - // stack: inp, out, 72, check_inv_fp254_12, retdest + %stack (inp, out) -> (inp, out, 60, check_inv_fp254_12) + // stack: inp, out, 60, check_inv_fp254_12, retdest %jump(mul_fp254_12) check_inv_fp254_12: // stack: retdest - PUSH 72 + PUSH 60 %load_fp254_12 // stack: unit?, retdest %assert_eq_unit_fp254_12 // stack: retdest + PUSH 0 + // stack: 0, retdest + %mstore_kernel_bn254_pairing(60) JUMP %macro prover_inv_fp254_12 diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 148847da..44589831 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -56,9 +56,9 @@ fn test_bn_mul_fp6() -> Result<()> { } fn run_bn_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Vec { - let in0: usize = 200; - let in1: usize = 212; - let out: usize = 224; + let in0: usize = 100; + let in1: usize = 112; + let out: usize = 124; let mut stack = vec![ U256::from(in0), @@ -126,7 +126,7 @@ fn test_bn_frob_fp6() -> Result<()> { } fn run_bn_frob_fp12(f: Fp12, n: usize) -> Vec { - let ptr: usize = 200; + let ptr: usize = 100; let setup = InterpreterMemoryInitialization { label: format!("test_frob_fp254_12_{}", n), stack: vec![U256::from(ptr)], @@ -152,8 +152,8 @@ fn test_bn_frob_fp12() -> Result<()> { #[test] fn test_bn_inv_fp12() -> Result<()> { - let ptr: usize = 200; - let inv: usize = 212; + let ptr: usize = 100; + let inv: usize = 112; let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); @@ -174,7 +174,7 @@ fn test_bn_inv_fp12() -> Result<()> { #[test] fn test_bn_final_exponent() -> Result<()> { - let ptr: usize = 200; + let ptr: usize = 100; let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); @@ -254,8 +254,8 @@ pub const TWISTED_GENERATOR: TwistedCurve = { #[test] fn test_bn_miller() -> Result<()> { - let ptr: usize = 200; - let out: usize = 206; + let ptr: usize = 100; + let out: usize = 106; let inputs: Vec = vec![ CURVE_GENERATOR.x.val, CURVE_GENERATOR.y.val, @@ -282,8 +282,8 @@ fn test_bn_miller() -> Result<()> { #[test] fn test_bn_pairing() -> Result<()> { - let out: usize = 200; - let ptr: usize = 212; + let out: usize = 100; + let ptr: usize = 112; let inputs: Vec = vec![ CURVE_GENERATOR.x.val, From dd58b9b5d891c809ffd5019608d1edbd8f3cfae3 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Fri, 21 Apr 2023 12:02:36 -0700 Subject: [PATCH 18/43] dont panic --- .../curve/bn254/curve_arithmetic/pairing.asm | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 3c91192b..5a70f141 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -1,8 +1,8 @@ /// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Fp12: /// /// for P, Q in pairs: -/// assert(P.is_valid) -/// assert(Q.is_valid) +/// if not (P.is_valid and Q.is_valid): +/// return @U256_MAX /// /// out = 1 /// for P, Q in pairs: @@ -35,17 +35,28 @@ bn254_input_check: // stack: P_j, inp_j, j, k, inp %bn_check // stack: valid?, inp_j, j, k, inp - %assert_nonzero + ISZERO + %jumpi(bn_pairing_invalid_input) // stack: inp_j, j, k, inp + DUP1 + // stack: inp_j , inp_j, j, k, inp %add_const(2) + // stack: inp_j', inp_j, j, k, inp %load_fp254_4 - // stack: Q_j, j, k, inp + // stack: Q_j, inp_j, j, k, inp %bn_check_twisted - // stack: valid?, j, k, inp - %assert_nonzero - // stack: j, k, inp + // stack: valid?, inp_j, j, k, inp + ISZERO + %jumpi(bn_pairing_invalid_input) + // stack: inp_j, j, k, inp + POP %jump(bn254_input_check) +bn_pairing_invalid_input: + // stack: inp_j, j, k, inp, out, retdest + %stack (inp_j, j, k, inp, out, retdest) -> (retdest, @U256_MAX) + JUMP + bn254_pairing_start: // stack: 0, k, inp, out, retdest %stack (j, k, inp, out) -> (out, 1, k, inp, out) From 2620446128028fef8ada33dd19704a0c12bcbadf Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Fri, 21 Apr 2023 13:31:51 -0700 Subject: [PATCH 19/43] it works --- .../curve/bn254/curve_arithmetic/pairing.asm | 98 ++++++++++++++++--- evm/src/cpu/kernel/tests/bn254.rs | 6 +- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 5a70f141..24e82045 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -1,4 +1,4 @@ -/// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Fp12: +/// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Bool: /// /// for P, Q in pairs: /// if not (P.is_valid and Q.is_valid): @@ -8,10 +8,11 @@ /// for P, Q in pairs: /// out *= miller_loop(P, Q) /// -/// return bn254_final_exponent(out) +/// result = bn254_final_exponent(out) +/// return result == @GENERATOR_PAIRING global bn254_pairing: - // stack: k, inp, out, retdest + // stack: DUP1 bn254_input_check: @@ -58,25 +59,96 @@ bn_pairing_invalid_input: JUMP bn254_pairing_start: - // stack: 0, k, inp, out, retdest - %stack (j, k, inp, out) -> (out, 1, k, inp, out) - // stack: out, 1, k, inp, out, retdest + // stack: 0, k, inp, out, retdest + %stack (j, k, inp, out) -> (out, 1, k, inp, out, bn254_pairing_output_validation, out) + // stack: out, 1, k, inp, out, final_label, out, retdest %mstore_kernel_bn254_pairing - // stack: k, inp, out, retdest + // stack: k, inp, out, final_label, out, retdest bn254_pairing_loop: - // stack: k, inp, out, retdest + // stack: k, inp, out, final_label DUP1 ISZERO - // stack: end?, k, inp, out, retdest + // stack: end?, k, inp, out, final_label %jumpi(bn254_final_exponent) - // stack: k, inp, out, retdest + // stack: k, inp, out, final_label %sub_const(1) - // stack: k=k-1, inp, out, retdest + // stack: k=k-1, inp, out, final_label %stack (k, inp, out) -> (k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out) - // stack: k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out retdest + // stack: k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out, final_label %mul_const(6) ADD - // stack: inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out retdest + // stack: inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out, final_label %jump(bn254_miller) + + +bn254_pairing_output_validation: + // stack: out, retdest + %push_desired_output + // stack: g0, g11..g1, out, retdest + SWAP12 + // stack: out, g11..g0, retdest + PUSH 1 + // stack: check, out, g11..g0, retdest + %check_output_term(11) + // stack: check, out, g10..g0, retdest + %check_output_term(10) + // stack: check, out, g9..g0, retdest + %check_output_term(9) + // stack: check, out, g8..g0, retdest + + %check_output_term(8) + + // stack: check, out, g7..g0, retdest + %check_output_term(7) + // stack: check, out, g6..g0, retdest + %check_output_term(6) + + // stack: check, out, g5..g0, retdest + %check_output_term(5) + // stack: check, out, g4..g0, retdest + %check_output_term(4) + // stack: check, out, g3..g0, retdest + %check_output_term(3) + // stack: check, out, g2..g0, retdest + %check_output_term(2) + // stack: check, out, g1, g0, retdest + %check_output_term(1) + // stack: check, out, g0, retdest + %check_output_term(0) + // stack: check, out, , retdest + %stack (check, out, retdest) -> (retdest, check) + JUMP + +%macro check_output_term(j) + // stack: check, out, gj + SWAP2 + // stack: gj, out, check + DUP2 + %add_const($j) + // stack: outj, gj, out, check + %mload_kernel_bn254_pairing + // stack: fj, gj, out, check + EQ + // stack: checkj, out, check + %stack (checkj, out, check) -> (check, checkj, out) + // stack: check, checkj, out + AND + // stack: check, out +%endmacro + +%macro push_desired_output + PUSH 07708764853296235550302896633598331924671113766219240748172066028946006022854 // g1 + PUSH 17700926755167371005308910210965003607045179123434251133647055306492170438120 // g2 + PUSH 00154397549418641559307524478611787574224314011122269053905755152919215659778 // g3 + PUSH 01984170487336525780293932330785856524432038724373274488958019302386252559231 // g4 + PUSH 03314362000193010715052769662421751145025288853014347901929084743686925091033 // g5 + PUSH 05969572836535217971378806448005698172042029600478282326636924294386246370693 // g6 + PUSH 18564243080196493066086408717287862863335702133957524699743268830525148172506 // g7 + PUSH 17269266067816704782247017427200956927940055030199138534350116254357612253048 // g8 + PUSH 09740411817590043771488498441210821606869449023601574073310485764683435152587 // g9 + PUSH 12727712035316870814661734054996728204626079181372322293888505805399715437139 // g10 + PUSH 20210469749439596480915120057935665765860695731536556057113952828024130849369 // g11 + PUSH 05408068458366290097693809645929734991458199404659878659553047611146680628954 // g0 +%endmacro diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 44589831..c03fcad9 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -306,10 +306,10 @@ fn test_bn_pairing() -> Result<()> { memory: vec![(ptr, inputs)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); + // let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); - - assert_eq!(output, expected); + println!("{:?}", expected); + assert_eq!(interpreter.stack()[0], U256::one()); Ok(()) } From 0f662ed043f49e10c71e9e87e92874a1a2bc883a Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 24 Apr 2023 08:08:26 -0700 Subject: [PATCH 20/43] fixes --- .../asm/curve/bn254/curve_arithmetic/pairing.asm | 4 ++-- .../curve/bn254/curve_arithmetic/twisted_curve.asm | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 24e82045..d89c9c31 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -12,7 +12,7 @@ /// return result == @GENERATOR_PAIRING global bn254_pairing: - // stack: + // stack: k, inp, out, retdest DUP1 bn254_input_check: @@ -134,7 +134,7 @@ bn254_pairing_output_validation: // stack: checkj, out, check %stack (checkj, out, check) -> (check, checkj, out) // stack: check, checkj, out - AND + MUL // stack: check, out %endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm index b87828de..859c45fe 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -11,7 +11,7 @@ // stack: range, x, x_, y, y_ %bn_check_twisted_curve // stack: curve , range, x, x_, y, y_ - AND + MUL // Cheaper than AND // stack: curve & range, x, x_, y, y_ SWAP4 // stack: y_, x, x_, y, curve & range @@ -49,9 +49,9 @@ // stack: x , N, x_ < N, y < N, y_ < N, x, x_, y, y_ LT // stack: x < N, x_ < N, y < N, y_ < N, x, x_, y, y_ - AND - AND - AND + MUL // Cheaper than AND + MUL // Cheaper than AND + MUL // Cheaper than AND // stack: range, x, x_, y, y_ %endmacro @@ -88,7 +88,7 @@ // stack: b , c==0, d==0, a==0 ISZERO // stack: b==0, c==0, d==0, a==0 - AND - AND - AND + MUL // Cheaper than AND + MUL // Cheaper than AND + MUL // Cheaper than AND %endmacro From 14ee46c85065552b2725cac5f353a76dc022cb98 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 24 Apr 2023 09:33:05 -0700 Subject: [PATCH 21/43] cleanup --- evm/src/bn254_pairing.rs | 53 ++++++++++++++++++ evm/src/cpu/kernel/tests/bn254.rs | 90 ++++++------------------------- 2 files changed, 68 insertions(+), 75 deletions(-) diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 6d2347a9..93d0d1e9 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -1,5 +1,6 @@ use std::ops::Add; +use ethereum_types::U256; use rand::Rng; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254}; @@ -11,6 +12,16 @@ pub struct Curve { pub y: BN254, } +// The curve is cyclic with generator (1, 2) +pub const CURVE_GENERATOR: Curve = { + Curve { + x: BN254 { val: U256::one() }, + y: BN254 { + val: U256([2, 0, 0, 0]), + }, + } +}; + /// Standard addition formula for elliptic curves, restricted to the cases /// where neither inputs nor output would ever be the identity O. source: /// https://en.wikipedia.org/wiki/Elliptic_curve#Algebraic_interpretation @@ -38,6 +49,48 @@ pub struct TwistedCurve { pub y: Fp2, } +// The twisted curve is cyclic with generator (x, y) as follows +pub const TWISTED_GENERATOR: TwistedCurve = { + TwistedCurve { + x: Fp2 { + re: BN254 { + val: U256([ + 0x46debd5cd992f6ed, + 0x674322d4f75edadd, + 0x426a00665e5c4479, + 0x1800deef121f1e76, + ]), + }, + im: BN254 { + val: U256([ + 0x97e485b7aef312c2, + 0xf1aa493335a9e712, + 0x7260bfb731fb5d25, + 0x198e9393920d483a, + ]), + }, + }, + y: Fp2 { + re: BN254 { + val: U256([ + 0x4ce6cc0166fa7daa, + 0xe3d1e7690c43d37b, + 0x4aab71808dcb408f, + 0x12c85ea5db8c6deb, + ]), + }, + im: BN254 { + val: U256([ + 0x55acdadcd122975b, + 0xbc4b313370b38ef3, + 0xec9e99ad690c3395, + 0x090689d0585ff075, + ]), + }, + }, + } +}; + // The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { let miller_output = miller_loop(p, q); diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index c03fcad9..720081b1 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -1,14 +1,16 @@ +use std::mem::transmute; + use anyhow::Result; use ethereum_types::U256; use rand::Rng; use crate::bn254_pairing::{ - final_exponent, gen_fp12_sparse, miller_loop, tate, Curve, TwistedCurve, + final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR, }; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; -use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; +use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -200,76 +202,21 @@ fn test_bn_final_exponent() -> Result<()> { Ok(()) } -// The curve is cyclic with generator (1, 2) -pub const CURVE_GENERATOR: Curve = { - Curve { - x: BN254 { val: U256::one() }, - y: BN254 { - val: U256([2, 0, 0, 0]), - }, - } -}; - -// The twisted curve is cyclic with generator (x, y) as follows -pub const TWISTED_GENERATOR: TwistedCurve = { - TwistedCurve { - x: Fp2 { - re: BN254 { - val: U256([ - 0x46debd5cd992f6ed, - 0x674322d4f75edadd, - 0x426a00665e5c4479, - 0x1800deef121f1e76, - ]), - }, - im: BN254 { - val: U256([ - 0x97e485b7aef312c2, - 0xf1aa493335a9e712, - 0x7260bfb731fb5d25, - 0x198e9393920d483a, - ]), - }, - }, - y: Fp2 { - re: BN254 { - val: U256([ - 0x4ce6cc0166fa7daa, - 0xe3d1e7690c43d37b, - 0x4aab71808dcb408f, - 0x12c85ea5db8c6deb, - ]), - }, - im: BN254 { - val: U256([ - 0x55acdadcd122975b, - 0xbc4b313370b38ef3, - 0xec9e99ad690c3395, - 0x090689d0585ff075, - ]), - }, - }, - } -}; - #[test] fn test_bn_miller() -> Result<()> { let ptr: usize = 100; let out: usize = 106; - let inputs: Vec = vec![ - CURVE_GENERATOR.x.val, - CURVE_GENERATOR.y.val, - TWISTED_GENERATOR.x.re.val, - TWISTED_GENERATOR.x.im.val, - TWISTED_GENERATOR.y.re.val, - TWISTED_GENERATOR.y.im.val, - ]; + + let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; + let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; + let mut input = curve_gen.to_vec(); + input.extend_from_slice(&twisted_gen); let setup = InterpreterMemoryInitialization { label: "bn254_miller".to_string(), stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], segment: BnPairing, - memory: vec![(ptr, inputs)], + memory: vec![(ptr, input)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); @@ -285,14 +232,10 @@ fn test_bn_pairing() -> Result<()> { let out: usize = 100; let ptr: usize = 112; - let inputs: Vec = vec![ - CURVE_GENERATOR.x.val, - CURVE_GENERATOR.y.val, - TWISTED_GENERATOR.x.re.val, - TWISTED_GENERATOR.x.im.val, - TWISTED_GENERATOR.y.re.val, - TWISTED_GENERATOR.y.im.val, - ]; + let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; + let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; + let mut input = curve_gen.to_vec(); + input.extend_from_slice(&twisted_gen); let setup = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), @@ -303,12 +246,9 @@ fn test_bn_pairing() -> Result<()> { U256::from(0xdeadbeefu32), ], segment: BnPairing, - memory: vec![(ptr, inputs)], + memory: vec![(ptr, input)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); - // let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); - println!("{:?}", expected); assert_eq!(interpreter.stack()[0], U256::one()); Ok(()) From 43f4d2b80cb23552fd898ab40447befffa9ddecf Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 24 Apr 2023 09:37:42 -0700 Subject: [PATCH 22/43] clean more --- evm/src/cpu/kernel/tests/bn254.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 720081b1..c77e74d3 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -202,15 +202,19 @@ fn test_bn_final_exponent() -> Result<()> { Ok(()) } -#[test] -fn test_bn_miller() -> Result<()> { - let ptr: usize = 100; - let out: usize = 106; - +fn pairing_input() -> Vec { let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; let mut input = curve_gen.to_vec(); input.extend_from_slice(&twisted_gen); + input +} + +#[test] +fn test_bn_miller() -> Result<()> { + let ptr: usize = 100; + let out: usize = 106; + let input = pairing_input(); let setup = InterpreterMemoryInitialization { label: "bn254_miller".to_string(), @@ -231,11 +235,7 @@ fn test_bn_miller() -> Result<()> { fn test_bn_pairing() -> Result<()> { let out: usize = 100; let ptr: usize = 112; - - let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; - let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; - let mut input = curve_gen.to_vec(); - input.extend_from_slice(&twisted_gen); + let input = pairing_input(); let setup = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), From f225ea495d083a797b12e804fa53e3718f1beec6 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Mon, 24 Apr 2023 13:44:31 -0700 Subject: [PATCH 23/43] add comment --- .../asm/curve/bn254/curve_arithmetic/pairing.asm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index d89c9c31..b6df8a94 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -11,6 +11,16 @@ /// result = bn254_final_exponent(out) /// return result == @GENERATOR_PAIRING +/// The following is a key to this API +/// +/// - k is the number of inputs, +/// - each input given by a pair of points, one on the curve and one on the twisted curve +/// - each input consists of 6 stack terms---2 for the curve point and 4 for the twisted curve point +/// - the inputs are presumed to be placed on the kernel contiguously +/// - the output (as defined above) is an Fp12 element +/// - out and inp are the BnPairing segment offsets for the output element and input +/// - the assembly code currently uses offsets 0-78 for scratch space + global bn254_pairing: // stack: k, inp, out, retdest DUP1 From d928a70b6f34cc1bf12ac34ddd374bf68c7e7505 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 09:54:46 -0700 Subject: [PATCH 24/43] clean --- evm/src/bn254_pairing.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 93d0d1e9..138f23e7 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -1,4 +1,4 @@ -use std::ops::Add; +use std::ops::{Add, Mul, Neg}; use ethereum_types::U256; use rand::Rng; @@ -42,6 +42,38 @@ impl Add for Curve { } } +impl Neg for Curve { + type Output = Curve; + + fn neg(self) -> Self { + Curve { + x: self.x, + y: -self.y, + } + } +} + +impl Mul for Curve { + type Output = Curve; + + fn mul(self, other: i32) -> Self { + let mut result: Curve = self; + if other.is_negative() { + result = -result; + } + let mut multiplier = result; + let mut exp = other.abs() as usize; + while exp > 0 { + if exp % 2 == 1 { + result = result + multiplier; + } + exp >>= 1; + multiplier = multiplier + multiplier; + } + result + } +} + // The twisted curve consists of pairs (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) #[derive(Debug, Copy, Clone, PartialEq)] pub struct TwistedCurve { From d31c60a04513dd8966a6e5997a8dcd68e3058b5f Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 09:57:36 -0700 Subject: [PATCH 25/43] clean up --- .../curve/bn254/curve_arithmetic/pairing.asm | 91 +++++++------------ evm/src/cpu/kernel/tests/bn254.rs | 86 ++++++++++++++++-- 2 files changed, 111 insertions(+), 66 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index b6df8a94..067e6d61 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -13,7 +13,7 @@ /// The following is a key to this API /// -/// - k is the number of inputs, +/// - k is the number of inputs /// - each input given by a pair of points, one on the curve and one on the twisted curve /// - each input consists of 6 stack terms---2 for the curve point and 4 for the twisted curve point /// - the inputs are presumed to be placed on the kernel contiguously @@ -94,71 +94,46 @@ bn254_pairing_loop: bn254_pairing_output_validation: - // stack: out, retdest - %push_desired_output - // stack: g0, g11..g1, out, retdest - SWAP12 - // stack: out, g11..g0, retdest + // stack: out, retdest PUSH 1 - // stack: check, out, g11..g0, retdest - %check_output_term(11) - // stack: check, out, g10..g0, retdest - %check_output_term(10) - // stack: check, out, g9..g0, retdest - %check_output_term(9) - // stack: check, out, g8..g0, retdest - - %check_output_term(8) - - // stack: check, out, g7..g0, retdest - %check_output_term(7) - // stack: check, out, g6..g0, retdest - %check_output_term(6) - - // stack: check, out, g5..g0, retdest - %check_output_term(5) - // stack: check, out, g4..g0, retdest - %check_output_term(4) - // stack: check, out, g3..g0, retdest - %check_output_term(3) - // stack: check, out, g2..g0, retdest - %check_output_term(2) - // stack: check, out, g1, g0, retdest + // stack: check, out, retdest + %check_output_term %check_output_term(1) - // stack: check, out, g0, retdest - %check_output_term(0) - // stack: check, out, , retdest + %check_output_term(2) + %check_output_term(3) + %check_output_term(4) + %check_output_term(5) + %check_output_term(6) + %check_output_term(7) + %check_output_term(8) + %check_output_term(9) + %check_output_term(10) + %check_output_term(11) + // stack: check, out, retdest %stack (check, out, retdest) -> (retdest, check) JUMP -%macro check_output_term(j) - // stack: check, out, gj - SWAP2 - // stack: gj, out, check +%macro check_output_term + // stack: check, out DUP2 - %add_const($j) - // stack: outj, gj, out, check + // stack: out0, check, out %mload_kernel_bn254_pairing - // stack: fj, gj, out, check - EQ - // stack: checkj, out, check - %stack (checkj, out, check) -> (check, checkj, out) - // stack: check, checkj, out + // stack: f0, check, out + %eq_const(1) + // stack: check0, check, out MUL - // stack: check, out + // stack: check, out %endmacro -%macro push_desired_output - PUSH 07708764853296235550302896633598331924671113766219240748172066028946006022854 // g1 - PUSH 17700926755167371005308910210965003607045179123434251133647055306492170438120 // g2 - PUSH 00154397549418641559307524478611787574224314011122269053905755152919215659778 // g3 - PUSH 01984170487336525780293932330785856524432038724373274488958019302386252559231 // g4 - PUSH 03314362000193010715052769662421751145025288853014347901929084743686925091033 // g5 - PUSH 05969572836535217971378806448005698172042029600478282326636924294386246370693 // g6 - PUSH 18564243080196493066086408717287862863335702133957524699743268830525148172506 // g7 - PUSH 17269266067816704782247017427200956927940055030199138534350116254357612253048 // g8 - PUSH 09740411817590043771488498441210821606869449023601574073310485764683435152587 // g9 - PUSH 12727712035316870814661734054996728204626079181372322293888505805399715437139 // g10 - PUSH 20210469749439596480915120057935665765860695731536556057113952828024130849369 // g11 - PUSH 05408068458366290097693809645929734991458199404659878659553047611146680628954 // g0 +%macro check_output_term(j) + // stack: check, out + DUP2 + %add_const($j) + // stack: outj, check, out + %mload_kernel_bn254_pairing + // stack: fj, check, out + ISZERO + // stack: checkj, check, out + MUL + // stack: check, out %endmacro diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index c77e74d3..63dd5b79 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -5,12 +5,13 @@ use ethereum_types::U256; use rand::Rng; use crate::bn254_pairing::{ - final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR, + final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR, Curve, TwistedCurve, tate, }; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; -use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254}; +use crate::cpu::kernel::tests::u256ify; +use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254, Fp2}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -203,7 +204,7 @@ fn test_bn_final_exponent() -> Result<()> { } fn pairing_input() -> Vec { - let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; + let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR ) }; let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; let mut input = curve_gen.to_vec(); input.extend_from_slice(&twisted_gen); @@ -235,9 +236,64 @@ fn test_bn_miller() -> Result<()> { fn test_bn_pairing() -> Result<()> { let out: usize = 100; let ptr: usize = 112; - let input = pairing_input(); + + let inputs: Vec = u256ify(vec![ + "0x1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59", + "0x3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41", + "0x4bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678", + "0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7", + "0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550", + "0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d", + "0x111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c", + "0x2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411", + "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", + "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", + "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", + ]) + .unwrap(); - let setup = InterpreterMemoryInitialization { + let A: Curve = { + Curve { + x: BN254 { val: inputs[0] }, + y: BN254 { val: inputs[1] }, + } + }; + + let B: TwistedCurve = { + TwistedCurve { + x: Fp2 { + re: BN254 { val: inputs[2] }, + im: BN254 { val: inputs[3] }, + }, + y: Fp2 { + re: BN254 { val: inputs[4] }, + im: BN254 { val: inputs[5] }, + }, + } + }; + + let C: Curve = { + Curve { + x: BN254 { val: inputs[6] }, + y: BN254 { val: inputs[7] }, + } + }; + + let D: TwistedCurve = { + TwistedCurve { + x: Fp2 { + re: BN254 { val: inputs[8] }, + im: BN254 { val: inputs[9] }, + }, + y: Fp2 { + re: BN254 { val: inputs[10] }, + im: BN254 { val: inputs[11] }, + }, + } + }; + + let setup1 = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), stack: vec![ U256::one(), @@ -246,10 +302,24 @@ fn test_bn_pairing() -> Result<()> { U256::from(0xdeadbeefu32), ], segment: BnPairing, - memory: vec![(ptr, input)], + memory: vec![(ptr, inputs[0..6].to_vec())], }; - let interpreter = run_interpreter_with_memory(setup).unwrap(); - assert_eq!(interpreter.stack()[0], U256::one()); + let interpreter1 = run_interpreter_with_memory(setup1).unwrap(); + let output1 = interpreter1.extract_kernel_memory(BnPairing, out..out + 12); + + let setup2 = InterpreterMemoryInitialization { + label: "bn254_pairing".to_string(), + stack: vec![ + U256::one(), + U256::from(ptr), + U256::from(out), + U256::from(0xdeadbeefu32), + ], + segment: BnPairing, + memory: vec![(ptr, inputs[6..12].to_vec())], + }; + let interpreter2 = run_interpreter_with_memory(setup2).unwrap(); + let output2 = interpreter2.extract_kernel_memory(BnPairing, out..out + 12); Ok(()) } From 6dc094a894b8f6a092544b9d369defd5da279bb1 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 14:16:23 -0700 Subject: [PATCH 26/43] test --- evm/src/cpu/kernel/tests/bn254.rs | 67 +++---------------------------- 1 file changed, 6 insertions(+), 61 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 63dd5b79..f1a244cc 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -240,7 +240,7 @@ fn test_bn_pairing() -> Result<()> { let inputs: Vec = u256ify(vec![ "0x1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59", "0x3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41", - "0x4bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678", + "0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678", "0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7", "0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550", "0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d", @@ -249,51 +249,11 @@ fn test_bn_pairing() -> Result<()> { "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", + "0x900689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", ]) .unwrap(); - let A: Curve = { - Curve { - x: BN254 { val: inputs[0] }, - y: BN254 { val: inputs[1] }, - } - }; - - let B: TwistedCurve = { - TwistedCurve { - x: Fp2 { - re: BN254 { val: inputs[2] }, - im: BN254 { val: inputs[3] }, - }, - y: Fp2 { - re: BN254 { val: inputs[4] }, - im: BN254 { val: inputs[5] }, - }, - } - }; - - let C: Curve = { - Curve { - x: BN254 { val: inputs[6] }, - y: BN254 { val: inputs[7] }, - } - }; - - let D: TwistedCurve = { - TwistedCurve { - x: Fp2 { - re: BN254 { val: inputs[8] }, - im: BN254 { val: inputs[9] }, - }, - y: Fp2 { - re: BN254 { val: inputs[10] }, - im: BN254 { val: inputs[11] }, - }, - } - }; - - let setup1 = InterpreterMemoryInitialization { + let setup = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), stack: vec![ U256::one(), @@ -302,24 +262,9 @@ fn test_bn_pairing() -> Result<()> { U256::from(0xdeadbeefu32), ], segment: BnPairing, - memory: vec![(ptr, inputs[0..6].to_vec())], + memory: vec![(ptr, inputs)], }; - let interpreter1 = run_interpreter_with_memory(setup1).unwrap(); - let output1 = interpreter1.extract_kernel_memory(BnPairing, out..out + 12); - - let setup2 = InterpreterMemoryInitialization { - label: "bn254_pairing".to_string(), - stack: vec![ - U256::one(), - U256::from(ptr), - U256::from(out), - U256::from(0xdeadbeefu32), - ], - segment: BnPairing, - memory: vec![(ptr, inputs[6..12].to_vec())], - }; - let interpreter2 = run_interpreter_with_memory(setup2).unwrap(); - let output2 = interpreter2.extract_kernel_memory(BnPairing, out..out + 12); - + let interpreter = run_interpreter_with_memory(setup).unwrap(); + assert_eq!(interpreter.stack(), Fp12::::UNIT.on_stack()); Ok(()) } From 479e919c04e777f6125451f76bbd63617ee8bd57 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 14:16:35 -0700 Subject: [PATCH 27/43] fmt --- evm/src/cpu/kernel/tests/bn254.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index f1a244cc..45ec151f 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -5,13 +5,14 @@ use ethereum_types::U256; use rand::Rng; use crate::bn254_pairing::{ - final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR, Curve, TwistedCurve, tate, + final_exponent, gen_fp12_sparse, miller_loop, tate, Curve, TwistedCurve, CURVE_GENERATOR, + TWISTED_GENERATOR, }; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; -use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254, Fp2}; +use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -204,7 +205,7 @@ fn test_bn_final_exponent() -> Result<()> { } fn pairing_input() -> Vec { - let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR ) }; + let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; let mut input = curve_gen.to_vec(); input.extend_from_slice(&twisted_gen); @@ -236,7 +237,7 @@ fn test_bn_miller() -> Result<()> { fn test_bn_pairing() -> Result<()> { let out: usize = 100; let ptr: usize = 112; - + let inputs: Vec = u256ify(vec![ "0x1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59", "0x3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41", From 89122a3d73278c26b9dd808dce841308c248225a Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 15:29:53 -0700 Subject: [PATCH 28/43] it works --- .../bn254/curve_arithmetic/miller_loop.asm | 26 +++++++++---------- evm/src/cpu/kernel/tests/bn254.rs | 12 ++++----- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm index 87537bf2..120365af 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm @@ -27,9 +27,9 @@ global bn254_miller: // stack: ptr, out, retdest - %stack (ptr, out) -> (out, 1, ptr, out) - // stack: out, 1, ptr, out, retdest - %mstore_kernel_bn254_pairing + %stack (ptr, out) -> (out, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ptr, out) + // stack: out, unit, ptr, out, retdest + %store_fp254_12 // stack: ptr, out, retdest %load_fp254_6 // stack: P, Q, out, retdest @@ -111,25 +111,25 @@ mul_tangent_1: DUP11 // stack: O, Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out %tangent - // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {12: line} %stack (out) -> (out, 12, out) - // stack: out, 12, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: out, 12, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {12: line} %jump(mul_fp254_12_sparse) mul_tangent_2: - // stack: retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: retdest, 0xnm, times, O, P, Q, out {12: line} PUSH after_double - // stack: after_double, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: after_double, retdest, 0xnm, times, O, P, Q, out {12: line} DUP6 DUP6 - // stack: O, after_double, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: O, after_double, retdest, 0xnm, times, O, P, Q, out {12: line} %jump(bn_double) after_double: - // stack: 2*O, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: 2*O, retdest, 0xnm, times, O, P, Q, out {12: line} SWAP5 POP SWAP5 POP - // stack: retdest, 0xnm, times, 2*O, P, Q, out {0: line} + // stack: retdest, 0xnm, times, 2*O, P, Q, out {12: line} JUMP /// def mul_cord() @@ -153,11 +153,11 @@ mul_cord: DUP13 // stack: P, O, Q, mul_cord_1, 0xnm, times, O, P, Q, out %cord - // stack: mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: mul_cord_1, 0xnm, times, O, P, Q, out {12: line} DUP12 - // stack: out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: out, mul_cord_1, 0xnm, times, O, P, Q, out {12: line} %stack (out) -> (out, 12, out) - // stack: out, 12, out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: out, 12, out, mul_cord_1, 0xnm, times, O, P, Q, out {12: line} %jump(mul_fp254_12_sparse) mul_cord_1: // stack: 0xnm, times, O , P, Q, out diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 45ec151f..8e17f0dc 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -5,14 +5,13 @@ use ethereum_types::U256; use rand::Rng; use crate::bn254_pairing::{ - final_exponent, gen_fp12_sparse, miller_loop, tate, Curve, TwistedCurve, CURVE_GENERATOR, - TWISTED_GENERATOR, + final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR, }; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; -use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; +use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -250,14 +249,14 @@ fn test_bn_pairing() -> Result<()> { "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "0x900689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", + "0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", ]) .unwrap(); let setup = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), stack: vec![ - U256::one(), + U256::from(2), U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32), @@ -266,6 +265,7 @@ fn test_bn_pairing() -> Result<()> { memory: vec![(ptr, inputs)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); - assert_eq!(interpreter.stack(), Fp12::::UNIT.on_stack()); + let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); + assert_eq!(output, Fp12::::UNIT.on_stack()); Ok(()) } From 537debdc2e5fd83470b37975a9e9000ad1e54102 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 15:35:19 -0700 Subject: [PATCH 29/43] return bool --- evm/src/cpu/kernel/tests/bn254.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 8e17f0dc..d489a8a8 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -265,7 +265,7 @@ fn test_bn_pairing() -> Result<()> { memory: vec![(ptr, inputs)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - assert_eq!(output, Fp12::::UNIT.on_stack()); + + assert_eq!(interpreter.stack()[0], U256::one()); Ok(()) } From 6599c90a6e075c267290a06da66348d50a905165 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 17:21:52 -0700 Subject: [PATCH 30/43] abstraction --- evm/src/bn254_pairing.rs | 111 ++++++++++++++++-------------- evm/src/cpu/kernel/tests/bn254.rs | 12 ++-- evm/src/extension_tower.rs | 49 +++++++++---- 3 files changed, 101 insertions(+), 71 deletions(-) diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 138f23e7..25cb649f 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -5,32 +5,32 @@ use rand::Rng; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254}; -// The curve consists of pairs (x, y): (BN254, BN254) | y^2 = x^3 + 2 #[derive(Debug, Copy, Clone, PartialEq)] -pub struct Curve { - pub x: BN254, - pub y: BN254, +pub struct Curve +where + T: FieldExt, +{ + pub x: T, + pub y: T, } -// The curve is cyclic with generator (1, 2) -pub const CURVE_GENERATOR: Curve = { - Curve { - x: BN254 { val: U256::one() }, - y: BN254 { - val: U256([2, 0, 0, 0]), - }, +impl Curve { + pub fn unit() -> Self { + Curve { + x: T::UNIT, + y: T::UNIT, + } } -}; +} /// Standard addition formula for elliptic curves, restricted to the cases -/// where neither inputs nor output would ever be the identity O. source: /// https://en.wikipedia.org/wiki/Elliptic_curve#Algebraic_interpretation -impl Add for Curve { +impl Add for Curve { type Output = Self; fn add(self, other: Self) -> Self { let m = if self == other { - BN254::new(3) * self.x * self.x / (BN254::new(2) * self.y) + T::new(3) * self.x * self.x / (T::new(2) * self.y) } else { (other.y - self.y) / (other.x - self.x) }; @@ -42,8 +42,8 @@ impl Add for Curve { } } -impl Neg for Curve { - type Output = Curve; +impl Neg for Curve { + type Output = Curve; fn neg(self) -> Self { Curve { @@ -53,37 +53,48 @@ impl Neg for Curve { } } -impl Mul for Curve { - type Output = Curve; - - fn mul(self, other: i32) -> Self { - let mut result: Curve = self; - if other.is_negative() { - result = -result; - } - let mut multiplier = result; - let mut exp = other.abs() as usize; - while exp > 0 { - if exp % 2 == 1 { - result = result + multiplier; - } - exp >>= 1; - multiplier = multiplier + multiplier; - } - result - } +pub trait CurveGroup { + const GENERATOR: Self; } -// The twisted curve consists of pairs (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct TwistedCurve { - pub x: Fp2, - pub y: Fp2, +/// The BN curve consists of pairs +/// (x, y): (BN254, BN254) | y^2 = x^3 + 2 +// with generator given by (1, 2) +impl CurveGroup for Curve { + const GENERATOR: Curve = Curve { + x: BN254 { val: U256::one() }, + y: BN254 { + val: U256([2, 0, 0, 0]), + }, + }; } -// The twisted curve is cyclic with generator (x, y) as follows -pub const TWISTED_GENERATOR: TwistedCurve = { - TwistedCurve { +// impl Mul for Curve { +// type Output = Curve; + +// fn mul(self, other: i32) -> Self { +// let mut result: Curve = self; +// if other.is_negative() { +// result = -result; +// } +// let mut multiplier = result; +// let mut exp = other.unsigned_abs() as usize; +// while exp > 0 { +// if exp % 2 == 1 { +// result = result + multiplier; +// } +// exp >>= 1; +// multiplier = multiplier + multiplier; +// } +// result +// } +// } + +/// The twisted curve consists of pairs +/// (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) +/// with generator given as follows +impl CurveGroup for Curve> { + const GENERATOR: Curve> = Curve { x: Fp2 { re: BN254 { val: U256([ @@ -120,11 +131,11 @@ pub const TWISTED_GENERATOR: TwistedCurve = { ]), }, }, - } -}; + }; +} // The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element -pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { +pub fn tate(p: Curve, q: Curve>) -> Fp12 { let miller_output = miller_loop(p, q); final_exponent(miller_output) } @@ -132,7 +143,7 @@ pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { /// Standard code for miller loop, can be found on page 99 at this url: /// https://static1.squarespace.com/static/5fdbb09f31d71c1227082339/t/5ff394720493bd28278889c6/1609798774687/PairingsForBeginners.pdf#page=107 /// where EXP is a hardcoding of the array of Booleans that the loop traverses -pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { +pub fn miller_loop(p: Curve, q: Curve>) -> Fp12 { let mut r = p; let mut acc: Fp12 = Fp12::::UNIT; let mut line: Fp12; @@ -151,14 +162,14 @@ pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { } /// The sloped line function for doubling a point -pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 { +pub fn tangent(p: Curve, q: Curve>) -> Fp12 { let cx = -BN254::new(3) * p.x * p.x; let cy = BN254::new(2) * p.y; sparse_embed(p.y * p.y - BN254::new(9), q.x * cx, q.y * cy) } /// The sloped line function for adding two points -pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { +pub fn cord(p1: Curve, p2: Curve, q: Curve>) -> Fp12 { let cx = p2.y - p1.y; let cy = p1.x - p2.x; sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x * cx, q.y * cy) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index d489a8a8..6895e8a4 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -4,14 +4,12 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; -use crate::bn254_pairing::{ - final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR, -}; +use crate::bn254_pairing::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CurveGroup}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; -use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254}; +use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; fn extract_stack(interpreter: Interpreter<'static>) -> Vec { @@ -204,8 +202,8 @@ fn test_bn_final_exponent() -> Result<()> { } fn pairing_input() -> Vec { - let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) }; - let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) }; + let curve_gen: [U256; 2] = unsafe { transmute(Curve::::GENERATOR) }; + let twisted_gen: [U256; 4] = unsafe { transmute(Curve::>::GENERATOR) }; let mut input = curve_gen.to_vec(); input.extend_from_slice(&twisted_gen); input @@ -225,7 +223,7 @@ fn test_bn_miller() -> Result<()> { }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack(); + let expected = miller_loop(Curve::::GENERATOR, Curve::>::GENERATOR).on_stack(); assert_eq!(output, expected); diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index ddcfe254..1b5bf684 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -7,6 +7,7 @@ use rand::Rng; pub trait FieldExt: Copy + + std::cmp::PartialEq + std::ops::Add + std::ops::Neg + std::ops::Sub @@ -15,6 +16,7 @@ pub trait FieldExt: { const ZERO: Self; const UNIT: Self; + fn new(val: usize) -> Self; fn inv(self) -> Self; } @@ -30,14 +32,6 @@ pub struct BN254 { pub val: U256, } -impl BN254 { - pub fn new(val: usize) -> BN254 { - BN254 { - val: U256::from(val), - } - } -} - impl Distribution for Standard { fn sample(&self, rng: &mut R) -> BN254 { let xs = rng.gen::<[u64; 4]>(); @@ -91,6 +85,11 @@ impl Mul for BN254 { impl FieldExt for BN254 { const ZERO: Self = BN254 { val: U256::zero() }; const UNIT: Self = BN254 { val: U256::one() }; + fn new(val: usize) -> BN254 { + BN254 { + val: U256::from(val), + } + } fn inv(self) -> BN254 { let exp = BN_BASE - 2; let mut current = self; @@ -131,12 +130,6 @@ pub struct BLS381 { } impl BLS381 { - pub fn new(val: usize) -> BLS381 { - BLS381 { - val: U512::from(val), - } - } - pub fn lo(self) -> U256 { U256(self.val.0[..4].try_into().unwrap()) } @@ -234,6 +227,11 @@ impl Mul for BLS381 { impl FieldExt for BLS381 { const ZERO: Self = BLS381 { val: U512::zero() }; const UNIT: Self = BLS381 { val: U512::one() }; + fn new(val: usize) -> BLS381 { + BLS381 { + val: U512::from(val), + } + } fn inv(self) -> BLS381 { let exp = BLS_BASE - 2; let mut current = self; @@ -365,6 +363,14 @@ impl FieldExt for Fp2 { re: T::UNIT, im: T::ZERO, }; + + fn new(val: usize) -> Fp2 { + Fp2 { + re: T::new(val), + im: T::ZERO, + } + } + /// The inverse of z is given by z'/||z||^2 since ||z||^2 = zz' fn inv(self) -> Fp2 { let norm_sq = self.norm_sq(); @@ -974,6 +980,14 @@ where t1: Fp2::::ZERO, t2: Fp2::::ZERO, }; + + fn new(val: usize) -> Fp6 { + Fp6 { + t0: Fp2::::new(val), + t1: Fp2::::ZERO, + t2: Fp2::::ZERO, + } + } /// Let x_n = x^(p^n) and note that /// x_0 = x^(p^0) = x^1 = x @@ -1040,6 +1054,13 @@ where z1: Fp6::::ZERO, }; + fn new(val: usize) -> Fp12 { + Fp12 { + z0: Fp6::::new(val), + z1: Fp6::::ZERO, + } + } + /// By Galois Theory, given x: Fp12, the product /// phi = Prod_{i=0}^11 x_i /// lands in BN254, and hence the inverse of x is given by From 13c653bc53a99820d2408251059c72a189872c1e Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Wed, 26 Apr 2023 18:10:40 -0700 Subject: [PATCH 31/43] mul works --- evm/src/bn254_pairing.rs | 60 +++++++++++++++++++++---------- evm/src/cpu/kernel/tests/bn254.rs | 5 +-- evm/src/extension_tower.rs | 4 ++- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 25cb649f..44e22189 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -29,6 +29,15 @@ impl Add for Curve { type Output = Self; fn add(self, other: Self) -> Self { + if self == Curve::::unit() { + return other; + } + if other == Curve::::unit() { + return self; + } + if self == -other { + return Curve::::unit(); + } let m = if self == other { T::new(3) * self.x * self.x / (T::new(2) * self.y) } else { @@ -69,26 +78,39 @@ impl CurveGroup for Curve { }; } -// impl Mul for Curve { -// type Output = Curve; +impl Mul for Curve +where + T: FieldExt, + Curve: CurveGroup, +{ + type Output = Curve; -// fn mul(self, other: i32) -> Self { -// let mut result: Curve = self; -// if other.is_negative() { -// result = -result; -// } -// let mut multiplier = result; -// let mut exp = other.unsigned_abs() as usize; -// while exp > 0 { -// if exp % 2 == 1 { -// result = result + multiplier; -// } -// exp >>= 1; -// multiplier = multiplier + multiplier; -// } -// result -// } -// } + fn mul(self, other: i32) -> Self { + if other == 0 { + return Curve::::unit(); + } + if self == Curve::::unit() { + return Curve::::unit(); + } + + let mut x: Curve = self; + if other.is_negative() { + x = -x; + } + let mut result = Curve::::unit(); + + let mut exp = other.unsigned_abs() as usize; + while exp > 0 { + if exp % 2 == 1 { + result = result + x; + } + exp >>= 1; + x = x + x; + } + println!("result: {:?}", result); + result + } +} /// The twisted curve consists of pairs /// (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 6895e8a4..ee1ec702 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -202,7 +202,7 @@ fn test_bn_final_exponent() -> Result<()> { } fn pairing_input() -> Vec { - let curve_gen: [U256; 2] = unsafe { transmute(Curve::::GENERATOR) }; + let curve_gen: [U256; 2] = unsafe { transmute(Curve::::GENERATOR * 1) }; let twisted_gen: [U256; 4] = unsafe { transmute(Curve::>::GENERATOR) }; let mut input = curve_gen.to_vec(); input.extend_from_slice(&twisted_gen); @@ -223,7 +223,8 @@ fn test_bn_miller() -> Result<()> { }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = miller_loop(Curve::::GENERATOR, Curve::>::GENERATOR).on_stack(); + let expected = + miller_loop(Curve::::GENERATOR, Curve::>::GENERATOR).on_stack(); assert_eq!(output, expected); diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index 1b5bf684..2c81b035 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::mem::transmute; use std::ops::{Add, Div, Mul, Neg, Sub}; @@ -7,6 +8,7 @@ use rand::Rng; pub trait FieldExt: Copy + + std::fmt::Debug + std::cmp::PartialEq + std::ops::Add + std::ops::Neg @@ -980,7 +982,7 @@ where t1: Fp2::::ZERO, t2: Fp2::::ZERO, }; - + fn new(val: usize) -> Fp6 { Fp6 { t0: Fp2::::new(val), From b28e3e0db73c77234d70c945c2c028d6529f8cfd Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 07:45:35 -0700 Subject: [PATCH 32/43] minor --- evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm | 2 +- evm/src/cpu/kernel/tests/bn254.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 067e6d61..340d8b33 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -9,7 +9,7 @@ /// out *= miller_loop(P, Q) /// /// result = bn254_final_exponent(out) -/// return result == @GENERATOR_PAIRING +/// return result == unit_fp12 /// The following is a key to this API /// diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index ee1ec702..25ec6429 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -202,7 +202,7 @@ fn test_bn_final_exponent() -> Result<()> { } fn pairing_input() -> Vec { - let curve_gen: [U256; 2] = unsafe { transmute(Curve::::GENERATOR * 1) }; + let curve_gen: [U256; 2] = unsafe { transmute(Curve::::GENERATOR) }; let twisted_gen: [U256; 4] = unsafe { transmute(Curve::>::GENERATOR) }; let mut input = curve_gen.to_vec(); input.extend_from_slice(&twisted_gen); From 4ad8520e3447f040368d98998fff59c752c5f16e Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 27 Apr 2023 19:21:26 +0200 Subject: [PATCH 33/43] SNARKV precompile (#1010) * Serialize impls, and use in Fibonacci example * seralizing * cleanup * don't serialize challenges * deterministic build function * cleanup * cleanup * cleanup * fix * cleanup * fmt * rename * Unpacking and storing inputs * Finish snarkv interface * Failing test * move serialization to separate example * Imaginary part in front of real * serialize ProofChallenges * remove build_without_randomizing (no longer needed) * fix * Fix kernel peak * Fix stack comments * Minor * SSTORE gas (#1007) * Update storage access list and sload * Add noop for sys_sstore * Comments * Fix access list test * PR feedback --------- Co-authored-by: Nicholas Ward --- evm/src/cpu/kernel/asm/core/access_lists.asm | 46 ++++--- .../kernel/asm/core/precompiles/snarkv.asm | 119 +++++++++++++++++- .../kernel/asm/mpt/storage/storage_read.asm | 77 +++++++----- .../kernel/asm/mpt/storage/storage_write.asm | 45 ++++++- evm/src/cpu/kernel/constants/mod.rs | 6 + evm/src/cpu/kernel/tests/core/access_lists.rs | 51 +++++--- evm/src/witness/util.rs | 4 +- plonky2/Cargo.toml | 1 + plonky2/examples/fibonacci_serialization.rs | 79 ++++++++++++ plonky2/src/fri/mod.rs | 6 +- plonky2/src/fri/proof.rs | 1 + plonky2/src/fri/reduction_strategies.rs | 3 +- plonky2/src/gates/constant.rs | 4 +- plonky2/src/gates/gate.rs | 7 ++ plonky2/src/gates/selectors.rs | 4 +- plonky2/src/plonk/circuit_data.rs | 7 +- plonky2/src/plonk/config.rs | 2 +- plonky2/src/plonk/get_challenges.rs | 2 +- plonky2/src/plonk/proof.rs | 5 +- 19 files changed, 379 insertions(+), 90 deletions(-) create mode 100644 plonky2/examples/fibonacci_serialization.rs diff --git a/evm/src/cpu/kernel/asm/core/access_lists.asm b/evm/src/cpu/kernel/asm/core/access_lists.asm index 80d96e43..0c5e595e 100644 --- a/evm/src/cpu/kernel/asm/core/access_lists.asm +++ b/evm/src/cpu/kernel/asm/core/access_lists.asm @@ -54,49 +54,55 @@ insert_accessed_addresses_found: %macro insert_accessed_storage_keys - %stack (addr, key) -> (addr, key, %%after) + %stack (addr, key, value) -> (addr, key, value, %%after) %jump(insert_accessed_storage_keys) %%after: // stack: cold_access %endmacro -/// Inserts the storage key into the access list if it is not already present. -/// Return 1 if the storage key was inserted, 0 if it was already present. +/// Inserts the storage key and value into the access list if it is not already present. +/// `value` should be the current storage value at the slot `(addr, key)`. +/// Return `1, original_value` if the storage key was inserted, `0, original_value` if it was already present. global insert_accessed_storage_keys: - // stack: addr, key, retdest + // stack: addr, key, value, retdest %mload_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) - // stack: len, addr, key, retdest + // stack: len, addr, key, value, retdest PUSH 0 insert_accessed_storage_keys_loop: - %stack (i, len, addr, key, retdest) -> (i, len, i, len, addr, key, retdest) + %stack (i, len, addr, key, value, retdest) -> (i, len, i, len, addr, key, value, retdest) EQ %jumpi(insert_storage_key) - // stack: i, len, addr, key, retdest + // stack: i, len, addr, key, value, retdest DUP1 %increment %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) - // stack: loaded_key, i, len, addr, key, retdest + // stack: loaded_key, i, len, addr, key, value, retdest DUP2 %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) - // stack: loaded_addr, loaded_key, i, len, addr, key, retdest + // stack: loaded_addr, loaded_key, i, len, addr, key, value, retdest DUP5 EQ - // stack: loaded_addr==addr, loaded_key, i, len, addr, key, retdest + // stack: loaded_addr==addr, loaded_key, i, len, addr, key, value, retdest SWAP1 DUP6 EQ - // stack: loaded_key==key, loaded_addr==addr, i, len, addr, key, retdest + // stack: loaded_key==key, loaded_addr==addr, i, len, addr, key, value, retdest MUL // AND %jumpi(insert_accessed_storage_keys_found) - // stack: i, len, addr, key, retdest - %add_const(2) + // stack: i, len, addr, key, value, retdest + %add_const(3) %jump(insert_accessed_storage_keys_loop) insert_storage_key: - // stack: i, len, addr, key, retdest + // stack: i, len, addr, key, value, retdest DUP1 %increment - %stack (i_plus_1, i, len, addr, key, retdest) -> (i, addr, i_plus_1, key, i_plus_1, retdest) + DUP1 %increment + %stack (i_plus_2, i_plus_1, i, len, addr, key, value) -> (i, addr, i_plus_1, key, i_plus_2, value, i_plus_2, value) %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new address at the end of the array. %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new key after that - // stack: i_plus_1, retdest + %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new value after that + // stack: i_plus_2, value, retdest %increment - %mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Store new length in front of the array. - PUSH 1 // Return 1 to indicate that the storage key was inserted. - SWAP1 JUMP + %mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Store new length. + %stack (value, retdest) -> (retdest, 1, value) // Return 1 to indicate that the storage key was inserted. + JUMP insert_accessed_storage_keys_found: - %stack (i, len, addr, key, retdest) -> (retdest, 0) // Return 0 to indicate that the storage key was already present. + // stack: i, len, addr, key, value, retdest + %add_const(2) + %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) + %stack (original_value, len, addr, key, value, retdest) -> (retdest, 0, original_value) // Return 0 to indicate that the storage key was already present. JUMP diff --git a/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm b/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm index fbb46670..26bad450 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm @@ -1,3 +1,118 @@ global precompile_snarkv: - // TODO - PANIC + // stack: address, retdest, new_ctx, (old stack) + %pop2 + // stack: new_ctx, (old stack) + DUP1 + SET_CONTEXT + // stack: (empty) + PUSH 0x100000000 // = 2^32 (is_kernel = true) + // stack: kexit_info + + PUSH 192 %calldatasize DUP2 DUP2 + // stack: calldata_size, 192, calldata_size, 192, kexit_info + MOD %jumpi(fault_exception) // calldata_size should be a multiple of 192 + DIV + // stack: k, kexit_info + DUP1 %mul_const(@SNARKV_DYNAMIC_GAS) %add_const(@SNARKV_STATIC_GAS) + %stack (gas, k, kexit_info) -> (gas, kexit_info, k) + %charge_gas + SWAP1 + // stack: k, kexit_info + PUSH 0 +loading_loop: + // stack: i, k, kexit_info + DUP2 DUP2 EQ %jumpi(loading_done) + // stack: i, k, kexit_info + DUP1 %mul_const(192) + // stack: px, i, k, kexit_info + GET_CONTEXT + %stack (ctx, px) -> (ctx, @SEGMENT_CALLDATA, px, 32, loading_loop_contd, px) + %jump(mload_packing) +loading_loop_contd: + // stack: x, px, i, k, kexit_info + SWAP1 %add_const(32) + GET_CONTEXT + %stack (ctx, py) -> (ctx, @SEGMENT_CALLDATA, py, 32, loading_loop_contd2, py) + %jump(mload_packing) +loading_loop_contd2: + // stack: y, py, x, i, k, kexit_info + SWAP1 %add_const(32) + GET_CONTEXT + %stack (ctx, px_im) -> (ctx, @SEGMENT_CALLDATA, px_im, 32, loading_loop_contd3, px_im) + %jump(mload_packing) +loading_loop_contd3: + // stack: x_im, px_im, y, x, i, k, kexit_info + SWAP1 %add_const(32) + // stack: px_re, x_im, y, x, i, k, kexit_info + GET_CONTEXT + %stack (ctx, px_re) -> (ctx, @SEGMENT_CALLDATA, px_re, 32, loading_loop_contd4, px_re) + %jump(mload_packing) +loading_loop_contd4: + // stack: x_re, px_re, x_im, y, x, i, k, kexit_info + SWAP1 %add_const(32) + // stack: py_im, x_re, x_im, y, x, i, k, kexit_info + GET_CONTEXT + %stack (ctx, py_im) -> (ctx, @SEGMENT_CALLDATA, py_im, 32, loading_loop_contd5, py_im) + %jump(mload_packing) +loading_loop_contd5: + // stack: y_im, py_im, x_re, x_im, y, x, i, k, kexit_info + SWAP1 %add_const(32) + // stack: py_re, y_im, x_re, x_im, y, x, i, k, kexit_info + GET_CONTEXT + %stack (ctx, py_re) -> (ctx, @SEGMENT_CALLDATA, py_re, 32, loading_loop_contd6) + %jump(mload_packing) +loading_loop_contd6: + // stack: y_re, y_im, x_re, x_im, y, x, i, k, kexit_info + SWAP1 + // stack: y_im, y_re, x_re, x_im, y, x, i, k, kexit_info + DUP7 + // stack: i, y_im, y_re, x_re, x_im, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(5) + %mstore_kernel_bn254_pairing + // stack: y_re, x_re, x_im, y, x, i, k, kexit_info + DUP6 + // stack: i, y_re, x_re, x_im, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(4) + %mstore_kernel_bn254_pairing + SWAP1 + // stack: x_im, x_re, y, x, i, k, kexit_info + DUP5 + // stack: i, x_im, x_re, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(3) + %mstore_kernel_bn254_pairing + // stack: x_re, y, x, i, k, kexit_info + DUP4 + // stack: i, x_re, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(2) + %mstore_kernel_bn254_pairing + // stack: y, x, i, k, kexit_info + DUP3 + // stack: i, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(1) + %mstore_kernel_bn254_pairing + // stack: x, i, k, kexit_info + DUP2 + // stack: i, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %mstore_kernel_bn254_pairing + // stack: i, k, kexit_info + %increment + %jump(loading_loop) + +loading_done: + %stack (i, k) -> (k, @SNARKV_INP, @SNARKV_OUT, got_result) + %jump(bn254_pairing) +got_result: + // stack: result, kexit_info + DUP1 %eq_const(@U256_MAX) %jumpi(fault_exception) + // stack: result, kexit_info + // Store the result bool (repr. by a U256) to the parent's return data using `mstore_unpacking`. + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32) + %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) + %stack (parent_ctx, address) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, address, 32, pop_and_return_success) + %jump(mstore_unpacking) diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm index edb63e2d..84d8d0ef 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm @@ -1,3 +1,34 @@ +%macro sload_current + %stack (slot) -> (slot, %%after) + %jump(sload_current) +%%after: +%endmacro + +global sload_current: + %stack (slot) -> (slot, after_storage_read) + %slot_to_storage_key + // stack: storage_key, after_storage_read + PUSH 64 // storage_key has 64 nibbles + %current_storage_trie + // stack: storage_root_ptr, 64, storage_key, after_storage_read + %jump(mpt_read) + +global after_storage_read: + // stack: value_ptr, retdest + DUP1 %jumpi(storage_key_exists) + + // Storage key not found. Return default value_ptr = 0, + // which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0. + %stack (value_ptr, retdest) -> (retdest, 0) + JUMP + +global storage_key_exists: + // stack: value_ptr, retdest + %mload_trie_data + // stack: value, retdest + SWAP1 + JUMP + // Read a word from the current account's storage trie. // // Pre stack: kexit_info, slot @@ -6,38 +37,20 @@ global sys_sload: // stack: kexit_info, slot SWAP1 - // stack: slot, kexit_info - DUP1 %address - // stack: addr, slot, slot, kexit_info - %insert_accessed_storage_keys PUSH @GAS_COLDSLOAD_MINUS_WARMACCESS - MUL - PUSH @GAS_WARMACCESS - ADD - %stack (gas, slot, kexit_info) -> (gas, kexit_info, slot) + DUP1 + // stack: slot, slot, kexit_info + %sload_current + + %stack (value, slot, kexit_info) -> (slot, value, kexit_info, value) + %address + // stack: addr, slot, value, kexit_info, value + %insert_accessed_storage_keys + // stack: cold_access, old_value, kexit_info, value + SWAP1 POP + // stack: cold_access, kexit_info, value + %mul_const(@GAS_COLDSLOAD_MINUS_WARMACCESS) + %add_const(@GAS_WARMACCESS) %charge_gas - // stack: kexit_info, slot - - SWAP1 - %stack (slot) -> (slot, after_storage_read) - %slot_to_storage_key - // stack: storage_key, after_storage_read, kexit_info - PUSH 64 // storage_key has 64 nibbles - %current_storage_trie - // stack: storage_root_ptr, 64, storage_key, after_storage_read, kexit_info - %jump(mpt_read) - -after_storage_read: - // stack: value_ptr, kexit_info - DUP1 %jumpi(storage_key_exists) - - // Storage key not found. Return default value_ptr = 0, - // which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0. - %stack (value_ptr, kexit_info) -> (kexit_info, 0) + // stack: kexit_info, value EXIT_KERNEL -storage_key_exists: - // stack: value_ptr, kexit_info - %mload_trie_data - // stack: value, kexit_info - SWAP1 - EXIT_KERNEL diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm index 6da8f567..af8bc912 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -6,14 +6,42 @@ global sys_sstore: %check_static %stack (kexit_info, slot, value) -> (slot, kexit_info, slot, value) - %address %insert_accessed_storage_keys POP // TODO: Use return value in gas calculation. - // TODO: Assuming a cold zero -> nonzero write for now. - PUSH @GAS_COLDSLOAD - PUSH @GAS_SSET - ADD + %sload_current + %address + %stack (addr, current_value, kexit_info, slot, value) -> (addr, slot, current_value, current_value, kexit_info, slot, value) + %insert_accessed_storage_keys + // stack: cold_access, original_value, current_value, kexit_info, slot, value + %mul_const(@GAS_COLDSLOAD) + + // Check for warm access. + %stack (gas, original_value, current_value, kexit_info, slot, value) -> + (value, current_value, current_value, original_value, gas, original_value, current_value, kexit_info, slot, value) + EQ SWAP2 EQ ISZERO + // stack: current_value==original_value, value==current_value, gas, original_value, current_value, kexit_info, slot, value) + ADD // OR + %jumpi(sstore_warm) + + // Check for sset (set a zero storage slot to a non-zero value). + // stack: gas, original_value, current_value, kexit_info, slot, value + DUP2 ISZERO %mul_const(@GAS_SSET) ADD + + // Check for sreset (set a non-zero storage slot to a non-zero value). + // stack: gas, original_value, current_value, kexit_info, slot, value + DUP2 ISZERO ISZERO %mul_const(@GAS_SRESET) ADD + %jump(sstore_charge_gas) + +sstore_warm: + // stack: gas, original_value, current_value, kexit_info, slot, value) + %add_const(@GAS_WARMACCESS) + +sstore_charge_gas: + %stack (gas, original_value, current_value, kexit_info, slot, value) -> (gas, kexit_info, current_value, slot, value) %charge_gas - %stack (kexit_info, slot, value) -> (slot, value, kexit_info) + // Check if `value` is equal to `current_value`, and if so exit the kernel early. + %stack (kexit_info, current_value, slot, value) -> (value, current_value, slot, value, kexit_info) + EQ %jumpi(sstore_noop) + // TODO: If value = 0, delete the key instead of inserting 0. // stack: slot, value, kexit_info @@ -57,3 +85,8 @@ after_storage_insert: after_state_insert: // stack: kexit_info EXIT_KERNEL + +sstore_noop: + // stack: slot, value, kexit_info + %pop2 + EXIT_KERNEL diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index f25032ff..2ee44c88 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -44,6 +44,10 @@ pub fn evm_constants() -> HashMap { c.insert(name.into(), U256::from(value)); } + for (name, value) in SNARKV_POINTERS { + c.insert(name.into(), U256::from(value)); + } + for segment in Segment::all() { c.insert(segment.var_name().into(), (segment as u32).into()); } @@ -240,6 +244,8 @@ const PRECOMPILES_GAS: [(&str, u16); 13] = [ ("BLAKE2_F_DYNAMIC_GAS", 1), ]; +const SNARKV_POINTERS: [(&str, u64); 2] = [("SNARKV_INP", 112), ("SNARKV_OUT", 100)]; + const CODE_SIZE_LIMIT: [(&str, u64); 3] = [ ("MAX_CODE_SIZE", 0x6000), ("MAX_INITCODE_SIZE", 0xc000), diff --git a/evm/src/cpu/kernel/tests/core/access_lists.rs b/evm/src/cpu/kernel/tests/core/access_lists.rs index 2b647811..c62d4865 100644 --- a/evm/src/cpu/kernel/tests/core/access_lists.rs +++ b/evm/src/cpu/kernel/tests/core/access_lists.rs @@ -99,12 +99,12 @@ fn test_insert_accessed_storage_keys() -> Result<()> { let mut rng = thread_rng(); let n = rng.gen_range(1..10); let storage_keys = (0..n) - .map(|_| (rng.gen::
(), U256(rng.gen()))) + .map(|_| (rng.gen::
(), U256(rng.gen()), U256(rng.gen()))) .collect::>() .into_iter() - .collect::>(); + .collect::>(); let storage_key_in_list = storage_keys[rng.gen_range(0..n)]; - let storage_key_not_in_list = (rng.gen::
(), U256(rng.gen())); + let storage_key_not_in_list = (rng.gen::
(), U256(rng.gen()), U256(rng.gen())); assert!( !storage_keys.contains(&storage_key_not_in_list), "Cosmic luck or bad RNG?" @@ -113,6 +113,7 @@ fn test_insert_accessed_storage_keys() -> Result<()> { // Test for storage key already in list. let initial_stack = vec![ retaddr, + storage_key_in_list.2, storage_key_in_list.1, U256::from(storage_key_in_list.0 .0.as_slice()), ]; @@ -122,30 +123,35 @@ fn test_insert_accessed_storage_keys() -> Result<()> { interpreter .generation_state .memory - .set(MemoryAddress::new(0, AccessedStorageKeys, 2 * i), addr); + .set(MemoryAddress::new(0, AccessedStorageKeys, 3 * i), addr); interpreter.generation_state.memory.set( - MemoryAddress::new(0, AccessedStorageKeys, 2 * i + 1), + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 1), storage_keys[i].1, ); + interpreter.generation_state.memory.set( + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 2), + storage_keys[i].2, + ); } interpreter.generation_state.memory.set( MemoryAddress::new(0, GlobalMetadata, AccessedStorageKeysLen as usize), - U256::from(2 * n), + U256::from(3 * n), ); interpreter.run()?; - assert_eq!(interpreter.stack(), &[U256::zero()]); + assert_eq!(interpreter.stack(), &[storage_key_in_list.2, U256::zero()]); assert_eq!( interpreter.generation_state.memory.get(MemoryAddress::new( 0, GlobalMetadata, AccessedStorageKeysLen as usize )), - U256::from(2 * n) + U256::from(3 * n) ); // Test for storage key not in list. let initial_stack = vec![ retaddr, + storage_key_not_in_list.2, storage_key_not_in_list.1, U256::from(storage_key_not_in_list.0 .0.as_slice()), ]; @@ -155,41 +161,56 @@ fn test_insert_accessed_storage_keys() -> Result<()> { interpreter .generation_state .memory - .set(MemoryAddress::new(0, AccessedStorageKeys, 2 * i), addr); + .set(MemoryAddress::new(0, AccessedStorageKeys, 3 * i), addr); interpreter.generation_state.memory.set( - MemoryAddress::new(0, AccessedStorageKeys, 2 * i + 1), + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 1), storage_keys[i].1, ); + interpreter.generation_state.memory.set( + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 2), + storage_keys[i].2, + ); } interpreter.generation_state.memory.set( MemoryAddress::new(0, GlobalMetadata, AccessedStorageKeysLen as usize), - U256::from(2 * n), + U256::from(3 * n), ); interpreter.run()?; - assert_eq!(interpreter.stack(), &[U256::one()]); + assert_eq!( + interpreter.stack(), + &[storage_key_not_in_list.2, U256::one()] + ); assert_eq!( interpreter.generation_state.memory.get(MemoryAddress::new( 0, GlobalMetadata, AccessedStorageKeysLen as usize )), - U256::from(2 * (n + 1)) + U256::from(3 * (n + 1)) ); assert_eq!( interpreter .generation_state .memory - .get(MemoryAddress::new(0, AccessedStorageKeys, 2 * n,)), + .get(MemoryAddress::new(0, AccessedStorageKeys, 3 * n,)), U256::from(storage_key_not_in_list.0 .0.as_slice()) ); assert_eq!( interpreter.generation_state.memory.get(MemoryAddress::new( 0, AccessedStorageKeys, - 2 * n + 1, + 3 * n + 1, )), storage_key_not_in_list.1 ); + assert_eq!( + interpreter.generation_state.memory.get(MemoryAddress::new( + 0, + AccessedStorageKeys, + 3 * n + 2, + )), + storage_key_not_in_list.2 + ); Ok(()) } diff --git a/evm/src/witness/util.rs b/evm/src/witness/util.rs index a5ebf2ac..94e13e50 100644 --- a/evm/src/witness/util.rs +++ b/evm/src/witness/util.rs @@ -45,9 +45,7 @@ pub(crate) fn kernel_peek( segment: Segment, virt: usize, ) -> U256 { - state - .memory - .get(MemoryAddress::new(state.registers.context, segment, virt)) + state.memory.get(MemoryAddress::new(0, segment, virt)) } pub(crate) fn mem_read_with_log( diff --git a/plonky2/Cargo.toml b/plonky2/Cargo.toml index 6df46060..39b95f21 100644 --- a/plonky2/Cargo.toml +++ b/plonky2/Cargo.toml @@ -31,6 +31,7 @@ plonky2_util = { version = "0.1.0", default-features = false } rand = { version = "0.8.4", default-features = false } rand_chacha = { version = "0.3.1", optional = true, default-features = false } serde = { version = "1.0", default-features = false, features = ["derive"] } +serde_json = "1.0" static_assertions = { version = "1.1.0", default-features = false } unroll = { version = "0.1.5", default-features = false } diff --git a/plonky2/examples/fibonacci_serialization.rs b/plonky2/examples/fibonacci_serialization.rs new file mode 100644 index 00000000..68943457 --- /dev/null +++ b/plonky2/examples/fibonacci_serialization.rs @@ -0,0 +1,79 @@ +#![allow(clippy::upper_case_acronyms)] + +use std::fs; + +use anyhow::Result; +use plonky2::field::types::Field; +use plonky2::iop::witness::{PartialWitness, WitnessWrite}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + +/// An example of using Plonky2 to prove a statement of the form +/// "I know the 100th element of the Fibonacci sequence, starting with constants a and b." +/// When a == 0 and b == 1, this is proving knowledge of the 100th (standard) Fibonacci number. +/// This example also serializes the circuit data and proof to JSON files. +fn main() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + // The arithmetic circuit. + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + let mut prev_target = initial_a; + let mut cur_target = initial_b; + for _ in 0..99 { + let temp = builder.add(prev_target, cur_target); + prev_target = cur_target; + cur_target = temp; + } + + // Public inputs are the two initial values (provided below) and the result (which is generated). + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(cur_target); + + // Provide initial values. + let mut pw = PartialWitness::new(); + pw.set_target(initial_a, F::ZERO); + pw.set_target(initial_b, F::ONE); + + let data = builder.build::(); + + let common_circuit_data_serialized = serde_json::to_string(&data.common).unwrap(); + fs::write("common_circuit_data.json", common_circuit_data_serialized) + .expect("Unable to write file"); + + let verifier_only_circuit_data_serialized = serde_json::to_string(&data.verifier_only).unwrap(); + fs::write( + "verifier_only_circuit_data.json", + verifier_only_circuit_data_serialized, + ) + .expect("Unable to write file"); + + let proof = data.prove(pw)?; + + let proof_serialized = serde_json::to_string(&proof).unwrap(); + fs::write("proof_with_public_inputs.json", proof_serialized).expect("Unable to write file"); + + let proof_challenges = proof + .get_challenges( + proof.get_public_inputs_hash(), + &data.verifier_only.circuit_digest, + &data.common, + ) + .unwrap(); + let proof_challenges_serialized = serde_json::to_string(&proof_challenges).unwrap(); + fs::write("proof_challenges.json", proof_challenges_serialized).expect("Unable to write file"); + + println!( + "100th Fibonacci number mod |F| (starting with {}, {}) is: {}", + proof.public_inputs[0], proof.public_inputs[1], proof.public_inputs[2] + ); + + data.verify(proof) +} diff --git a/plonky2/src/fri/mod.rs b/plonky2/src/fri/mod.rs index ca800b98..5121d755 100644 --- a/plonky2/src/fri/mod.rs +++ b/plonky2/src/fri/mod.rs @@ -1,5 +1,7 @@ use alloc::vec::Vec; +use serde::Serialize; + use crate::fri::reduction_strategies::FriReductionStrategy; mod challenges; @@ -13,7 +15,7 @@ mod validate_shape; pub mod verifier; pub mod witness_util; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct FriConfig { /// `rate = 2^{-rate_bits}`. pub rate_bits: usize, @@ -56,7 +58,7 @@ impl FriConfig { /// FRI parameters, including generated parameters which are specific to an instance size, in /// contrast to `FriConfig` which is user-specified and independent of instance size. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct FriParams { /// User-specified FRI configuration. pub config: FriConfig, diff --git a/plonky2/src/fri/proof.rs b/plonky2/src/fri/proof.rs index 326001fd..d00feb4c 100644 --- a/plonky2/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -393,6 +393,7 @@ impl, HCO: HashConfig, H: Hasher, const D: } } +#[derive(Serialize)] pub struct FriChallenges, const D: usize> { // Scaling factor to combine polynomials. pub fri_alpha: F::Extension, diff --git a/plonky2/src/fri/reduction_strategies.rs b/plonky2/src/fri/reduction_strategies.rs index 409a0224..df273eea 100644 --- a/plonky2/src/fri/reduction_strategies.rs +++ b/plonky2/src/fri/reduction_strategies.rs @@ -4,9 +4,10 @@ use alloc::vec::Vec; use std::time::Instant; use log::debug; +use serde::Serialize; /// A method for deciding what arity to use at each reduction layer. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub enum FriReductionStrategy { /// Specifies the exact sequence of arities (expressed in bits) to use. Fixed(Vec), diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index f794c904..5fac1f00 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -2,6 +2,8 @@ use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; +use serde::{Deserialize, Serialize}; + use crate::field::extension::Extendable; use crate::field::packed::PackedField; use crate::gates::gate::Gate; @@ -18,7 +20,7 @@ use crate::plonk::vars::{ use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate which takes a single constant parameter and outputs that value. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct ConstantGate { pub(crate) num_consts: usize, } diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 43c1179a..1dbc4f57 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -8,6 +8,7 @@ use core::hash::{Hash, Hasher}; use core::ops::Range; use hashbrown::HashMap; +use serde::{Serialize, Serializer}; use crate::field::batch_util::batch_multiply_inplace; use crate::field::extension::{Extendable, FieldExtension}; @@ -239,6 +240,12 @@ impl, const D: usize> Debug for GateRef { } } +impl, const D: usize> Serialize for GateRef { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.0.id()) + } +} + /// Map between gate parameters and available slots. /// An available slot is of the form `(row, op)`, meaning the current available slot /// is at gate index `row` in the `op`-th operation. diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 7217de2f..0e690c6d 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -2,6 +2,8 @@ use alloc::vec; use alloc::vec::Vec; use core::ops::Range; +use serde::Serialize; + use crate::field::extension::Extendable; use crate::field::polynomial::PolynomialValues; use crate::gates::gate::{GateInstance, GateRef}; @@ -10,7 +12,7 @@ use crate::hash::hash_types::RichField; /// Placeholder value to indicate that a gate doesn't use a selector polynomial. pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct SelectorsInfo { pub(crate) selector_indices: Vec, pub(crate) groups: Vec>, diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index fa9af818..8ecf646e 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use core::ops::{Range, RangeFrom}; use anyhow::Result; +use serde::Serialize; use crate::field::extension::Extendable; use crate::field::fft::FftRootTable; @@ -35,7 +36,7 @@ use crate::util::serialization::{ }; use crate::util::timing::TimingTree; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct CircuitConfig { pub num_wires: usize, pub num_routed_wires: usize, @@ -347,7 +348,7 @@ pub struct ProverOnlyCircuitData< } /// Circuit data required by the verifier, but not the prover. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct VerifierOnlyCircuitData, const D: usize> { /// A commitment to each constant polynomial and each permutation polynomial. pub constants_sigmas_cap: MerkleCap, @@ -370,7 +371,7 @@ impl, const D: usize> VerifierOnlyCircuitData { } /// Circuit data required by both the prover and the verifier. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct CommonCircuitData, const D: usize> { pub config: CircuitConfig, diff --git a/plonky2/src/plonk/config.rs b/plonky2/src/plonk/config.rs index 60f9a7b8..a5fe5bdc 100644 --- a/plonky2/src/plonk/config.rs +++ b/plonky2/src/plonk/config.rs @@ -117,7 +117,7 @@ impl HashConfig for PoseidonHashConfig { const WIDTH: usize = 12; } /// Configuration using Poseidon over the Goldilocks field. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize)] pub struct PoseidonGoldilocksConfig; impl GenericConfig<2> for PoseidonGoldilocksConfig { type F = GoldilocksField; diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index d0682572..0e90b398 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -94,7 +94,7 @@ impl, C: GenericConfig, const D: usize> } /// Computes all Fiat-Shamir challenges used in the Plonk proof. - pub(crate) fn get_challenges( + pub fn get_challenges( &self, public_inputs_hash: <>::InnerHasher as Hasher>::Hash, circuit_digest: &<>::Hasher as Hasher>::Hash, diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 90a7ea86..fe4a0511 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -102,7 +102,7 @@ impl, C: GenericConfig, const D: usize> }) } - pub(crate) fn get_public_inputs_hash( + pub fn get_public_inputs_hash( &self, ) -> <>::InnerHasher as Hasher>::Hash where @@ -276,7 +276,8 @@ impl, C: GenericConfig, const D: usize> } } -pub(crate) struct ProofChallenges, const D: usize> { +#[derive(Serialize)] +pub struct ProofChallenges, const D: usize> { /// Random values used in Plonk's permutation argument. pub plonk_betas: Vec, From 503cb8a99f6d6065095df394a1229fd004d2c702 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 16:20:55 -0700 Subject: [PATCH 34/43] random inp --- evm/src/bn254_pairing.rs | 31 ++++++++++++++++++++++++++----- evm/src/cpu/kernel/tests/bn254.rs | 15 +++++++++++---- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/evm/src/bn254_pairing.rs b/evm/src/bn254_pairing.rs index 44e22189..5f3fc7fa 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/bn254_pairing.rs @@ -1,6 +1,8 @@ use std::ops::{Add, Mul, Neg}; use ethereum_types::U256; +use rand::distributions::Standard; +use rand::prelude::Distribution; use rand::Rng; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254}; @@ -23,6 +25,26 @@ impl Curve { } } +impl Curve +where + T: FieldExt, + Curve: CyclicGroup, +{ + pub fn int(z: i32) -> Self { + Curve::::GENERATOR * z + } +} + +impl Distribution> for Standard +where + T: FieldExt, + Curve: CyclicGroup, +{ + fn sample(&self, rng: &mut R) -> Curve { + Curve::::GENERATOR * rng.gen::() + } +} + /// Standard addition formula for elliptic curves, restricted to the cases /// https://en.wikipedia.org/wiki/Elliptic_curve#Algebraic_interpretation impl Add for Curve { @@ -62,14 +84,14 @@ impl Neg for Curve { } } -pub trait CurveGroup { +pub trait CyclicGroup { const GENERATOR: Self; } /// The BN curve consists of pairs /// (x, y): (BN254, BN254) | y^2 = x^3 + 2 // with generator given by (1, 2) -impl CurveGroup for Curve { +impl CyclicGroup for Curve { const GENERATOR: Curve = Curve { x: BN254 { val: U256::one() }, y: BN254 { @@ -81,7 +103,7 @@ impl CurveGroup for Curve { impl Mul for Curve where T: FieldExt, - Curve: CurveGroup, + Curve: CyclicGroup, { type Output = Curve; @@ -107,7 +129,6 @@ where exp >>= 1; x = x + x; } - println!("result: {:?}", result); result } } @@ -115,7 +136,7 @@ where /// The twisted curve consists of pairs /// (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) /// with generator given as follows -impl CurveGroup for Curve> { +impl CyclicGroup for Curve> { const GENERATOR: Curve> = Curve { x: Fp2 { re: BN254 { diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 25ec6429..63796a4e 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -4,7 +4,7 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; -use crate::bn254_pairing::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CurveGroup}; +use crate::bn254_pairing::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CyclicGroup}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; @@ -213,7 +213,15 @@ fn pairing_input() -> Vec { fn test_bn_miller() -> Result<()> { let ptr: usize = 100; let out: usize = 106; - let input = pairing_input(); + + let mut rng = rand::thread_rng(); + let p: Curve = rng.gen::>(); + let q: Curve> = rng.gen::>>(); + + let p_stack: [U256; 2] = unsafe { transmute(p) }; + let q_stack: [U256; 4] = unsafe { transmute(q) }; + let mut input = p_stack.to_vec(); + input.extend(q_stack); let setup = InterpreterMemoryInitialization { label: "bn254_miller".to_string(), @@ -223,8 +231,7 @@ fn test_bn_miller() -> Result<()> { }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = - miller_loop(Curve::::GENERATOR, Curve::>::GENERATOR).on_stack(); + let expected = miller_loop(p, q).on_stack(); assert_eq!(output, expected); From ae4b50913994bd93f69b65304aeff4b0a6291e4f Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 16:24:36 -0700 Subject: [PATCH 35/43] neutral name --- evm/src/cpu/kernel/tests/bn254.rs | 2 +- evm/src/{bn254_pairing.rs => curve_pairings.rs} | 0 evm/src/lib.rs | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename evm/src/{bn254_pairing.rs => curve_pairings.rs} (100%) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 63796a4e..4ca60696 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -4,7 +4,7 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; -use crate::bn254_pairing::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CyclicGroup}; +use crate::curve_pairings::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CyclicGroup}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; diff --git a/evm/src/bn254_pairing.rs b/evm/src/curve_pairings.rs similarity index 100% rename from evm/src/bn254_pairing.rs rename to evm/src/curve_pairings.rs diff --git a/evm/src/lib.rs b/evm/src/lib.rs index dc07d233..edce8060 100644 --- a/evm/src/lib.rs +++ b/evm/src/lib.rs @@ -9,7 +9,7 @@ pub mod all_stark; pub mod arithmetic; -pub mod bn254_pairing; +pub mod curve_pairings; pub mod config; pub mod constraint_consumer; pub mod cpu; From 57113905de3aba768084c0cd6c2f9da1631d4340 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 16:26:40 -0700 Subject: [PATCH 36/43] redundant --- evm/src/cpu/kernel/tests/bn254.rs | 10 +--------- evm/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 4ca60696..1f2f12e3 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -4,11 +4,11 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; -use crate::curve_pairings::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CyclicGroup}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; +use crate::curve_pairings::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CyclicGroup}; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; @@ -201,14 +201,6 @@ fn test_bn_final_exponent() -> Result<()> { Ok(()) } -fn pairing_input() -> Vec { - let curve_gen: [U256; 2] = unsafe { transmute(Curve::::GENERATOR) }; - let twisted_gen: [U256; 4] = unsafe { transmute(Curve::>::GENERATOR) }; - let mut input = curve_gen.to_vec(); - input.extend_from_slice(&twisted_gen); - input -} - #[test] fn test_bn_miller() -> Result<()> { let ptr: usize = 100; diff --git a/evm/src/lib.rs b/evm/src/lib.rs index edce8060..02730321 100644 --- a/evm/src/lib.rs +++ b/evm/src/lib.rs @@ -9,11 +9,11 @@ pub mod all_stark; pub mod arithmetic; -pub mod curve_pairings; pub mod config; pub mod constraint_consumer; pub mod cpu; pub mod cross_table_lookup; +pub mod curve_pairings; pub mod extension_tower; pub mod fixed_recursive_verifier; pub mod generation; From 4a42ddb2038371f3d67fd5f24ecb80cee821f8b2 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 17:15:25 -0700 Subject: [PATCH 37/43] on stack --- evm/src/cpu/kernel/tests/bn254.rs | 10 +++----- evm/src/curve_pairings.rs | 10 +++++++- evm/src/extension_tower.rs | 42 +++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 1f2f12e3..51966f59 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -1,5 +1,3 @@ -use std::mem::transmute; - use anyhow::Result; use ethereum_types::U256; use rand::Rng; @@ -8,7 +6,7 @@ use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; -use crate::curve_pairings::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CyclicGroup}; +use crate::curve_pairings::{final_exponent, gen_fp12_sparse, miller_loop, Curve}; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; @@ -210,10 +208,8 @@ fn test_bn_miller() -> Result<()> { let p: Curve = rng.gen::>(); let q: Curve> = rng.gen::>>(); - let p_stack: [U256; 2] = unsafe { transmute(p) }; - let q_stack: [U256; 4] = unsafe { transmute(q) }; - let mut input = p_stack.to_vec(); - input.extend(q_stack); + let mut input = p.on_stack(); + input.extend(q.on_stack()); let setup = InterpreterMemoryInitialization { label: "bn254_miller".to_string(), diff --git a/evm/src/curve_pairings.rs b/evm/src/curve_pairings.rs index 5f3fc7fa..fc369406 100644 --- a/evm/src/curve_pairings.rs +++ b/evm/src/curve_pairings.rs @@ -5,7 +5,7 @@ use rand::distributions::Standard; use rand::prelude::Distribution; use rand::Rng; -use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254}; +use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; #[derive(Debug, Copy, Clone, PartialEq)] pub struct Curve @@ -25,6 +25,14 @@ impl Curve { } } +impl Curve { + pub fn on_stack(self) -> Vec { + let mut stack = self.x.on_stack(); + stack.extend(self.y.on_stack()); + stack + } +} + impl Curve where T: FieldExt, diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index 2c81b035..0e654c88 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -1,5 +1,4 @@ use std::fmt::Debug; -use std::mem::transmute; use std::ops::{Add, Div, Mul, Neg, Sub}; use ethereum_types::{U256, U512}; @@ -1227,22 +1226,51 @@ pub trait Stack { fn on_stack(self) -> Vec; } +impl Stack for BN254 { + fn on_stack(self) -> Vec { + vec![self.val] + } +} + impl Stack for BLS381 { fn on_stack(self) -> Vec { vec![self.lo(), self.hi()] } } -impl Stack for Fp6 { +impl Stack for Fp2 +where + T: FieldExt + Stack, +{ fn on_stack(self) -> Vec { - let f: [U256; 6] = unsafe { transmute(self) }; - f.into_iter().collect() + let mut stack = self.re.on_stack(); + stack.extend(self.im.on_stack()); + stack } } -impl Stack for Fp12 { +impl Stack for Fp6 +where + T: FieldExt, + Fp2: Adj + Stack, +{ fn on_stack(self) -> Vec { - let f: [U256; 12] = unsafe { transmute(self) }; - f.into_iter().collect() + let mut stack = self.t0.on_stack(); + stack.extend(self.t1.on_stack()); + stack.extend(self.t2.on_stack()); + stack + } +} + +impl Stack for Fp12 +where + T: FieldExt, + Fp2: Adj, + Fp6: Stack, +{ + fn on_stack(self) -> Vec { + let mut stack = self.z0.on_stack(); + stack.extend(self.z1.on_stack()); + stack } } From f6a49e88cba5073ddb829b218706a94caf367806 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 17:23:55 -0700 Subject: [PATCH 38/43] fair naming --- evm/src/cpu/kernel/tests/bn254.rs | 8 ++--- evm/src/curve_pairings.rs | 56 +++++++++++++++---------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 51966f59..7a5154d5 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -6,7 +6,7 @@ use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; -use crate::curve_pairings::{final_exponent, gen_fp12_sparse, miller_loop, Curve}; +use crate::curve_pairings::{bn_final_exponent, gen_bn_fp12_sparse, bn_miller_loop, Curve}; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; @@ -84,7 +84,7 @@ fn test_bn_mul_fp12() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let g: Fp12 = rng.gen::>(); - let h: Fp12 = gen_fp12_sparse(&mut rng); + let h: Fp12 = gen_bn_fp12_sparse(&mut rng); let out_normal: Vec = run_bn_mul_fp12(f, g, "mul_fp254_12"); let out_sparse: Vec = run_bn_mul_fp12(f, h, "mul_fp254_12_sparse"); @@ -192,7 +192,7 @@ fn test_bn_final_exponent() -> Result<()> { let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); - let expected: Vec = final_exponent(f).on_stack(); + let expected: Vec = bn_final_exponent(f).on_stack(); assert_eq!(output, expected); @@ -219,7 +219,7 @@ fn test_bn_miller() -> Result<()> { }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = miller_loop(p, q).on_stack(); + let expected = bn_miller_loop(p, q).on_stack(); assert_eq!(output, expected); diff --git a/evm/src/curve_pairings.rs b/evm/src/curve_pairings.rs index fc369406..c16aed2a 100644 --- a/evm/src/curve_pairings.rs +++ b/evm/src/curve_pairings.rs @@ -186,25 +186,25 @@ impl CyclicGroup for Curve> { } // The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element -pub fn tate(p: Curve, q: Curve>) -> Fp12 { - let miller_output = miller_loop(p, q); - final_exponent(miller_output) +pub fn bn_tate(p: Curve, q: Curve>) -> Fp12 { + let miller_output = bn_miller_loop(p, q); + bn_final_exponent(miller_output) } /// Standard code for miller loop, can be found on page 99 at this url: /// https://static1.squarespace.com/static/5fdbb09f31d71c1227082339/t/5ff394720493bd28278889c6/1609798774687/PairingsForBeginners.pdf#page=107 -/// where EXP is a hardcoding of the array of Booleans that the loop traverses -pub fn miller_loop(p: Curve, q: Curve>) -> Fp12 { +/// where BN_EXP is a hardcoding of the array of Booleans that the loop traverses +pub fn bn_miller_loop(p: Curve, q: Curve>) -> Fp12 { let mut r = p; let mut acc: Fp12 = Fp12::::UNIT; let mut line: Fp12; - for i in EXP { - line = tangent(r, q); + for i in BN_EXP { + line = bn_tangent(r, q); r = r + r; acc = line * acc * acc; if i { - line = cord(p, r, q); + line = bn_cord(p, r, q); r = r + p; acc = line * acc; } @@ -213,22 +213,22 @@ pub fn miller_loop(p: Curve, q: Curve>) -> Fp12 { } /// The sloped line function for doubling a point -pub fn tangent(p: Curve, q: Curve>) -> Fp12 { +pub fn bn_tangent(p: Curve, q: Curve>) -> Fp12 { let cx = -BN254::new(3) * p.x * p.x; let cy = BN254::new(2) * p.y; - sparse_embed(p.y * p.y - BN254::new(9), q.x * cx, q.y * cy) + bn_sparse_embed(p.y * p.y - BN254::new(9), q.x * cx, q.y * cy) } /// The sloped line function for adding two points -pub fn cord(p1: Curve, p2: Curve, q: Curve>) -> Fp12 { +pub fn bn_cord(p1: Curve, p2: Curve, q: Curve>) -> Fp12 { let cx = p2.y - p1.y; let cy = p1.x - p2.x; - sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x * cx, q.y * cy) + bn_sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x * cx, q.y * cy) } /// The tangent and cord functions output sparse Fp12 elements. /// This map embeds the nonzero coefficients into an Fp12. -pub fn sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12 { +pub fn bn_sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12 { let g0 = Fp6 { t0: Fp2 { re: g000, @@ -247,8 +247,8 @@ pub fn sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12(rng: &mut R) -> Fp12 { - sparse_embed( +pub fn gen_bn_fp12_sparse(rng: &mut R) -> Fp12 { + bn_sparse_embed( rng.gen::(), rng.gen::>(), rng.gen::>(), @@ -267,10 +267,10 @@ pub fn gen_fp12_sparse(rng: &mut R) -> Fp12 { /// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 /// where 0 < a0, a1, a2 < p. Then the final power is given by /// y = y_3 * (y^a2)_2 * (y^-a1)_1 * (y^-a0) -pub fn final_exponent(f: Fp12) -> Fp12 { +pub fn bn_final_exponent(f: Fp12) -> Fp12 { let mut y = f.frob(6) / f; y = y.frob(2) * y; - let (y_a2, y_a1, y_a0) = get_custom_powers(y); + let (y_a2, y_a1, y_a0) = get_bn_custom_powers(y); y.frob(3) * y_a2.frob(2) * y_a1.frob(1) * y_a0 } @@ -282,10 +282,10 @@ pub fn final_exponent(f: Fp12) -> Fp12 { /// y^a2, y^a1 = y^a4 * y^a2 * y^a2 * y^(-a0), y^(-a0) /// /// Representing a4, a2, a0 in *little endian* binary, define -/// EXPS4 = [(a4[i], a2[i], a0[i]) for i in 0..len(a4)] -/// EXPS2 = [ (a2[i], a0[i]) for i in len(a4)..len(a2)] -/// EXPS0 = [ a0[i] for i in len(a2)..len(a0)] -fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { +/// BN_EXPS4 = [(a4[i], a2[i], a0[i]) for i in 0..len(a4)] +/// BN_EXPS2 = [ (a2[i], a0[i]) for i in len(a4)..len(a2)] +/// BN_EXPS0 = [ a0[i] for i in len(a2)..len(a0)] +fn get_bn_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { let mut sq: Fp12 = f; let mut y0: Fp12 = Fp12::::UNIT; let mut y2: Fp12 = Fp12::::UNIT; @@ -294,7 +294,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) // proceed via standard squaring algorithm for exponentiation // must keep multiplying all three values: a4, a2, a0 - for (a, b, c) in EXPS4 { + for (a, b, c) in BN_EXPS4 { if a { y4 = y4 * sq; } @@ -310,7 +310,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) y4 = y4 * sq; // must keep multiplying remaining two values: a2, a0 - for (a, b) in EXPS2 { + for (a, b) in BN_EXPS2 { if a { y2 = y2 * sq; } @@ -323,7 +323,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) y2 = y2 * sq; // must keep multiplying final remaining value: a0 - for a in EXPS0 { + for a in BN_EXPS0 { if a { y0 = y0 * sq; } @@ -339,7 +339,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) (y2, y4 * y2 * y2 * y0_inv, y0_inv) } -const EXP: [bool; 253] = [ +const BN_EXP: [bool; 253] = [ true, false, false, false, false, false, true, true, false, false, true, false, false, false, true, false, false, true, true, true, false, false, true, true, true, false, false, true, false, true, true, true, false, false, false, false, true, false, false, true, true, false, @@ -363,7 +363,7 @@ const EXP: [bool; 253] = [ // The folowing constants are defined above get_custom_powers -const EXPS4: [(bool, bool, bool); 64] = [ +const BN_EXPS4: [(bool, bool, bool); 64] = [ (true, true, false), (true, true, true), (true, true, true), @@ -430,7 +430,7 @@ const EXPS4: [(bool, bool, bool); 64] = [ (true, true, true), ]; -const EXPS2: [(bool, bool); 62] = [ +const BN_EXPS2: [(bool, bool); 62] = [ (true, false), (true, true), (false, false), @@ -495,7 +495,7 @@ const EXPS2: [(bool, bool); 62] = [ (true, true), ]; -const EXPS0: [bool; 65] = [ +const BN_EXPS0: [bool; 65] = [ false, false, true, false, false, true, true, false, true, false, true, true, true, false, true, false, false, false, true, false, false, true, false, true, false, true, true, false, false, false, false, false, true, false, true, false, true, true, true, false, false, true, From b37e049abd16ba2473747590bf059e3e8a2ebba4 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 17:24:06 -0700 Subject: [PATCH 39/43] fmt --- evm/src/cpu/kernel/tests/bn254.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 7a5154d5..c88ec73e 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -6,7 +6,7 @@ use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; use crate::cpu::kernel::tests::u256ify; -use crate::curve_pairings::{bn_final_exponent, gen_bn_fp12_sparse, bn_miller_loop, Curve}; +use crate::curve_pairings::{bn_final_exponent, bn_miller_loop, gen_bn_fp12_sparse, Curve}; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; From 16928fd0fb0e9e94c376fc8aa0399de3b2f52ca8 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 18:06:51 -0700 Subject: [PATCH 40/43] peculiar... --- evm/src/cpu/kernel/tests/bn254.rs | 42 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index c88ec73e..ef574c25 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -5,8 +5,9 @@ use rand::Rng; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; -use crate::cpu::kernel::tests::u256ify; -use crate::curve_pairings::{bn_final_exponent, bn_miller_loop, gen_bn_fp12_sparse, Curve}; +use crate::curve_pairings::{ + bn_final_exponent, bn_miller_loop, gen_bn_fp12_sparse, Curve, CyclicGroup, +}; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; @@ -231,32 +232,35 @@ fn test_bn_pairing() -> Result<()> { let out: usize = 100; let ptr: usize = 112; - let inputs: Vec = u256ify(vec![ - "0x1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59", - "0x3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41", - "0x04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678", - "0x209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7", - "0x120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550", - "0x2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d", - "0x111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c", - "0x2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411", - "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed", - "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", - "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - "0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", - ]) - .unwrap(); + let mut rng = rand::thread_rng(); + let k: usize = rng.gen_range(1..10); + let mut acc: i32 = 0; + let mut input: Vec = vec![]; + for _ in 1..k { + let m: i32 = rng.gen_range(-10..10); + let n: i32 = rng.gen_range(-10..10); + acc -= m * n; + + let p: Curve = Curve::::int(m); + let q: Curve> = Curve::>::int(n); + input.extend(p.on_stack()); + input.extend(q.on_stack()); + } + let p: Curve = Curve::::int(acc); + let q: Curve> = Curve::>::GENERATOR; + input.extend(p.on_stack()); + input.extend(q.on_stack()); let setup = InterpreterMemoryInitialization { label: "bn254_pairing".to_string(), stack: vec![ - U256::from(2), + U256::from(k), U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32), ], segment: BnPairing, - memory: vec![(ptr, inputs)], + memory: vec![(ptr, input)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); From 9b18b3aeec4018ed3b3bd933eea4e554e3e29e0f Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Thu, 27 Apr 2023 18:24:08 -0700 Subject: [PATCH 41/43] fix unit --- .../cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm | 2 +- evm/src/cpu/kernel/tests/bn254.rs | 5 ++--- evm/src/curve_pairings.rs | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 340d8b33..8548d3c7 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -65,7 +65,7 @@ bn254_input_check: bn_pairing_invalid_input: // stack: inp_j, j, k, inp, out, retdest - %stack (inp_j, j, k, inp, out, retdest) -> (retdest, @U256_MAX) + %stack (inp_j, j, k, inp, out, retdest) -> (retdest, inp_j) JUMP bn254_pairing_start: diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index ef574c25..c0faabc4 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -237,8 +237,8 @@ fn test_bn_pairing() -> Result<()> { let mut acc: i32 = 0; let mut input: Vec = vec![]; for _ in 1..k { - let m: i32 = rng.gen_range(-10..10); - let n: i32 = rng.gen_range(-10..10); + let m: i32 = rng.gen_range(1..8); + let n: i32 = rng.gen_range(1..8); acc -= m * n; let p: Curve = Curve::::int(m); @@ -263,7 +263,6 @@ fn test_bn_pairing() -> Result<()> { memory: vec![(ptr, input)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); - assert_eq!(interpreter.stack()[0], U256::one()); Ok(()) } diff --git a/evm/src/curve_pairings.rs b/evm/src/curve_pairings.rs index c16aed2a..708e7fb2 100644 --- a/evm/src/curve_pairings.rs +++ b/evm/src/curve_pairings.rs @@ -19,8 +19,8 @@ where impl Curve { pub fn unit() -> Self { Curve { - x: T::UNIT, - y: T::UNIT, + x: T::ZERO, + y: T::ZERO, } } } From f9aad433fe311161b47c1ebe1d43820f8792b7b2 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Fri, 28 Apr 2023 18:23:08 -0700 Subject: [PATCH 42/43] neutral input --- .../curve/bn254/curve_arithmetic/pairing.asm | 58 ++++++++++++++++--- evm/src/cpu/kernel/tests/bn254.rs | 4 +- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index 8548d3c7..ef109661 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -76,21 +76,37 @@ bn254_pairing_start: // stack: k, inp, out, final_label, out, retdest bn254_pairing_loop: - // stack: k, inp, out, final_label + // stack: k, inp, out, final_label DUP1 ISZERO - // stack: end?, k, inp, out, final_label + // stack: end?, k, inp, out, final_label %jumpi(bn254_final_exponent) - // stack: k, inp, out, final_label + // stack: k, inp, out, final_label %sub_const(1) - // stack: k=k-1, inp, out, final_label - - %stack (k, inp, out) -> (k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out) - // stack: k, inp, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out, final_label + // stack: k=k-1, inp, out, final_label + %stack (k, inp) -> (k, inp, k, inp) + // stack: k, inp, k, inp, out, final_label %mul_const(6) ADD - // stack: inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out, final_label - %jump(bn254_miller) + // stack: inp_k, k, inp, out, final_label + DUP1 + %load_fp254_6 + // stack: P, Q, inp_k, k, inp, out, final_label + %neutral_input + // stack: skip?, inp_k, k, inp, out, final_label + %jumpi(bn_skip_input) + // stack: inp_k, k, inp, out, final_label + %stack (inp_k, k, inp, out) -> (bn254_miller, inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out) + // stack: bn254_miller, inp_k, 0, + // mul_fp254_12, 0, out, out, + // bn254_pairing_loop, k, inp, out, final_label + JUMP + +bn_skip_input: + // stack: inp_k, k, inp, out, final_label + POP + // stack: k, inp, out, final_label + %jump(bn254_pairing_loop) bn254_pairing_output_validation: @@ -137,3 +153,27 @@ bn254_pairing_output_validation: MUL // stack: check, out %endmacro + +%macro neutral_input + // stack: P , Q + ISZERO + SWAP1 + ISZERO + MUL + // stack: P==0, Q + SWAP4 + // stack: Q , P==0 + ISZERO + SWAP1 + ISZERO + MUL + SWAP1 + ISZERO + MUL + SWAP1 + ISZERO + MUL + // stack: Q==0, P==0 + OR + // stack: Q==0||P==0 +%endmacro \ No newline at end of file diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index c0faabc4..548f9789 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -237,8 +237,8 @@ fn test_bn_pairing() -> Result<()> { let mut acc: i32 = 0; let mut input: Vec = vec![]; for _ in 1..k { - let m: i32 = rng.gen_range(1..8); - let n: i32 = rng.gen_range(1..8); + let m: i32 = rng.gen_range(-8..8); + let n: i32 = rng.gen_range(-8..8); acc -= m * n; let p: Curve = Curve::::int(m); From 84f17699be0faf823343193d9c0e14f443be5702 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Fri, 28 Apr 2023 21:57:10 -0700 Subject: [PATCH 43/43] comments --- .../kernel/asm/core/precompiles/snarkv.asm | 4 +- .../curve/bn254/curve_arithmetic/pairing.asm | 48 ++++++++++++------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm b/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm index 26bad450..433186b5 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm @@ -63,7 +63,7 @@ loading_loop_contd5: %jump(mload_packing) loading_loop_contd6: // stack: y_re, y_im, x_re, x_im, y, x, i, k, kexit_info - SWAP1 + SWAP1 // the EVM serializes the imaginary part first // stack: y_im, y_re, x_re, x_im, y, x, i, k, kexit_info DUP7 // stack: i, y_im, y_re, x_re, x_im, y, x, i, k, kexit_info @@ -76,7 +76,7 @@ loading_loop_contd6: %mul_const(6) %add_const(@SNARKV_INP) %add_const(4) %mstore_kernel_bn254_pairing - SWAP1 + SWAP1 // the EVM serializes the imaginary part first // stack: x_im, x_re, y, x, i, k, kexit_info DUP5 // stack: i, x_im, x_re, y, x, i, k, kexit_info diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm index ef109661..4479b965 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -1,3 +1,15 @@ +/// The input to the pairing script is a list of points +/// P_i = n_i*G: Curve, Q_i = m_i*H: TwistedCurve +/// where G, H are the respective generators, such that +/// sum_i n_i*m_i = 0 +/// and therefore, due to bilinearity of the pairing: +/// prod_i e(P_i, Q_i) +/// = prod_i e(n_i G, m_i H) +/// = prod_i e(G,H)^{n_i * m_i} +/// = e(G,H)^{sum_i n_i * m_i} +/// = e(G,H)^0 +/// = 1: Fp12 + /// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Bool: /// /// for P, Q in pairs: @@ -6,7 +18,8 @@ /// /// out = 1 /// for P, Q in pairs: -/// out *= miller_loop(P, Q) +/// if P != 0 and Q != 0: +/// out *= miller_loop(P, Q) /// /// result = bn254_final_exponent(out) /// return result == unit_fp12 @@ -71,41 +84,42 @@ bn_pairing_invalid_input: bn254_pairing_start: // stack: 0, k, inp, out, retdest %stack (j, k, inp, out) -> (out, 1, k, inp, out, bn254_pairing_output_validation, out) - // stack: out, 1, k, inp, out, final_label, out, retdest + // stack: out, 1, k, inp, out, bn254_pairing_output_validation, out, retdest %mstore_kernel_bn254_pairing - // stack: k, inp, out, final_label, out, retdest + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest bn254_pairing_loop: - // stack: k, inp, out, final_label + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest DUP1 ISZERO - // stack: end?, k, inp, out, final_label + // stack: end?, k, inp, out, bn254_pairing_output_validation, out, retdest %jumpi(bn254_final_exponent) - // stack: k, inp, out, final_label + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest %sub_const(1) - // stack: k=k-1, inp, out, final_label + // stack: k=k-1, inp, out, bn254_pairing_output_validation, out, retdest %stack (k, inp) -> (k, inp, k, inp) - // stack: k, inp, k, inp, out, final_label + // stack: k, inp, k, inp, out, bn254_pairing_output_validation, out, retdest %mul_const(6) ADD - // stack: inp_k, k, inp, out, final_label + // stack: inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest DUP1 %load_fp254_6 - // stack: P, Q, inp_k, k, inp, out, final_label + // stack: P, Q, inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest %neutral_input - // stack: skip?, inp_k, k, inp, out, final_label + // stack: skip?, inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest %jumpi(bn_skip_input) - // stack: inp_k, k, inp, out, final_label + // stack: inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest %stack (inp_k, k, inp, out) -> (bn254_miller, inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out) - // stack: bn254_miller, inp_k, 0, - // mul_fp254_12, 0, out, out, - // bn254_pairing_loop, k, inp, out, final_label + // stack: bn254_miller, inp_k, 0, + // mul_fp254_12, 0, out, out, + // bn254_pairing_loop, k, inp, out, + // bn254_pairing_output_validation, out, retdest JUMP bn_skip_input: - // stack: inp_k, k, inp, out, final_label + // stack: inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest POP - // stack: k, inp, out, final_label + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest %jump(bn254_pairing_loop)