mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 22:33:06 +00:00
skeleton inv
This commit is contained in:
parent
a503b05813
commit
7788a29f4a
@ -974,7 +974,7 @@
|
||||
|
||||
%macro assert_eq_fp12_unit
|
||||
// stack: ptr
|
||||
DUP1 %mload_kernel_code
|
||||
DUP1 %mload_kernel_code
|
||||
// stack: x00, ptr
|
||||
%assert_eq_const(1)
|
||||
// stack: ptr
|
||||
|
||||
@ -23,23 +23,26 @@
|
||||
|
||||
global inverse_fp12:
|
||||
// stack: ptr, inv, retdest
|
||||
DUP1 %load_fp12
|
||||
// DUP1 %load_fp12
|
||||
// stack: f, ptr, inv, retdest
|
||||
DUP14
|
||||
// stack: inv, f, ptr, inv, retdest
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ff::bn254_base::inverse_fp12)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv11)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv10)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv9)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv8)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv7)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv6)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv5)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv4)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv3)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv2)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv1)
|
||||
PROVER_INPUT(ffe::bn254_base::ext_inv0)
|
||||
// stack: f^-1, inv, f, ptr, inv, retdest
|
||||
|
||||
%jump(0xdeadbeef)
|
||||
|
||||
DUP13
|
||||
// stack: inv, f^-1, inv, f, ptr, inv, retdest
|
||||
%store_fp12
|
||||
@ -55,6 +58,9 @@ global check_inv:
|
||||
// stack: 200, ptr, inv, retdest
|
||||
%assert_eq_fp12_unit
|
||||
// stack: ptr, inv, retdest
|
||||
POP SWAP1
|
||||
%pop2
|
||||
// stack: retdest
|
||||
%jump(0xdeadbeef)
|
||||
// SWAP1
|
||||
// stack: retdest, inv
|
||||
JUMP
|
||||
// JUMP
|
||||
|
||||
@ -96,6 +96,10 @@ fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
||||
[sub_fp(a, b), sub_fp(a_, b_)]
|
||||
}
|
||||
|
||||
fn neg_fp2(a: Fp2) -> Fp2 {
|
||||
sub_fp2(embed_fp2(ZERO), a)
|
||||
}
|
||||
|
||||
fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
let [b, b_] = b;
|
||||
@ -131,6 +135,10 @@ fn sub_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
||||
[e0, e1, e2]
|
||||
}
|
||||
|
||||
fn neg_fp6(a: Fp6) -> Fp6 {
|
||||
sub_fp6(embed_fp6(ZERO), a)
|
||||
}
|
||||
|
||||
fn mul_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
||||
let [c0, c1, c2] = c;
|
||||
let [d0, d1, d2] = d;
|
||||
@ -343,6 +351,51 @@ fn frob_fp12(n: usize, f: Fp12) -> Fp12 {
|
||||
[frob_fp6(n, f0), mul_fp6(scale, frob_fp6(n, f1))]
|
||||
}
|
||||
|
||||
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 {
|
||||
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)];
|
||||
[mul_fp6(e, f[0]), neg_fp6(mul_fp6(e, f[1]))]
|
||||
}
|
||||
|
||||
const EXPS4: [(bool, bool, bool); 65] = [
|
||||
(true, true, true),
|
||||
(true, true, false),
|
||||
@ -604,6 +657,35 @@ fn test_mul_fp12() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inv_fp12() -> Result<()> {
|
||||
let ptr = U256::from(100);
|
||||
let inv = U256::from(200);
|
||||
|
||||
let f: Fp12 = gen_fp12();
|
||||
let flat_f: Vec<U256> = f.into_iter().flatten().flatten().collect();
|
||||
let mut stack: Vec<U256> = flat_f.clone();
|
||||
stack.extend(vec![ptr, inv]);
|
||||
stack.reverse();
|
||||
|
||||
let g = inv_fp12(f);
|
||||
let one = mul_fp12(f, g);
|
||||
println!("ONE? {:#?}", one);
|
||||
|
||||
let mut expected: Vec<U256> = g.into_iter().flatten().flatten().collect();
|
||||
expected.extend(vec![inv]);
|
||||
expected.extend(flat_f);
|
||||
expected.extend(vec![ptr, inv]);
|
||||
expected.reverse();
|
||||
|
||||
let initial_offset = KERNEL.global_labels["inverse_fp12"];
|
||||
let output: Vec<U256> = run_interpreter(initial_offset, stack)?.stack().to_vec();
|
||||
|
||||
assert_eq!(output, expected);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_frob_stack(f: Fp12) -> Vec<U256> {
|
||||
let ptr = U256::from(100);
|
||||
let f: Vec<U256> = f.into_iter().flatten().flatten().collect();
|
||||
|
||||
@ -6,9 +6,13 @@ use plonky2::field::types::Field;
|
||||
use crate::generation::prover_input::EvmField::{
|
||||
Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar,
|
||||
};
|
||||
use crate::generation::prover_input::FieldExtOp::{
|
||||
ExtInv0, ExtInv1, ExtInv10, ExtInv11, ExtInv2, ExtInv3, ExtInv4, ExtInv5, ExtInv6, ExtInv7,
|
||||
ExtInv8, ExtInv9,
|
||||
};
|
||||
use crate::generation::prover_input::FieldOp::{Inverse, Sqrt};
|
||||
use crate::generation::state::GenerationState;
|
||||
use crate::witness::util::stack_peek;
|
||||
use crate::witness::util::{stack_peek, stack_peeks};
|
||||
|
||||
/// Prover input function represented as a scoped function name.
|
||||
/// Example: `PROVER_INPUT(ff::bn254_base::inverse)` is represented as `ProverInputFn([ff, bn254_base, inverse])`.
|
||||
@ -26,6 +30,7 @@ impl<F: Field> GenerationState<F> {
|
||||
match input_fn.0[0].as_str() {
|
||||
"end_of_txns" => self.run_end_of_txns(),
|
||||
"ff" => self.run_ff(input_fn),
|
||||
"ffe" => self.run_ffe(input_fn),
|
||||
"mpt" => self.run_mpt(),
|
||||
"rlp" => self.run_rlp(),
|
||||
"account_code" => self.run_account_code(input_fn),
|
||||
@ -51,6 +56,14 @@ impl<F: Field> GenerationState<F> {
|
||||
field.op(op, x)
|
||||
}
|
||||
|
||||
/// Finite field extension operations.
|
||||
fn run_ffe(&self, input_fn: &ProverInputFn) -> U256 {
|
||||
let field = EvmField::from_str(input_fn.0[1].as_str()).unwrap();
|
||||
let op = FieldExtOp::from_str(input_fn.0[2].as_str()).unwrap();
|
||||
let xs = stack_peeks(self).expect("Empty stack");
|
||||
field.extop(op, xs)
|
||||
}
|
||||
|
||||
/// MPT data.
|
||||
fn run_mpt(&mut self) -> U256 {
|
||||
self.mpt_prover_inputs
|
||||
@ -100,6 +113,21 @@ enum FieldOp {
|
||||
Sqrt,
|
||||
}
|
||||
|
||||
enum FieldExtOp {
|
||||
ExtInv0,
|
||||
ExtInv1,
|
||||
ExtInv2,
|
||||
ExtInv3,
|
||||
ExtInv4,
|
||||
ExtInv5,
|
||||
ExtInv6,
|
||||
ExtInv7,
|
||||
ExtInv8,
|
||||
ExtInv9,
|
||||
ExtInv10,
|
||||
ExtInv11,
|
||||
}
|
||||
|
||||
impl FromStr for EvmField {
|
||||
type Err = ();
|
||||
|
||||
@ -126,6 +154,28 @@ impl FromStr for FieldOp {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for FieldExtOp {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"ext_inv0" => ExtInv0,
|
||||
"ext_inv1" => ExtInv1,
|
||||
"ext_inv2" => ExtInv2,
|
||||
"ext_inv3" => ExtInv3,
|
||||
"ext_inv4" => ExtInv4,
|
||||
"ext_inv5" => ExtInv5,
|
||||
"ext_inv6" => ExtInv6,
|
||||
"ext_inv7" => ExtInv7,
|
||||
"ext_inv8" => ExtInv8,
|
||||
"ext_inv9" => ExtInv9,
|
||||
"ext_inv10" => ExtInv10,
|
||||
"ext_inv11" => ExtInv11,
|
||||
_ => panic!("Unrecognized field extension operation."),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl EvmField {
|
||||
fn order(&self) -> U256 {
|
||||
match self {
|
||||
@ -152,6 +202,23 @@ impl EvmField {
|
||||
}
|
||||
}
|
||||
|
||||
fn extop(&self, op: FieldExtOp, xs: Vec<U256>) -> U256 {
|
||||
match op {
|
||||
FieldExtOp::ExtInv0 => self.ext_inv0(xs),
|
||||
FieldExtOp::ExtInv1 => self.ext_inv1(xs),
|
||||
FieldExtOp::ExtInv2 => self.ext_inv2(xs),
|
||||
FieldExtOp::ExtInv3 => self.ext_inv3(xs),
|
||||
FieldExtOp::ExtInv4 => self.ext_inv4(xs),
|
||||
FieldExtOp::ExtInv5 => self.ext_inv5(xs),
|
||||
FieldExtOp::ExtInv6 => self.ext_inv6(xs),
|
||||
FieldExtOp::ExtInv7 => self.ext_inv7(xs),
|
||||
FieldExtOp::ExtInv8 => self.ext_inv8(xs),
|
||||
FieldExtOp::ExtInv9 => self.ext_inv9(xs),
|
||||
FieldExtOp::ExtInv10 => self.ext_inv10(xs),
|
||||
FieldExtOp::ExtInv11 => self.ext_inv11(xs),
|
||||
}
|
||||
}
|
||||
|
||||
fn inverse(&self, x: U256) -> U256 {
|
||||
let n = self.order();
|
||||
assert!(x < n);
|
||||
@ -168,6 +235,84 @@ impl EvmField {
|
||||
);
|
||||
modexp(x, q, n)
|
||||
}
|
||||
|
||||
fn ext_inv(&self, xs: Vec<U256>, offset: usize) -> [U256; 12] {
|
||||
|
||||
let f0 = xs.clone().into_iter().nth(offset).unwrap();
|
||||
let f1 = xs.clone().into_iter().nth(offset + 1).unwrap();
|
||||
let f2 = xs.clone().into_iter().nth(offset + 2).unwrap();
|
||||
let f3 = xs.clone().into_iter().nth(offset + 3).unwrap();
|
||||
let f4 = xs.clone().into_iter().nth(offset + 4).unwrap();
|
||||
let f5 = xs.clone().into_iter().nth(offset + 5).unwrap();
|
||||
let f6 = xs.clone().into_iter().nth(offset + 6).unwrap();
|
||||
let f7 = xs.clone().into_iter().nth(offset + 7).unwrap();
|
||||
let f8 = xs.clone().into_iter().nth(offset + 8).unwrap();
|
||||
let f9 = xs.clone().into_iter().nth(offset + 9).unwrap();
|
||||
let f10 = xs.clone().into_iter().nth(offset + 10).unwrap();
|
||||
let f11 = xs.clone().into_iter().nth(offset + 11).unwrap();
|
||||
|
||||
let f = [
|
||||
[[f0, f1], [f2, f3], [f4, f5]],
|
||||
[[f6, f7], [f8, f9], [f10, f11]],
|
||||
];
|
||||
|
||||
println!("STACK_: {:#?}", f);
|
||||
|
||||
let g = inv_fp12(f);
|
||||
|
||||
[
|
||||
g[0][0][0], g[0][0][1], g[0][1][0], g[0][1][1], g[0][2][0], g[0][2][1],
|
||||
g[1][0][0], g[1][0][1], g[1][1][0], g[1][1][1], g[1][2][0], g[1][2][1],
|
||||
]
|
||||
}
|
||||
|
||||
fn ext_inv0(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 12)[0]
|
||||
}
|
||||
|
||||
fn ext_inv1(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 11)[1]
|
||||
}
|
||||
|
||||
fn ext_inv2(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 10)[2]
|
||||
}
|
||||
|
||||
fn ext_inv3(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 9)[3]
|
||||
}
|
||||
|
||||
fn ext_inv4(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 8)[4]
|
||||
}
|
||||
|
||||
fn ext_inv5(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 7)[5]
|
||||
}
|
||||
|
||||
fn ext_inv6(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 6)[6]
|
||||
}
|
||||
|
||||
fn ext_inv7(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 5)[7]
|
||||
}
|
||||
|
||||
fn ext_inv8(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 4)[8]
|
||||
}
|
||||
|
||||
fn ext_inv9(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 3)[9]
|
||||
}
|
||||
|
||||
fn ext_inv10(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 2)[10]
|
||||
}
|
||||
|
||||
fn ext_inv11(&self, xs: Vec<U256>) -> U256 {
|
||||
Self::ext_inv(&self, xs, 1)[11]
|
||||
}
|
||||
}
|
||||
|
||||
fn modexp(x: U256, e: U256, n: U256) -> U256 {
|
||||
@ -182,3 +327,377 @@ fn modexp(x: U256, e: U256, n: U256) -> U256 {
|
||||
}
|
||||
product
|
||||
}
|
||||
|
||||
type Fp = U256;
|
||||
type Fp2 = [U256; 2];
|
||||
type Fp6 = [Fp2; 3];
|
||||
type Fp12 = [Fp6; 2];
|
||||
|
||||
const ZERO: Fp = U256([0, 0, 0, 0]);
|
||||
|
||||
const BN_BASE: U256 = U256([
|
||||
4332616871279656263,
|
||||
10917124144477883021,
|
||||
13281191951274694749,
|
||||
3486998266802970665,
|
||||
]);
|
||||
|
||||
fn embed_fp2(x: Fp) -> Fp2 {
|
||||
[x, ZERO]
|
||||
}
|
||||
|
||||
fn embed_fp2_fp6(a: Fp2) -> Fp6 {
|
||||
[a, embed_fp2(ZERO), embed_fp2(ZERO)]
|
||||
}
|
||||
|
||||
fn embed_fp6(x: Fp) -> Fp6 {
|
||||
embed_fp2_fp6(embed_fp2(x))
|
||||
}
|
||||
|
||||
fn embed_fp12(x: Fp) -> Fp12 {
|
||||
[embed_fp6(x), embed_fp6(ZERO)]
|
||||
}
|
||||
|
||||
fn add_fp(x: Fp, y: Fp) -> Fp {
|
||||
(x + y) % BN_BASE
|
||||
}
|
||||
|
||||
fn add3_fp(x: Fp, y: Fp, z: Fp) -> Fp {
|
||||
(x + y + z) % BN_BASE
|
||||
}
|
||||
|
||||
fn mul_fp(x: Fp, y: Fp) -> Fp {
|
||||
U256::try_from(x.full_mul(y) % BN_BASE).unwrap()
|
||||
}
|
||||
|
||||
fn sub_fp(x: Fp, y: Fp) -> Fp {
|
||||
(BN_BASE + x - y) % BN_BASE
|
||||
}
|
||||
|
||||
fn neg_fp(x: Fp) -> Fp {
|
||||
(BN_BASE - x) % BN_BASE
|
||||
}
|
||||
|
||||
fn conj_fp2(a: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
[a, neg_fp(a_)]
|
||||
}
|
||||
|
||||
fn add_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
let [b, b_] = b;
|
||||
[add_fp(a, b), add_fp(a_, b_)]
|
||||
}
|
||||
|
||||
fn add3_fp2(a: Fp2, b: Fp2, c: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
let [b, b_] = b;
|
||||
let [c, c_] = c;
|
||||
[add3_fp(a, b, c), add3_fp(a_, b_, c_)]
|
||||
}
|
||||
|
||||
fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
let [b, b_] = b;
|
||||
[sub_fp(a, b), sub_fp(a_, b_)]
|
||||
}
|
||||
|
||||
fn neg_fp2(a: Fp2) -> Fp2 {
|
||||
sub_fp2(embed_fp2(ZERO), a)
|
||||
}
|
||||
|
||||
fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
let [b, b_] = b;
|
||||
[
|
||||
sub_fp(mul_fp(a, b), mul_fp(a_, b_)),
|
||||
add_fp(mul_fp(a, b_), mul_fp(a_, b)),
|
||||
]
|
||||
}
|
||||
|
||||
fn i9(a: Fp2) -> Fp2 {
|
||||
let [a, a_] = a;
|
||||
let nine = U256::from(9);
|
||||
[sub_fp(mul_fp(nine, a), a_), add_fp(a, mul_fp(nine, a_))]
|
||||
}
|
||||
|
||||
fn add_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
||||
let [c0, c1, c2] = c;
|
||||
let [d0, d1, d2] = d;
|
||||
|
||||
let e0 = add_fp2(c0, d0);
|
||||
let e1 = add_fp2(c1, d1);
|
||||
let e2 = add_fp2(c2, d2);
|
||||
[e0, e1, e2]
|
||||
}
|
||||
|
||||
fn sub_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
||||
let [c0, c1, c2] = c;
|
||||
let [d0, d1, d2] = d;
|
||||
|
||||
let e0 = sub_fp2(c0, d0);
|
||||
let e1 = sub_fp2(c1, d1);
|
||||
let e2 = sub_fp2(c2, d2);
|
||||
[e0, e1, e2]
|
||||
}
|
||||
|
||||
fn neg_fp6(a: Fp6) -> Fp6 {
|
||||
sub_fp6(embed_fp6(ZERO), a)
|
||||
}
|
||||
|
||||
fn mul_fp6(c: Fp6, d: Fp6) -> Fp6 {
|
||||
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),
|
||||
]
|
||||
}
|
||||
|
||||
fn sh(c: Fp6) -> Fp6 {
|
||||
let [c0, c1, c2] = c;
|
||||
[i9(c2), c0, c1]
|
||||
}
|
||||
|
||||
fn sparse_embed(x: [U256; 5]) -> Fp12 {
|
||||
let [g0, g1, g1_, g2, g2_] = x;
|
||||
[
|
||||
[embed_fp2(g0), [g1, g1_], embed_fp2(ZERO)],
|
||||
[embed_fp2(ZERO), [g2, g2_], embed_fp2(ZERO)],
|
||||
]
|
||||
}
|
||||
|
||||
fn mul_fp12(f: Fp12, g: Fp12) -> Fp12 {
|
||||
let [f0, f1] = f;
|
||||
let [g0, g1] = g;
|
||||
|
||||
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))]
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
let n = n % 6;
|
||||
let frob_t1 = frob_t1(n);
|
||||
let frob_t2 = frob_t2(n);
|
||||
|
||||
if n % 2 != 0 {
|
||||
[_c0, mul_fp2(frob_t1, _c1), mul_fp2(frob_t2, _c2)]
|
||||
} else {
|
||||
[c0, mul_fp2(frob_t1, c1), mul_fp2(frob_t2, c2)]
|
||||
}
|
||||
}
|
||||
|
||||
fn frob_fp12(n: usize, f: Fp12) -> Fp12 {
|
||||
let [f0, f1] = f;
|
||||
let scale = embed_fp2_fp6(frob_z(n));
|
||||
|
||||
[frob_fp6(n, f0), mul_fp6(scale, frob_fp6(n, f1))]
|
||||
}
|
||||
|
||||
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 {
|
||||
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)];
|
||||
[mul_fp6(e, f[0]), neg_fp6(mul_fp6(e, f[1]))]
|
||||
}
|
||||
|
||||
@ -39,6 +39,20 @@ pub(crate) fn stack_peek<F: Field>(state: &GenerationState<F>, i: usize) -> Opti
|
||||
)))
|
||||
}
|
||||
|
||||
/// Peak at the entire stack.
|
||||
pub(crate) fn stack_peeks<F: Field>(state: &GenerationState<F>) -> Option<Vec<U256>> {
|
||||
let n = state.registers.stack_len;
|
||||
let mut stack: Vec<U256> = vec![];
|
||||
for i in 0..n {
|
||||
stack.extend(vec![state.memory.get(MemoryAddress::new(
|
||||
state.registers.effective_context(),
|
||||
Segment::Stack,
|
||||
n - 1 - i,
|
||||
))])
|
||||
}
|
||||
Some(stack)
|
||||
}
|
||||
|
||||
pub(crate) fn mem_read_with_log<F: Field>(
|
||||
channel: MemoryChannel,
|
||||
address: MemoryAddress,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user