From 823b06acab0bbac4054602a308dd3de25bf29f98 Mon Sep 17 00:00:00 2001 From: Dmitry Vagner Date: Tue, 28 Mar 2023 11:12:59 -0700 Subject: [PATCH] fp2 works --- evm/src/cpu/kernel/asm/curve/bls381/util.asm | 62 ++++++++++++++------ evm/src/cpu/kernel/tests/bls381.rs | 39 ++++++++++-- evm/src/cpu/kernel/tests/bn254.rs | 36 ++++++------ evm/src/extension_tower.rs | 50 ++++++++++++---- 4 files changed, 135 insertions(+), 52 deletions(-) diff --git a/evm/src/cpu/kernel/asm/curve/bls381/util.asm b/evm/src/cpu/kernel/asm/curve/bls381/util.asm index 1ef99a8c..c35a56e0 100644 --- a/evm/src/cpu/kernel/asm/curve/bls381/util.asm +++ b/evm/src/cpu/kernel/asm/curve/bls381/util.asm @@ -53,7 +53,7 @@ global test_sub_fp381: %jump(0xdeadbeef) -%macro add_fp381_2 +global add_fp381_2: // stack: x: 2, x_: 2, y: 2, y_: 2 %stack (x: 2, x_: 2, y: 2, y_: 2) -> (y_, x_, y, x) // stack: y_: 2, x_: 2, y: 2, x: 2 @@ -63,28 +63,52 @@ global test_sub_fp381: // stack: x: 2, y: 2, z_: 2 %add_fp381 // stack: z: 2, z_: 2 -%endmacro + %jump(0xdeadbeef) -%macro mul_fp381_2 - // stack: x: 2, x_: 2, y: 2, y_: 2 - %stack (x: 2, x_: 2, y: 2, y_: 2) -> (y_, x_, y, x) - // stack: y_: 2, x_: 2, y: 2, x: 2 - %add_fp381 - // stack: z_: 2, y: 2, x: 2 - %stack (z_: 2, y: 2, x: 2) -> (x, y, z_) - // stack: x: 2, y: 2, z_: 2 - %add_fp381 - // stack: z: 2, z_: 2 -%endmacro +global mul_fp381_2: + // stack: a, b, c, d + DUP4 + DUP4 + // stack: b, a, b, c, d + DUP8 + DUP8 + // stack: c, b, a, b, c, d + DUP12 + DUP12 + // stack: d, c, b, a, b, c, d + DUP8 + DUP8 + // stack: a, d, c, b, a, b, c, d -%macro sub_fp381_2 - // stack: x: 2, x_: 2, y: 2, y_: 2 - %stack (x: 2, x_: 2, y: 2, y_: 2) -> (y_, x_, y, x) - // stack: y_: 2, x_: 2, y: 2, x: 2 + // stack: a, d, c, b, a, b, c, d + %mul_fp381 + // stack: ad, c, b, a, b, c, d + %stack (ad: 2, c: 2, b: 2) -> (b, c, ad) + // stack: b, c, ad, a, b, c, d + %mul_fp381 + // stack: bc, ad, a, b, c, d %add_fp381 + // stack: z_im, a, b, c, d + %stack (z_im: 2, a: 2, b: 2, c: 2, d: 2) -> (b, d, c, a, z_im) + // stack: b, d, c, a, z_im + %mul_fp381 + // stack: bd, c, a, z_im + %stack (bd: 2, c: 2, a: 2) -> (a, c, bd) + // stack: a, c, bd, z_im + %mul_fp381 + // stack: ac, bd, z_im + %sub_fp381 + // stack: z_re, z_im + %jump(0xdeadbeef) + +global sub_fp381_2: + // stack: x: 2, x_: 2, y: 2, y_: 2 + %stack (x: 2, x_: 2, y: 2, y_: 2) -> (x_, y_, y, x) + // stack: x_: 2, y_: 2, y: 2, x: 2 + %sub_fp381 // stack: z_: 2, y: 2, x: 2 %stack (z_: 2, y: 2, x: 2) -> (x, y, z_) // stack: x: 2, y: 2, z_: 2 - %add_fp381 + %sub_fp381 // stack: z: 2, z_: 2 -%endmacro \ No newline at end of file + %jump(0xdeadbeef) diff --git a/evm/src/cpu/kernel/tests/bls381.rs b/evm/src/cpu/kernel/tests/bls381.rs index b8315b6f..69904a4e 100644 --- a/evm/src/cpu/kernel/tests/bls381.rs +++ b/evm/src/cpu/kernel/tests/bls381.rs @@ -4,12 +4,12 @@ use rand::Rng; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, InterpreterMemoryInitialization, }; -use crate::extension_tower::{Stack, BLS381}; +use crate::extension_tower::{Fp2, Stack, BLS381}; use crate::memory::segments::Segment::KernelGeneral; fn run_and_return_bls(label: String, x: BLS381, y: BLS381) -> BLS381 { - let mut stack = x.on_stack(); - stack.extend(y.on_stack()); + let mut stack = x.to_stack(); + stack.extend(y.to_stack()); let setup = InterpreterMemoryInitialization { label, stack, @@ -18,7 +18,7 @@ fn run_and_return_bls(label: String, x: BLS381, y: BLS381) -> BLS381 { }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output = interpreter.stack(); - BLS381::from_limbs(output[0], output[1]) + BLS381::from_stack(output) } #[test] @@ -37,3 +37,34 @@ fn test_bls_ops() -> Result<()> { Ok(()) } + +fn run_and_return_bls_fp2(label: String, x: Fp2, y: Fp2) -> Fp2 { + let mut stack = x.to_stack(); + stack.extend(y.to_stack()); + let setup = InterpreterMemoryInitialization { + label, + stack, + segment: KernelGeneral, + memory: vec![], + }; + let interpreter = run_interpreter_with_memory(setup).unwrap(); + let output = interpreter.stack(); + Fp2::from_stack(output) +} + +#[test] +fn test_bls_fp2() -> Result<()> { + let mut rng = rand::thread_rng(); + let x: Fp2 = rng.gen::>(); + let y: Fp2 = rng.gen::>(); + + let output_add = run_and_return_bls_fp2("add_fp381_2".to_string(), x, y); + let output_mul = run_and_return_bls_fp2("mul_fp381_2".to_string(), x, y); + let output_sub = run_and_return_bls_fp2("sub_fp381_2".to_string(), x, y); + + assert_eq!(output_add, x + y); + assert_eq!(output_mul, x * y); + assert_eq!(output_sub, x - y); + + Ok(()) +} diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 8e71ffd6..6a5acea9 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -25,9 +25,9 @@ fn setup_mul_fp6_test( g: Fp6, label: &str, ) -> InterpreterMemoryInitialization { - let mut stack = f.on_stack(); + let mut stack = f.to_stack(); if label == "mul_fp254_6" { - stack.extend(g.on_stack()); + stack.extend(g.to_stack()); } stack.push(U256::from(0xdeadbeefu32)); InterpreterMemoryInitialization { @@ -53,8 +53,8 @@ fn test_mul_fp6() -> Result<()> { let out_normal: Vec = extract_stack(intrptr_normal); let out_square: Vec = extract_stack(intrptr_square); - let exp_normal: Vec = (f * g).on_stack(); - let exp_square: Vec = (f * f).on_stack(); + let exp_normal: Vec = (f * g).to_stack(); + let exp_square: Vec = (f * f).to_stack(); assert_eq!(out_normal, exp_normal); assert_eq!(out_square, exp_square); @@ -84,7 +84,7 @@ fn setup_mul_fp12_test( label: label.to_string(), stack, segment: BnPairing, - memory: vec![(in0, f.on_stack()), (in1, g.on_stack())], + memory: vec![(in0, f.to_stack()), (in1, g.to_stack())], } } @@ -112,9 +112,9 @@ fn test_mul_fp12() -> Result<()> { 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 exp_normal: Vec = (f * g).on_stack(); - let exp_sparse: Vec = (f * h).on_stack(); - let exp_square: Vec = (f * f).on_stack(); + let exp_normal: Vec = (f * g).to_stack(); + let exp_sparse: Vec = (f * h).to_stack(); + let exp_square: Vec = (f * f).to_stack(); assert_eq!(out_normal, exp_normal); assert_eq!(out_sparse, exp_sparse); @@ -126,7 +126,7 @@ fn test_mul_fp12() -> Result<()> { fn setup_frob_fp6_test(f: Fp6, n: usize) -> InterpreterMemoryInitialization { InterpreterMemoryInitialization { label: String::from("test_frob_fp254_6_") + &(n.to_string()), - stack: f.on_stack(), + stack: f.to_stack(), segment: BnPairing, memory: vec![], } @@ -140,7 +140,7 @@ fn test_frob_fp6() -> Result<()> { 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(); + let exp_frob: Vec = f.frob(n).to_stack(); assert_eq!(out_frob, exp_frob); } Ok(()) @@ -151,7 +151,7 @@ fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemo label: String::from("test_frob_fp254_12_") + &(n.to_string()), stack: vec![U256::from(ptr)], segment: BnPairing, - memory: vec![(ptr, f.on_stack())], + memory: vec![(ptr, f.to_stack())], } } @@ -164,7 +164,7 @@ fn test_frob_fp12() -> Result<()> { 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(); + let exp_frob: Vec = f.frob(n).to_stack(); assert_eq!(out_frob, exp_frob); } Ok(()) @@ -181,11 +181,11 @@ fn test_inv_fp12() -> Result<()> { label: "inv_fp254_12".to_string(), stack: vec![U256::from(ptr), U256::from(inv), U256::from(0xdeadbeefu32)], segment: BnPairing, - memory: vec![(ptr, f.on_stack())], + memory: vec![(ptr, f.to_stack())], }; let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12); - let expected: Vec = f.inv().on_stack(); + let expected: Vec = f.inv().to_stack(); assert_eq!(output, expected); @@ -202,12 +202,12 @@ fn test_invariant_exponent() -> Result<()> { label: "bn254_invariant_exponent".to_string(), stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], segment: BnPairing, - memory: vec![(ptr, f.on_stack())], + memory: vec![(ptr, f.to_stack())], }; 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 = invariant_exponent(f).to_stack(); assert_eq!(output, expected); @@ -287,7 +287,7 @@ fn test_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, TWISTED_GENERATOR).to_stack(); assert_eq!(output, expected); @@ -315,7 +315,7 @@ fn test_tate() -> Result<()> { }; 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(); + let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).to_stack(); assert_eq!(output, expected); diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index 72a1106c..dc5df22d 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -144,13 +144,6 @@ impl BLS381 { pub fn hi(self) -> U256 { U256(self.val.0[4..].try_into().unwrap()) } - - pub fn from_limbs(hi: U256, lo: U256) -> BLS381 { - let mut val = [0u64; 8]; - val[..4].copy_from_slice(&lo.0); - val[4..].copy_from_slice(&hi.0); - BLS381 { val: U512(val) } - } } impl Distribution for Standard { @@ -1208,25 +1201,60 @@ where } pub trait Stack { - fn on_stack(self) -> Vec; + fn to_stack(self) -> Vec; + + fn from_stack(stack: &[U256]) -> Self; } impl Stack for BLS381 { - fn on_stack(self) -> Vec { + fn to_stack(self) -> Vec { vec![self.lo(), self.hi()] } + + fn from_stack(stack: &[U256]) -> BLS381 { + let mut val = [0u64; 8]; + val[..4].copy_from_slice(&stack[1].0); + val[4..].copy_from_slice(&stack[0].0); + BLS381 { val: U512(val) } + } +} + +impl Stack for Fp2 { + fn to_stack(self) -> Vec { + let mut res = self.re.to_stack(); + res.extend(self.im.to_stack()); + res + } + + fn from_stack(stack: &[U256]) -> Fp2 { + let re = BLS381::from_stack(&stack[2..4]); + let im = BLS381::from_stack(&stack[0..2]); + Fp2 { re, im } + } } impl Stack for Fp6 { - fn on_stack(self) -> Vec { + fn to_stack(self) -> Vec { let f: [U256; 6] = unsafe { transmute(self) }; f.into_iter().collect() } + + fn from_stack(stack: &[U256]) -> Self { + let mut f = [U256::zero(); 6]; + f.copy_from_slice(stack); + unsafe { transmute(f) } + } } impl Stack for Fp12 { - fn on_stack(self) -> Vec { + fn to_stack(self) -> Vec { let f: [U256; 12] = unsafe { transmute(self) }; f.into_iter().collect() } + + fn from_stack(stack: &[U256]) -> Self { + let mut f = [U256::zero(); 12]; + f.copy_from_slice(stack); + unsafe { transmute(f) } + } }