2022-12-15 14:08:23 -08:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
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;
|
2022-12-14 19:14:14 -08:00
|
|
|
use crate::cpu::kernel::interpreter::{run_interpreter, BN_BASE};
|
2022-10-12 10:06:34 -04:00
|
|
|
|
2022-12-16 17:35:52 -08:00
|
|
|
type Fp = U256;
|
2022-12-15 14:08:23 -08:00
|
|
|
type Fp2 = [U256; 2];
|
|
|
|
|
type Fp6 = [Fp2; 3];
|
|
|
|
|
type Fp12 = [Fp6; 2];
|
|
|
|
|
|
2022-12-19 14:39:23 -08:00
|
|
|
const ZERO: Fp = U256([0, 0, 0, 0]);
|
2022-12-16 17:35:52 -08:00
|
|
|
|
|
|
|
|
fn embed_fp2(x: Fp) -> Fp2 {
|
2022-12-19 14:39:23 -08:00
|
|
|
[x, ZERO]
|
2022-12-16 17:35:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn embed_fp2_fp6(a: Fp2) -> Fp6 {
|
2022-12-19 14:39:23 -08:00
|
|
|
[a, embed_fp2(ZERO), embed_fp2(ZERO)]
|
2022-12-16 17:35:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn embed_fp6(x: Fp) -> Fp6 {
|
|
|
|
|
embed_fp2_fp6(embed_fp2(x))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn embed_fp12(x: Fp) -> Fp12 {
|
2022-12-19 14:39:23 -08:00
|
|
|
[embed_fp6(x), embed_fp6(ZERO)]
|
2022-12-16 17:35:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gen_fp() -> Fp {
|
2022-12-19 14:39:23 -08:00
|
|
|
let mut rng = thread_rng();
|
2022-12-16 17:35:52 -08:00
|
|
|
let x64 = rng.gen::<u64>();
|
|
|
|
|
U256([x64, x64, x64, x64]) % BN_BASE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gen_fp6() -> Fp6 {
|
|
|
|
|
[
|
|
|
|
|
[gen_fp(), gen_fp()],
|
|
|
|
|
[gen_fp(), gen_fp()],
|
|
|
|
|
[gen_fp(), gen_fp()],
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gen_fp12() -> Fp12 {
|
|
|
|
|
[gen_fp6(), gen_fp6()]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn gen_fp12_sparse() -> Fp12 {
|
2022-12-20 21:53:52 -08:00
|
|
|
sparse_embed(gen_fp(), [gen_fp(), gen_fp()], [gen_fp(), gen_fp()])
|
2022-12-16 17:35:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn add_fp(x: Fp, y: Fp) -> Fp {
|
2022-12-14 19:14:14 -08:00
|
|
|
(x + y) % BN_BASE
|
2022-10-18 10:34:41 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 17:35:52 -08:00
|
|
|
fn add3_fp(x: Fp, y: Fp, z: Fp) -> Fp {
|
2022-12-14 19:14:14 -08:00
|
|
|
(x + y + z) % BN_BASE
|
2022-10-18 10:34:41 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 17:35:52 -08:00
|
|
|
fn mul_fp(x: Fp, y: Fp) -> Fp {
|
2022-12-14 19:14:14 -08:00
|
|
|
U256::try_from(x.full_mul(y) % BN_BASE).unwrap()
|
2022-10-18 10:34:41 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 17:35:52 -08:00
|
|
|
fn sub_fp(x: Fp, y: Fp) -> Fp {
|
2022-12-14 19:14:14 -08:00
|
|
|
(BN_BASE + x - y) % BN_BASE
|
2022-10-18 10:34:41 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 17:35:52 -08:00
|
|
|
fn neg_fp(x: Fp) -> Fp {
|
2022-12-15 13:18:00 -08:00
|
|
|
(BN_BASE - x) % BN_BASE
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn conj_fp2(a: Fp2) -> Fp2 {
|
2022-12-15 13:18:00 -08:00
|
|
|
let [a, a_] = a;
|
|
|
|
|
[a, neg_fp(a_)]
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn add_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
2022-10-17 23:19:14 -04:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn add3_fp2(a: Fp2, b: Fp2, c: Fp2) -> Fp2 {
|
2022-10-17 23:19:14 -04:00
|
|
|
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-12-15 14:08:23 -08:00
|
|
|
fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
2022-11-14 15:58:37 -08:00
|
|
|
let [a, a_] = a;
|
|
|
|
|
let [b, b_] = b;
|
|
|
|
|
[sub_fp(a, b), sub_fp(a_, b_)]
|
|
|
|
|
}
|
2022-10-17 23:19:14 -04:00
|
|
|
|
2022-12-20 00:22:59 -08:00
|
|
|
fn neg_fp2(a: Fp2) -> Fp2 {
|
|
|
|
|
sub_fp2(embed_fp2(ZERO), a)
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
2022-10-17 23:19:14 -04:00
|
|
|
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
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn i9(a: Fp2) -> Fp2 {
|
2022-10-17 23:19:14 -04:00
|
|
|
let [a, a_] = a;
|
2022-12-15 13:18:00 -08:00
|
|
|
let nine = U256::from(9);
|
|
|
|
|
[sub_fp(mul_fp(nine, a), a_), add_fp(a, mul_fp(nine, a_))]
|
2022-10-17 23:19:14 -04:00
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn add_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
2022-11-14 15:58:37 -08:00
|
|
|
let [c0, c1, c2] = c;
|
|
|
|
|
let [d0, d1, d2] = d;
|
2022-10-17 23:19:14 -04:00
|
|
|
|
2022-11-14 15:58:37 -08: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-12-15 14:08:23 -08:00
|
|
|
fn sub_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
2022-11-14 15:58:37 -08:00
|
|
|
let [c0, c1, c2] = c;
|
|
|
|
|
let [d0, d1, d2] = d;
|
2022-10-17 23:19:14 -04:00
|
|
|
|
2022-11-14 15:58:37 -08: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
|
|
|
|
2022-12-20 00:22:59 -08:00
|
|
|
fn neg_fp6(a: Fp6) -> Fp6 {
|
|
|
|
|
sub_fp6(embed_fp6(ZERO), a)
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn mul_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
2022-10-17 23:19:14 -04:00
|
|
|
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-12-15 14:08:23 -08:00
|
|
|
fn sh(c: Fp6) -> Fp6 {
|
2022-11-14 15:58:37 -08:00
|
|
|
let [c0, c1, c2] = c;
|
|
|
|
|
[i9(c2), c0, c1]
|
|
|
|
|
}
|
2022-10-17 23:19:14 -04:00
|
|
|
|
2022-12-20 21:53:52 -08:00
|
|
|
fn sparse_embed(g0: Fp, g1: Fp2, g2: Fp2) -> Fp12 {
|
2022-12-15 13:18:00 -08:00
|
|
|
[
|
2022-12-20 21:53:52 -08:00
|
|
|
[embed_fp2(g0), g1, embed_fp2(ZERO)],
|
|
|
|
|
[embed_fp2(ZERO), g2, embed_fp2(ZERO)],
|
2022-12-15 13:18:00 -08:00
|
|
|
]
|
2022-11-14 16:41:36 -08:00
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn mul_fp12(f: Fp12, g: Fp12) -> Fp12 {
|
2022-11-14 15:58:37 -08:00
|
|
|
let [f0, f1] = f;
|
|
|
|
|
let [g0, g1] = g;
|
2022-10-17 23:19:14 -04:00
|
|
|
|
2022-11-14 15:58:37 -08: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
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn frob_t1(n: usize) -> Fp2 {
|
|
|
|
|
match n {
|
|
|
|
|
0 => [
|
|
|
|
|
U256::from_str("0x1").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
1 => [
|
|
|
|
|
U256::from_str("0x2fb347984f7911f74c0bec3cf559b143b78cc310c2c3330c99e39557176f553d")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x16c9e55061ebae204ba4cc8bd75a079432ae2a1d0b7c9dce1665d51c640fcba2")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
2 => [
|
|
|
|
|
U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
3 => [
|
|
|
|
|
U256::from_str("0x856e078b755ef0abaff1c77959f25ac805ffd3d5d6942d37b746ee87bdcfb6d")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x4f1de41b3d1766fa9f30e6dec26094f0fdf31bf98ff2631380cab2baaa586de")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
4 => [
|
|
|
|
|
U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
5 => [
|
|
|
|
|
U256::from_str("0x28be74d4bb943f51699582b87809d9caf71614d4b0b71f3a62e913ee1dada9e4")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x14a88ae0cb747b99c2b86abcbe01477a54f40eb4c3f6068dedae0bcec9c7aac7")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
_ => panic!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn frob_t2(n: usize) -> Fp2 {
|
|
|
|
|
match n {
|
|
|
|
|
0 => [
|
|
|
|
|
U256::from_str("0x1").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
1 => [
|
|
|
|
|
U256::from_str("0x5b54f5e64eea80180f3c0b75a181e84d33365f7be94ec72848a1f55921ea762")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x2c145edbe7fd8aee9f3a80b03b0b1c923685d2ea1bdec763c13b4711cd2b8126")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
2 => [
|
|
|
|
|
U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
3 => [
|
|
|
|
|
U256::from_str("0xbc58c6611c08dab19bee0f7b5b2444ee633094575b06bcb0e1a92bc3ccbf066")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x23d5e999e1910a12feb0f6ef0cd21d04a44a9e08737f96e55fe3ed9d730c239f")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
4 => [
|
|
|
|
|
U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
5 => [
|
|
|
|
|
U256::from_str("0x1ee972ae6a826a7d1d9da40771b6f589de1afb54342c724fa97bda050992657f")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x10de546ff8d4ab51d2b513cdbb25772454326430418536d15721e37e70c255c9")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
_ => panic!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn frob_z(n: usize) -> Fp2 {
|
|
|
|
|
match n {
|
|
|
|
|
0 => [
|
|
|
|
|
U256::from_str("0x1").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
1 => [
|
|
|
|
|
U256::from_str("0x1284b71c2865a7dfe8b99fdd76e68b605c521e08292f2176d60b35dadcc9e470")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x246996f3b4fae7e6a6327cfe12150b8e747992778eeec7e5ca5cf05f80f362ac")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
2 => [
|
|
|
|
|
U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd49")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
3 => [
|
|
|
|
|
U256::from_str("0x19dc81cfcc82e4bbefe9608cd0acaa90894cb38dbe55d24ae86f7d391ed4a67f")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0xabf8b60be77d7306cbeee33576139d7f03a5e397d439ec7694aa2bf4c0c101")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
4 => [
|
|
|
|
|
U256::from_str("0x30644e72e131a0295e6dd9e7e0acccb0c28f069fbb966e3de4bd44e5607cfd48")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
5 => [
|
|
|
|
|
U256::from_str("0x757cab3a41d3cdc072fc0af59c61f302cfa95859526b0d41264475e420ac20f")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0xca6b035381e35b618e9b79ba4e2606ca20b7dfd71573c93e85845e34c4a5b9c")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
6 => [
|
|
|
|
|
U256::from_str("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
7 => [
|
|
|
|
|
U256::from_str("0x1ddf9756b8cbf849cf96a5d90a9accfd3b2f4c893f42a9166615563bfbb318d7")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0xbfab77f2c36b843121dc8b86f6c4ccf2307d819d98302a771c39bb757899a9b")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
8 => [
|
|
|
|
|
U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
9 => [
|
|
|
|
|
U256::from_str("0x1687cca314aebb6dc866e529b0d4adcd0e34b703aa1bf84253b10eddb9a856c8")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x2fb855bcd54a22b6b18456d34c0b44c0187dc4add09d90a0c58be1eae3bc3c46")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
10 => [
|
|
|
|
|
U256::from_str("0x59e26bcea0d48bacd4f263f1acdb5c4f5763473177ffffff").unwrap(),
|
|
|
|
|
U256::from_str("0x0").unwrap(),
|
|
|
|
|
],
|
|
|
|
|
11 => [
|
|
|
|
|
U256::from_str("0x290c83bf3d14634db120850727bb392d6a86d50bd34b19b929bc44b896723b38")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x23bd9e3da9136a739f668e1adc9ef7f0f575ec93f71a8df953c846338c32a1ab")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
],
|
|
|
|
|
_ => panic!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn frob_fp6(n: usize, c: Fp6) -> Fp6 {
|
|
|
|
|
let [c0, c1, c2] = c;
|
|
|
|
|
let _c0 = conj_fp2(c0);
|
|
|
|
|
let _c1 = conj_fp2(c1);
|
|
|
|
|
let _c2 = conj_fp2(c2);
|
|
|
|
|
|
2022-12-15 17:00:38 -08:00
|
|
|
let n = n % 6;
|
|
|
|
|
let frob_t1 = frob_t1(n);
|
|
|
|
|
let frob_t2 = frob_t2(n);
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
if n % 2 != 0 {
|
2022-12-15 17:00:38 -08:00
|
|
|
[_c0, mul_fp2(frob_t1, _c1), mul_fp2(frob_t2, _c2)]
|
2022-12-15 14:08:23 -08:00
|
|
|
} else {
|
2022-12-15 17:00:38 -08:00
|
|
|
[c0, mul_fp2(frob_t1, c1), mul_fp2(frob_t2, c2)]
|
2022-12-15 14:08:23 -08:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-15 17:00:38 -08:00
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn frob_fp12(n: usize, f: Fp12) -> Fp12 {
|
|
|
|
|
let [f0, f1] = f;
|
2022-12-16 17:35:52 -08:00
|
|
|
let scale = embed_fp2_fp6(frob_z(n));
|
2022-12-15 17:00:38 -08:00
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
[frob_fp6(n, f0), mul_fp6(scale, frob_fp6(n, f1))]
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-20 00:22:59 -08:00
|
|
|
fn exp_fp(x: Fp, e: U256) -> Fp {
|
|
|
|
|
let mut current = x;
|
|
|
|
|
let mut product = U256::one();
|
|
|
|
|
|
|
|
|
|
for j in 0..256 {
|
|
|
|
|
if e.bit(j) {
|
|
|
|
|
product = U256::try_from(product.full_mul(current) % BN_BASE).unwrap();
|
|
|
|
|
}
|
|
|
|
|
current = U256::try_from(current.full_mul(current) % BN_BASE).unwrap();
|
|
|
|
|
}
|
|
|
|
|
product
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn inv_fp(x: Fp) -> Fp {
|
|
|
|
|
exp_fp(x, BN_BASE - 2)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn inv_fp2(a: Fp2) -> Fp2 {
|
|
|
|
|
let [a0, a1] = a;
|
|
|
|
|
let norm = inv_fp(mul_fp(a0, a0) + mul_fp(a1, a1));
|
|
|
|
|
[mul_fp(norm, a0), neg_fp(mul_fp(norm, a1))]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn inv_fp6(c: Fp6) -> Fp6 {
|
|
|
|
|
let b = mul_fp6(frob_fp6(1, c), frob_fp6(3, c));
|
|
|
|
|
let e = mul_fp6(b, frob_fp6(5, c))[0];
|
|
|
|
|
let n = mul_fp2(e, conj_fp2(e))[0];
|
|
|
|
|
let i = inv_fp(n);
|
|
|
|
|
let d = mul_fp2(embed_fp2(i), e);
|
|
|
|
|
let [f0, f1, f2] = frob_fp6(1, b);
|
|
|
|
|
[mul_fp2(d, f0), mul_fp2(d, f1), mul_fp2(d, f2)]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn inv_fp12(f: Fp12) -> Fp12 {
|
2022-12-20 11:57:45 -08:00
|
|
|
let [f0, f1] = f;
|
2022-12-20 00:22:59 -08:00
|
|
|
let a = mul_fp12(frob_fp12(1, f), frob_fp12(7, f))[0];
|
|
|
|
|
let b = mul_fp6(a, frob_fp6(2, a));
|
|
|
|
|
let c = mul_fp6(b, frob_fp6(4, a))[0];
|
|
|
|
|
let n = mul_fp2(c, conj_fp2(c))[0];
|
|
|
|
|
let i = inv_fp(n);
|
|
|
|
|
let d = mul_fp2(embed_fp2(i), c);
|
|
|
|
|
let [g0, g1, g2] = frob_fp6(1, b);
|
|
|
|
|
let e = [mul_fp2(d, g0), mul_fp2(d, g1), mul_fp2(d, g2)];
|
2022-12-20 11:57:45 -08:00
|
|
|
[mul_fp6(e, f0), neg_fp6(mul_fp6(e, f1))]
|
2022-12-20 00:22:59 -08:00
|
|
|
}
|
|
|
|
|
|
2022-12-16 17:35:52 -08:00
|
|
|
const EXPS4: [(bool, bool, bool); 65] = [
|
2022-12-16 17:46:50 -08:00
|
|
|
(true, true, true),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, true),
|
|
|
|
|
(true, true, true),
|
|
|
|
|
(false, false, false),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, false, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, false, false),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(false, false, false),
|
|
|
|
|
(true, false, false),
|
|
|
|
|
(true, false, false),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(false, false, false),
|
|
|
|
|
(true, true, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, false, false),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(true, false, false),
|
|
|
|
|
(false, false, true),
|
|
|
|
|
(true, false, true),
|
|
|
|
|
(true, true, false),
|
|
|
|
|
(true, true, true),
|
|
|
|
|
(false, true, true),
|
|
|
|
|
(false, true, false),
|
|
|
|
|
(true, true, true),
|
2022-12-16 17:35:52 -08:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const EXPS2: [(bool, bool); 62] = [
|
2022-12-16 17:46:50 -08:00
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(false, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(false, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(false, false),
|
|
|
|
|
(false, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(false, false),
|
|
|
|
|
(true, false),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(true, false),
|
|
|
|
|
(true, true),
|
|
|
|
|
(false, true),
|
|
|
|
|
(true, true),
|
2022-12-16 17:35:52 -08:00
|
|
|
];
|
|
|
|
|
|
2022-12-16 17:46:50 -08:00
|
|
|
const 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,
|
|
|
|
|
true, true, true, false, true, false, true, true, false, false, true, false, false, false,
|
|
|
|
|
true, true, true, true, false, false, true, true, false,
|
2022-12-16 17:35:52 -08:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
fn fast_exp(f: Fp12) -> Fp12 {
|
|
|
|
|
let mut sq: Fp12 = f;
|
2022-12-20 15:37:41 -08:00
|
|
|
let mut y0: Fp12 = embed_fp12(U256::one());
|
|
|
|
|
let mut y2: Fp12 = embed_fp12(U256::one());
|
|
|
|
|
let mut y4: Fp12 = embed_fp12(U256::one());
|
2022-12-16 17:35:52 -08:00
|
|
|
|
|
|
|
|
for (a, b, c) in EXPS4 {
|
|
|
|
|
if a {
|
|
|
|
|
y4 = mul_fp12(y4, sq);
|
|
|
|
|
}
|
|
|
|
|
if b {
|
|
|
|
|
y2 = mul_fp12(y2, sq);
|
|
|
|
|
}
|
|
|
|
|
if c {
|
|
|
|
|
y0 = mul_fp12(y0, sq);
|
|
|
|
|
}
|
|
|
|
|
sq = mul_fp12(sq, sq);
|
|
|
|
|
}
|
2022-12-20 15:37:41 -08:00
|
|
|
y4 = mul_fp12(y4, sq);
|
2022-12-16 17:35:52 -08:00
|
|
|
|
|
|
|
|
for (a, b) in EXPS2 {
|
|
|
|
|
if a {
|
|
|
|
|
y2 = mul_fp12(y2, sq);
|
|
|
|
|
}
|
|
|
|
|
if b {
|
|
|
|
|
y0 = mul_fp12(y0, sq);
|
|
|
|
|
}
|
|
|
|
|
sq = mul_fp12(sq, sq);
|
|
|
|
|
}
|
2022-12-20 15:37:41 -08:00
|
|
|
y2 = mul_fp12(y2, sq);
|
2022-12-16 17:35:52 -08:00
|
|
|
|
|
|
|
|
for a in EXPS0 {
|
|
|
|
|
if a {
|
|
|
|
|
y0 = mul_fp12(y0, sq);
|
|
|
|
|
}
|
|
|
|
|
sq = mul_fp12(sq, sq);
|
|
|
|
|
}
|
2022-12-20 15:37:41 -08:00
|
|
|
y0 = mul_fp12(y0, sq);
|
2022-12-20 17:23:05 -08:00
|
|
|
|
2022-12-20 11:57:45 -08:00
|
|
|
y0 = inv_fp12(y0);
|
2022-12-16 17:35:52 -08:00
|
|
|
|
|
|
|
|
y4 = mul_fp12(y4, y2);
|
|
|
|
|
y4 = mul_fp12(y4, y2);
|
|
|
|
|
y4 = mul_fp12(y4, y0);
|
|
|
|
|
|
|
|
|
|
y4 = frob_fp12(1, y4);
|
|
|
|
|
y2 = frob_fp12(2, y2);
|
|
|
|
|
|
|
|
|
|
mul_fp12(mul_fp12(y4, y2), y0)
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 13:20:16 -08:00
|
|
|
fn make_mul_stack(
|
2022-12-15 13:18:00 -08:00
|
|
|
in0: usize,
|
2022-12-14 19:14:14 -08:00
|
|
|
in1: usize,
|
|
|
|
|
out: usize,
|
2022-12-15 17:00:38 -08:00
|
|
|
f: Fp12,
|
|
|
|
|
g: Fp12,
|
2022-12-15 13:18:00 -08:00
|
|
|
mul_label: &str,
|
2022-11-14 15:58:37 -08:00
|
|
|
) -> Vec<U256> {
|
2022-12-15 13:18:00 -08:00
|
|
|
let in0 = U256::from(in0);
|
2022-12-14 19:14:14 -08:00
|
|
|
let in1 = U256::from(in1);
|
|
|
|
|
let out = U256::from(out);
|
|
|
|
|
|
2022-12-15 17:00:38 -08:00
|
|
|
let f: Vec<U256> = f.into_iter().flatten().flatten().collect();
|
|
|
|
|
let g: Vec<U256> = g.into_iter().flatten().flatten().collect();
|
2022-11-14 15:58:37 -08:00
|
|
|
|
2022-12-15 13:18:00 -08:00
|
|
|
let ret_stack = U256::from(KERNEL.global_labels["ret_stack"]);
|
|
|
|
|
let mul_dest = U256::from(KERNEL.global_labels[mul_label]);
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
let mut input = vec![in0];
|
2022-12-15 17:00:38 -08:00
|
|
|
input.extend(f);
|
2022-12-15 13:18:00 -08:00
|
|
|
input.extend(vec![in1]);
|
2022-12-15 17:00:38 -08:00
|
|
|
input.extend(g);
|
2022-12-15 13:18:00 -08:00
|
|
|
input.extend(vec![mul_dest, in0, in1, out, ret_stack, out]);
|
2022-12-14 19:31:21 -08:00
|
|
|
input.reverse();
|
|
|
|
|
input
|
2022-11-14 15:58:37 -08:00
|
|
|
}
|
|
|
|
|
|
2022-12-15 14:08:23 -08:00
|
|
|
fn make_mul_expected(f: Fp12, g: Fp12) -> Vec<U256> {
|
2022-12-15 13:18:00 -08:00
|
|
|
mul_fp12(f, g)
|
2022-11-14 15:58:37 -08:00
|
|
|
.into_iter()
|
|
|
|
|
.flatten()
|
|
|
|
|
.flatten()
|
2022-12-14 19:14:14 -08:00
|
|
|
.rev()
|
2022-12-15 13:18:00 -08:00
|
|
|
.collect()
|
2022-11-14 15:58:37 -08:00
|
|
|
}
|
2022-11-14 16:41:36 -08:00
|
|
|
|
2022-12-14 20:16:50 -08:00
|
|
|
#[test]
|
2022-12-15 13:18:00 -08:00
|
|
|
fn test_mul_fp12() -> Result<()> {
|
|
|
|
|
let in0 = 64;
|
|
|
|
|
let in1 = 76;
|
2022-11-14 16:41:36 -08:00
|
|
|
let out = 88;
|
|
|
|
|
|
2022-12-15 17:00:38 -08:00
|
|
|
let f: Fp12 = gen_fp12();
|
|
|
|
|
let g: Fp12 = gen_fp12();
|
|
|
|
|
let h: Fp12 = gen_fp12_sparse();
|
2022-11-15 13:34:47 -08:00
|
|
|
|
2022-12-15 13:18:00 -08:00
|
|
|
let test_mul = KERNEL.global_labels["test_mul_fp12"];
|
2022-11-15 13:34:47 -08:00
|
|
|
|
2022-12-15 17:00:38 -08:00
|
|
|
let normal: Vec<U256> = make_mul_stack(in0, in1, out, f, g, "mul_fp12");
|
|
|
|
|
let sparse: Vec<U256> = make_mul_stack(in0, in1, out, f, h, "mul_fp12_sparse");
|
|
|
|
|
let square: Vec<U256> = make_mul_stack(in0, in1, out, f, f, "square_fp12_test");
|
2022-11-15 13:34:47 -08:00
|
|
|
|
2022-12-15 13:18:00 -08:00
|
|
|
let out_normal: Vec<U256> = run_interpreter(test_mul, normal)?.stack().to_vec();
|
|
|
|
|
let out_sparse: Vec<U256> = run_interpreter(test_mul, sparse)?.stack().to_vec();
|
|
|
|
|
let out_square: Vec<U256> = run_interpreter(test_mul, square)?.stack().to_vec();
|
2022-11-15 13:34:47 -08:00
|
|
|
|
2022-12-15 17:00:38 -08:00
|
|
|
let exp_normal: Vec<U256> = make_mul_expected(f, g);
|
|
|
|
|
let exp_sparse: Vec<U256> = make_mul_expected(f, h);
|
|
|
|
|
let exp_square: Vec<U256> = make_mul_expected(f, f);
|
2022-11-15 13:34:47 -08:00
|
|
|
|
2022-12-15 13:18:00 -08:00
|
|
|
assert_eq!(out_normal, exp_normal);
|
|
|
|
|
assert_eq!(out_sparse, exp_sparse);
|
|
|
|
|
assert_eq!(out_square, exp_square);
|
2022-11-15 13:34:47 -08:00
|
|
|
|
|
|
|
|
Ok(())
|
2022-11-15 13:40:14 -08:00
|
|
|
}
|
2022-12-15 17:00:38 -08:00
|
|
|
|
|
|
|
|
fn make_frob_stack(f: Fp12) -> Vec<U256> {
|
|
|
|
|
let ptr = U256::from(100);
|
|
|
|
|
let f: Vec<U256> = f.into_iter().flatten().flatten().collect();
|
|
|
|
|
let mut input = vec![ptr];
|
|
|
|
|
input.extend(f);
|
|
|
|
|
input.extend(vec![ptr]);
|
|
|
|
|
input.reverse();
|
|
|
|
|
input
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_frob_expected(n: usize, f: Fp12) -> Vec<U256> {
|
|
|
|
|
frob_fp12(n, f)
|
|
|
|
|
.into_iter()
|
|
|
|
|
.flatten()
|
|
|
|
|
.flatten()
|
|
|
|
|
.rev()
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_frob_fp12() -> Result<()> {
|
|
|
|
|
let f: Fp12 = gen_fp12();
|
|
|
|
|
|
|
|
|
|
let test_frob1 = KERNEL.global_labels["test_frob_fp12_1"];
|
|
|
|
|
let test_frob2 = KERNEL.global_labels["test_frob_fp12_2"];
|
|
|
|
|
let test_frob3 = KERNEL.global_labels["test_frob_fp12_3"];
|
|
|
|
|
let test_frob6 = KERNEL.global_labels["test_frob_fp12_6"];
|
|
|
|
|
|
|
|
|
|
let stack = make_frob_stack(f);
|
|
|
|
|
|
|
|
|
|
let out_frob1: Vec<U256> = run_interpreter(test_frob1, stack.clone())?.stack().to_vec();
|
|
|
|
|
let out_frob2: Vec<U256> = run_interpreter(test_frob2, stack.clone())?.stack().to_vec();
|
|
|
|
|
let out_frob3: Vec<U256> = run_interpreter(test_frob3, stack.clone())?.stack().to_vec();
|
|
|
|
|
let out_frob6: Vec<U256> = run_interpreter(test_frob6, stack)?.stack().to_vec();
|
|
|
|
|
|
|
|
|
|
let exp_frob1: Vec<U256> = make_frob_expected(1, f);
|
|
|
|
|
let exp_frob2: Vec<U256> = make_frob_expected(2, f);
|
|
|
|
|
let exp_frob3: Vec<U256> = make_frob_expected(3, f);
|
|
|
|
|
let exp_frob6: Vec<U256> = make_frob_expected(6, f);
|
|
|
|
|
|
|
|
|
|
assert_eq!(out_frob1, exp_frob1);
|
|
|
|
|
assert_eq!(out_frob2, exp_frob2);
|
|
|
|
|
assert_eq!(out_frob3, exp_frob3);
|
|
|
|
|
assert_eq!(out_frob6, exp_frob6);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2022-12-19 14:39:23 -08:00
|
|
|
|
2022-12-20 11:57:45 -08:00
|
|
|
fn make_inv_stack(f: Fp12) -> Vec<U256> {
|
2022-12-20 12:21:27 -08:00
|
|
|
let ptr = U256::from(200);
|
|
|
|
|
let inv = U256::from(300);
|
2022-12-20 11:57:45 -08:00
|
|
|
let f: Vec<U256> = f.into_iter().flatten().flatten().collect();
|
|
|
|
|
|
|
|
|
|
let mut input = vec![ptr];
|
|
|
|
|
input.extend(f);
|
|
|
|
|
input.extend(vec![ptr, inv, U256::from_str("0xdeadbeef").unwrap()]);
|
|
|
|
|
input.reverse();
|
|
|
|
|
input
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_inv_fp12() -> Result<()> {
|
|
|
|
|
let f: Fp12 = gen_fp12();
|
|
|
|
|
|
2022-12-20 12:47:09 -08:00
|
|
|
let test_inv = KERNEL.global_labels["test_inv_fp12"];
|
2022-12-20 11:57:45 -08:00
|
|
|
let stack = make_inv_stack(f);
|
|
|
|
|
|
|
|
|
|
let output: Vec<U256> = run_interpreter(test_inv, stack)?.stack().to_vec();
|
|
|
|
|
|
|
|
|
|
assert_eq!(output, vec![]);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-20 12:47:09 -08:00
|
|
|
fn make_pow_stack(f: Fp12) -> Vec<U256> {
|
2022-12-20 12:29:48 -08:00
|
|
|
let ptr = U256::from(300);
|
|
|
|
|
let out = U256::from(400);
|
2022-12-19 14:39:23 -08:00
|
|
|
let f: Vec<U256> = f.into_iter().flatten().flatten().collect();
|
|
|
|
|
let ret_stack = U256::from(KERNEL.global_labels["ret_stack"]);
|
|
|
|
|
|
2022-12-20 12:29:48 -08:00
|
|
|
let mut input = vec![ptr];
|
2022-12-19 14:39:23 -08:00
|
|
|
input.extend(f);
|
2022-12-20 12:29:48 -08:00
|
|
|
input.extend(vec![ptr, out, ret_stack, out]);
|
2022-12-19 14:39:23 -08:00
|
|
|
input.reverse();
|
|
|
|
|
input
|
|
|
|
|
}
|
2022-12-20 12:47:09 -08:00
|
|
|
|
|
|
|
|
fn make_pow_expected(f: Fp12) -> Vec<U256> {
|
2022-12-20 17:23:05 -08:00
|
|
|
fast_exp(f).into_iter().flatten().flatten().rev().collect()
|
2022-12-20 12:47:09 -08:00
|
|
|
}
|
|
|
|
|
|
2022-12-20 12:47:36 -08:00
|
|
|
#[test]
|
2022-12-20 12:47:09 -08:00
|
|
|
fn test_pow_fp12() -> Result<()> {
|
|
|
|
|
let f: Fp12 = gen_fp12();
|
|
|
|
|
|
|
|
|
|
let test_pow = KERNEL.global_labels["test_pow"];
|
|
|
|
|
let stack = make_pow_stack(f);
|
|
|
|
|
|
|
|
|
|
let output: Vec<U256> = run_interpreter(test_pow, stack)?.stack().to_vec();
|
|
|
|
|
let expected: Vec<U256> = make_pow_expected(f);
|
|
|
|
|
|
|
|
|
|
assert_eq!(output, expected);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2022-12-20 17:23:05 -08:00
|
|
|
|
|
|
|
|
fn make_miller_stack(p: [Fp; 2], q: [Fp2; 2]) -> Vec<U256> {
|
|
|
|
|
let ptr = U256::from(300);
|
|
|
|
|
let out = U256::from(400);
|
|
|
|
|
|
|
|
|
|
let p: Vec<U256> = p.into_iter().collect();
|
|
|
|
|
let q: Vec<U256> = q.into_iter().flatten().collect();
|
|
|
|
|
|
|
|
|
|
let ret_stack = U256::from(KERNEL.global_labels["ret_stack"]);
|
|
|
|
|
|
|
|
|
|
let mut input = vec![ptr];
|
|
|
|
|
input.extend(p);
|
|
|
|
|
input.extend(q);
|
|
|
|
|
input.extend(vec![ptr, out, ret_stack]);
|
|
|
|
|
input.reverse();
|
|
|
|
|
input
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-20 21:53:52 -08:00
|
|
|
fn store_tangent(p: [Fp; 2], q: [Fp2; 2]) -> Fp12 {
|
|
|
|
|
let [px, py] = p;
|
|
|
|
|
let [qx, qy] = q;
|
|
|
|
|
|
|
|
|
|
let cx = neg_fp(mul_fp(U256::from(3), mul_fp(px, px)));
|
|
|
|
|
let cy = mul_fp(U256::from(2), py);
|
|
|
|
|
|
|
|
|
|
sparse_embed(
|
|
|
|
|
sub_fp(mul_fp(py, py), U256::from(9)),
|
|
|
|
|
mul_fp2(embed_fp2(cx), qx),
|
|
|
|
|
mul_fp2(embed_fp2(cy), qy),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn store_cord(p1: [Fp; 2], p2: [Fp; 2], q: [Fp2; 2]) -> Fp12 {
|
|
|
|
|
let [p1x, p1y] = p1;
|
|
|
|
|
let [p2x, p2y] = p2;
|
|
|
|
|
let [qx, qy] = q;
|
|
|
|
|
|
|
|
|
|
let cx = sub_fp(p2y,p1y);
|
|
|
|
|
let cy = sub_fp(p1x,p2x);
|
|
|
|
|
|
|
|
|
|
sparse_embed(
|
|
|
|
|
sub_fp(mul_fp(p1y, p2x), mul_fp(p2y, p1x)),
|
|
|
|
|
mul_fp2(embed_fp2(cx), qx),
|
|
|
|
|
mul_fp2(embed_fp2(cy), qy),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_tan_stack(p: [Fp; 2], q: [Fp2; 2]) -> Vec<U256> {
|
|
|
|
|
let p: Vec<U256> = p.into_iter().collect();
|
|
|
|
|
let q: Vec<U256> = q.into_iter().flatten().collect();
|
|
|
|
|
|
|
|
|
|
let mut input = p;
|
|
|
|
|
input.extend(q);
|
|
|
|
|
input.reverse();
|
|
|
|
|
input
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_tan_expected(p: [Fp; 2], q: [Fp2; 2]) -> Vec<U256> {
|
|
|
|
|
store_tangent(p, q)
|
|
|
|
|
.into_iter()
|
|
|
|
|
.flatten()
|
|
|
|
|
.flatten()
|
|
|
|
|
.rev()
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_store_tangent() -> Result<()> {
|
|
|
|
|
let p = [gen_fp(), gen_fp()];
|
|
|
|
|
let q = [[gen_fp(), gen_fp()], [gen_fp(), gen_fp()]];
|
|
|
|
|
|
|
|
|
|
let expected = make_tan_expected(p, q);
|
|
|
|
|
|
|
|
|
|
let stack = make_tan_stack(p, q);
|
|
|
|
|
let test_tan = KERNEL.global_labels["test_store_tangent"];
|
|
|
|
|
|
|
|
|
|
let output: Vec<U256> = run_interpreter(test_tan, stack)?.stack().to_vec();
|
|
|
|
|
|
|
|
|
|
assert_eq!(output, expected);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_cord_stack(p1: [Fp; 2], p2: [Fp; 2], q: [Fp2; 2]) -> Vec<U256> {
|
|
|
|
|
let p1: Vec<U256> = p1.into_iter().collect();
|
|
|
|
|
let p2: Vec<U256> = p2.into_iter().collect();
|
|
|
|
|
let q: Vec<U256> = q.into_iter().flatten().collect();
|
|
|
|
|
|
|
|
|
|
let mut input = p1;
|
|
|
|
|
input.extend(p2);
|
|
|
|
|
input.extend(q);
|
|
|
|
|
input.reverse();
|
|
|
|
|
input
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_cord_expected(p1: [Fp; 2],p2: [Fp; 2], q: [Fp2; 2]) -> Vec<U256> {
|
|
|
|
|
store_cord(p1, p2, q)
|
|
|
|
|
.into_iter()
|
|
|
|
|
.flatten()
|
|
|
|
|
.flatten()
|
|
|
|
|
.rev()
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_store_cord() -> Result<()> {
|
|
|
|
|
let p1 = [gen_fp(), gen_fp()];
|
|
|
|
|
let p2 = [gen_fp(), gen_fp()];
|
|
|
|
|
let q = [[gen_fp(), gen_fp()], [gen_fp(), gen_fp()]];
|
|
|
|
|
|
|
|
|
|
let expected = make_cord_expected(p1, p2, q);
|
|
|
|
|
|
|
|
|
|
let stack = make_cord_stack(p1, p2, q);
|
|
|
|
|
let test_cord = KERNEL.global_labels["test_store_cord"];
|
|
|
|
|
|
|
|
|
|
let output: Vec<U256> = run_interpreter(test_cord, stack)?.stack().to_vec();
|
|
|
|
|
|
|
|
|
|
assert_eq!(output, expected);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-20 17:23:05 -08:00
|
|
|
#[test]
|
|
|
|
|
fn test_miller() -> Result<()> {
|
|
|
|
|
let p = [U256::from(1), U256::from(2)];
|
|
|
|
|
let q = [
|
|
|
|
|
[
|
2022-12-20 17:27:12 -08:00
|
|
|
U256::from_str("0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2")
|
|
|
|
|
.unwrap(),
|
2022-12-20 17:23:05 -08:00
|
|
|
],
|
|
|
|
|
[
|
2022-12-20 17:27:12 -08:00
|
|
|
U256::from_str("0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b")
|
|
|
|
|
.unwrap(),
|
2022-12-20 17:23:05 -08:00
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let test_mill = KERNEL.global_labels["test_miller"];
|
|
|
|
|
let stack = make_miller_stack(p, q);
|
|
|
|
|
|
|
|
|
|
let output: Vec<U256> = run_interpreter(test_mill, stack)?.stack().to_vec();
|
|
|
|
|
let mut expected: Vec<U256> = vec![
|
2022-12-20 17:27:12 -08:00
|
|
|
U256::from_str("0xbf4dbb7e41fb58122aa29dcced57731d7cbb49b1fe9a73cb13416e1002376da")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x110b019c149b43a7fbd6d42d7553debcbebd35c148f63aaecf72a5fbda451ac6")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x27225e97ee6c877964c8f32e0b54e61ead09c3e818174cd8b5beabe7cd7385e8")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x5762cb6648b4b4c5df8a8874a21d937adf185d91f34e8ccf58f5b39196db02").unwrap(),
|
|
|
|
|
U256::from_str("0x463002dc1a426b172f4a1e29486fc11eba01de99b559368139c8ef5271eb37f")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x753dcc72acdffcc45633803f1b555388969dd7c27d2a674a23a228f522480d9")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0xd32a892d29151553101376a6638938135e30126f698a40a73f20c6ac64a4585")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x290afd3e28c223a624d9f5a737f9f9e4b4200b518333844d81acc445fa5910da")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x262e0ee72a8123b741dc113b8e2d207ee8bad011e0f6ae2015439960c789cf78")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x1588e0b23d868d7517e3021e620c69eb1521a49faa9bfcd4cf3a54127d4d14cb")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x1c23a135a7dfa96db62622c5fef4b9751d121523dd39ca1cefeacb3419835a53")
|
|
|
|
|
.unwrap(),
|
|
|
|
|
U256::from_str("0x2caeb873076ec8f37fa7af265d2966dd0024acbc63bd2b21f323084fc71f4a59")
|
|
|
|
|
.unwrap(),
|
2022-12-20 17:23:05 -08:00
|
|
|
];
|
|
|
|
|
expected.reverse();
|
|
|
|
|
|
|
|
|
|
assert_eq!(output, expected);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|