203 lines
5.2 KiB
Rust
Raw Normal View History

2022-10-12 10:06:34 -04:00
use anyhow::Result;
use ethereum_types::U256;
2022-10-17 23:19:14 -04:00
use rand::{thread_rng, Rng};
2022-10-12 10:06:34 -04:00
2022-11-04 13:55:13 +01:00
use crate::cpu::kernel::aggregator::KERNEL;
use crate::cpu::kernel::interpreter::run_interpreter;
2022-10-12 10:06:34 -04:00
2022-10-28 02:08:56 -07:00
// TODO: 107 is hardcoded as a dummy prime for testing
// should be changed to the proper implementation prime
// once the run_{add, mul, sub}fp254 fns are implemented
2022-10-18 11:07:43 -04:00
const P254: u32 = 107;
2022-10-17 23:19:14 -04:00
2022-10-18 10:34:41 -04:00
fn add_fp(x: u32, y: u32) -> u32 {
(x + y) % P254
}
fn add3_fp(x: u32, y: u32, z: u32) -> u32 {
(x + y + z) % P254
}
fn mul_fp(x: u32, y: u32) -> u32 {
(x * y) % P254
}
fn sub_fp(x: u32, y: u32) -> u32 {
(P254 + x - y) % P254
}
2022-10-17 23:19:14 -04:00
fn add_fp2(a: [u32; 2], b: [u32; 2]) -> [u32; 2] {
let [a, a_] = a;
let [b, b_] = b;
2022-10-18 10:34:41 -04:00
[add_fp(a, b), add_fp(a_, b_)]
2022-10-17 23:19:14 -04:00
}
fn add3_fp2(a: [u32; 2], b: [u32; 2], c: [u32; 2]) -> [u32; 2] {
let [a, a_] = a;
let [b, b_] = b;
let [c, c_] = c;
2022-10-18 10:34:41 -04:00
[add3_fp(a, b, c), add3_fp(a_, b_, c_)]
2022-10-17 23:19:14 -04:00
}
2022-10-28 02:23:42 -07:00
// fn sub_fp2(a: [u32; 2], b: [u32; 2]) -> [u32; 2] {
// let [a, a_] = a;
// let [b, b_] = b;
// [sub_fp(a, b), sub_fp(a_, b_)]
// }
2022-10-17 23:19:14 -04:00
fn mul_fp2(a: [u32; 2], b: [u32; 2]) -> [u32; 2] {
let [a, a_] = a;
let [b, b_] = b;
[
2022-10-18 10:34:41 -04:00
sub_fp(mul_fp(a, b), mul_fp(a_, b_)),
add_fp(mul_fp(a, b_), mul_fp(a_, b)),
2022-10-17 23:19:14 -04:00
]
}
fn i9(a: [u32; 2]) -> [u32; 2] {
let [a, a_] = a;
2022-10-18 10:34:41 -04:00
[sub_fp(mul_fp(9, a), a_), add_fp(a, mul_fp(9, a_))]
2022-10-17 23:19:14 -04:00
}
2022-10-28 02:23:42 -07:00
// fn add_fp6(c: [[u32; 2]; 3], d: [[u32; 2]; 3]) -> [[u32; 2]; 3] {
// let [c0, c1, c2] = c;
// let [d0, d1, d2] = d;
2022-10-17 23:19:14 -04:00
2022-10-28 02:23:42 -07:00
// let e0 = add_fp2(c0, d0);
// let e1 = add_fp2(c1, d1);
// let e2 = add_fp2(c2, d2);
// [e0, e1, e2]
// }
2022-10-17 23:19:14 -04:00
2022-10-28 02:23:42 -07:00
// fn sub_fp6(c: [[u32; 2]; 3], d: [[u32; 2]; 3]) -> [[u32; 2]; 3] {
// let [c0, c1, c2] = c;
// let [d0, d1, d2] = d;
2022-10-17 23:19:14 -04:00
2022-10-28 02:23:42 -07:00
// let e0 = sub_fp2(c0, d0);
// let e1 = sub_fp2(c1, d1);
// let e2 = sub_fp2(c2, d2);
// [e0, e1, e2]
// }
2022-10-17 23:19:14 -04:00
fn mul_fp6(c: [[u32; 2]; 3], d: [[u32; 2]; 3]) -> [[u32; 2]; 3] {
let [c0, c1, c2] = c;
let [d0, d1, d2] = d;
let c0d0 = mul_fp2(c0, d0);
let c0d1 = mul_fp2(c0, d1);
let c0d2 = mul_fp2(c0, d2);
let c1d0 = mul_fp2(c1, d0);
let c1d1 = mul_fp2(c1, d1);
let c1d2 = mul_fp2(c1, d2);
let c2d0 = mul_fp2(c2, d0);
let c2d1 = mul_fp2(c2, d1);
let c2d2 = mul_fp2(c2, d2);
let cd12 = add_fp2(c1d2, c2d1);
[
add_fp2(c0d0, i9(cd12)),
add3_fp2(c0d1, c1d0, i9(c2d2)),
add3_fp2(c0d2, c1d1, c2d0),
]
}
2022-10-28 02:23:42 -07:00
// fn sh(c: [[u32; 2]; 3]) -> [[u32; 2]; 3] {
// let [c0, c1, c2] = c;
// [i9(c2), c0, c1]
// }
2022-10-17 23:19:14 -04:00
2022-10-28 02:23:42 -07:00
// fn mul_fp12(f: [[[u32; 2]; 3]; 2], g: [[[u32; 2]; 3]; 2]) -> [[[u32; 2]; 3]; 2] {
// let [f0, f1] = f;
// let [g0, g1] = g;
2022-10-17 23:19:14 -04:00
2022-10-28 02:23:42 -07:00
// let h0 = mul_fp6(f0, g0);
// let h1 = mul_fp6(f1, g1);
// let h01 = mul_fp6(add_fp6(f0, f1), add_fp6(g0, g1));
// [add_fp6(h0, sh(h1)), sub_fp6(h01, add_fp6(h0, h1))]
// }
2022-10-17 23:19:14 -04:00
fn gen_fp6() -> [[u32; 2]; 3] {
let mut rng = thread_rng();
[
[rng.gen_range(0..P254), rng.gen_range(0..P254)],
[rng.gen_range(0..P254), rng.gen_range(0..P254)],
[rng.gen_range(0..P254), rng.gen_range(0..P254)],
]
}
2022-10-18 00:22:51 -04:00
fn as_stack(xs: Vec<u32>) -> Vec<U256> {
2022-10-22 13:16:07 -04:00
xs.iter().map(|&x| U256::from(x)).rev().collect()
2022-10-17 14:57:32 -04:00
}
2022-10-18 00:07:57 -04:00
#[test]
2022-10-22 13:16:07 -04:00
fn test_fp6() -> Result<()> {
let c = gen_fp6();
let d = gen_fp6();
2022-10-22 16:19:23 -04:00
2022-10-22 13:16:07 -04:00
let mut input: Vec<u32> = [c, d].into_iter().flatten().flatten().collect();
input.push(0xdeadbeef);
2022-10-18 00:07:57 -04:00
2022-11-04 13:55:13 +01:00
let initial_offset = KERNEL.global_labels["mul_fp6"];
2022-10-18 00:07:57 -04:00
let initial_stack: Vec<U256> = as_stack(input);
2022-11-04 13:55:13 +01:00
let final_stack: Vec<U256> = run_interpreter(initial_offset, initial_stack)?
2022-10-18 00:07:57 -04:00
.stack()
.to_vec();
2022-10-22 13:16:07 -04:00
let output: Vec<u32> = mul_fp6(c, d).into_iter().flatten().collect();
2022-10-18 00:07:57 -04:00
let expected = as_stack(output);
2022-10-22 16:19:23 -04:00
2022-10-18 00:07:57 -04:00
assert_eq!(final_stack, expected);
Ok(())
}
2022-10-22 13:16:07 -04:00
2022-10-28 02:03:52 -07:00
// fn make_initial_stack(
// f0: [[u32; 2]; 3],
// f1: [[u32; 2]; 3],
// g0: [[u32; 2]; 3],
// g1: [[u32; 2]; 3],
// ) -> Vec<U256> {
// // stack: in0, f, in0', f', in1, g, in1', g', in1, out, in0, out
// let f0: Vec<u32> = f0.into_iter().flatten().collect();
// let f1: Vec<u32> = f1.into_iter().flatten().collect();
// let g0: Vec<u32> = g0.into_iter().flatten().collect();
// let g1: Vec<u32> = g1.into_iter().flatten().collect();
// let mut input = f0;
// input.extend(vec![0]);
// input.extend(f1);
// input.extend(g0);
// input.extend(vec![12]);
// input.extend(g1);
// input.extend(vec![12, 24, 0, 24]);
// as_stack(input)
// }
// #[test]
// fn test_fp12() -> Result<()> {
// let f0 = gen_fp6();
// let f1 = gen_fp6();
// let g0 = gen_fp6();
// let g1 = gen_fp6();
// let kernel = combined_kernel();
// let initial_offset = kernel.global_labels["test_mul_Fp12"];
// let initial_stack: Vec<U256> = make_initial_stack(f0, f1, g0, g1);
// let final_stack: Vec<U256> = run_with_kernel(&kernel, initial_offset, initial_stack)?
// .stack()
// .to_vec();
// let mut output: Vec<u32> = mul_fp12([f0, f1], [g0, g1])
// .into_iter()
// .flatten()
// .flatten()
// .collect();
// output.extend(vec![24]);
// let expected = as_stack(output);
// assert_eq!(final_stack, expected);
// Ok(())
// }