frob works

This commit is contained in:
Dmitry Vagner 2023-03-21 13:51:11 -07:00
parent caaf3b4a34
commit 4d83c58d1f
2 changed files with 617 additions and 226 deletions

View File

@ -2,13 +2,14 @@ use anyhow::Result;
use ethereum_types::U256;
use rand::Rng;
use crate::bn254_arithmetic::{Fp, Fp12, Fp2, Fp6};
use crate::bn254_pairing::{
gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve,
};
use crate::cpu::kernel::interpreter::{
run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization,
};
// use crate::bn254_arithmetic::{Fp, Fp12, Fp2, Fp6};
// use crate::bn254_pairing::{
// gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve,
// };
use crate::extension_tower::{Fp12, Stack, BN254};
use crate::memory::segments::Segment::BnPairing;
fn extract_stack(interpreter: Interpreter<'static>) -> Vec<U256> {
@ -20,48 +21,48 @@ fn extract_stack(interpreter: Interpreter<'static>) -> Vec<U256> {
.collect::<Vec<U256>>()
}
fn setup_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> InterpreterMemoryInitialization {
let mut stack = f.on_stack();
if label == "mul_fp254_6" {
stack.extend(g.on_stack());
}
stack.push(U256::from(0xdeadbeefu32));
InterpreterMemoryInitialization {
label: label.to_string(),
stack,
segment: BnPairing,
memory: vec![],
}
}
// fn setup_mul_fp6_test(f: Fp6, g: Fp6, label: &str) -> InterpreterMemoryInitialization {
// let mut stack = f.on_stack();
// if label == "mul_fp254_6" {
// stack.extend(g.on_stack());
// }
// stack.push(U256::from(0xdeadbeefu32));
// InterpreterMemoryInitialization {
// label: label.to_string(),
// stack,
// segment: BnPairing,
// memory: vec![],
// }
// }
#[test]
fn test_mul_fp6() -> Result<()> {
let mut rng = rand::thread_rng();
let f: Fp6 = rng.gen::<Fp6>();
let g: Fp6 = rng.gen::<Fp6>();
// #[test]
// fn test_mul_fp6() -> Result<()> {
// let mut rng = rand::thread_rng();
// let f: Fp6 = rng.gen::<Fp6>();
// let g: Fp6 = rng.gen::<Fp6>();
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 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 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<U256> = extract_stack(intrptr_normal);
let out_square: Vec<U256> = extract_stack(intrptr_square);
// let out_normal: Vec<U256> = extract_stack(intrptr_normal);
// let out_square: Vec<U256> = extract_stack(intrptr_square);
let exp_normal: Vec<U256> = (f * g).on_stack();
let exp_square: Vec<U256> = (f * f).on_stack();
// let exp_normal: Vec<U256> = (f * g).on_stack();
// let exp_square: Vec<U256> = (f * f).on_stack();
assert_eq!(out_normal, exp_normal);
assert_eq!(out_square, exp_square);
// assert_eq!(out_normal, exp_normal);
// assert_eq!(out_square, exp_square);
Ok(())
}
// Ok(())
// }
fn setup_mul_fp12_test(
out: usize,
f: Fp12,
g: Fp12,
f: Fp12<BN254>,
g: Fp12<BN254>,
label: &str,
) -> InterpreterMemoryInitialization {
let in0: usize = 200;
@ -89,60 +90,60 @@ fn test_mul_fp12() -> Result<()> {
let out: usize = 224;
let mut rng = rand::thread_rng();
let f: Fp12 = rng.gen::<Fp12>();
let g: Fp12 = rng.gen::<Fp12>();
let h: Fp12 = gen_fp12_sparse(&mut rng);
let f: Fp12<BN254> = rng.gen::<Fp12<BN254>>();
let g: Fp12<BN254> = rng.gen::<Fp12<BN254>>();
// let h: Fp12<BN254> = 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_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_sparse: Interpreter = run_interpreter_with_memory(setup_sparse).unwrap();
let intrptr_square: Interpreter = run_interpreter_with_memory(setup_square).unwrap();
let out_normal: Vec<U256> = intrptr_normal.extract_kernel_memory(BnPairing, out..out + 12);
let out_sparse: Vec<U256> = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12);
// let out_sparse: Vec<U256> = intrptr_sparse.extract_kernel_memory(BnPairing, out..out + 12);
let out_square: Vec<U256> = intrptr_square.extract_kernel_memory(BnPairing, out..out + 12);
let exp_normal: Vec<U256> = (f * g).on_stack();
let exp_sparse: Vec<U256> = (f * h).on_stack();
// let exp_sparse: Vec<U256> = (f * h).on_stack();
let exp_square: Vec<U256> = (f * f).on_stack();
assert_eq!(out_normal, exp_normal);
assert_eq!(out_sparse, exp_sparse);
// assert_eq!(out_sparse, exp_sparse);
assert_eq!(out_square, exp_square);
Ok(())
}
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(),
segment: BnPairing,
memory: vec![],
}
}
// 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(),
// segment: BnPairing,
// memory: vec![],
// }
// }
#[test]
fn test_frob_fp6() -> Result<()> {
let mut rng = rand::thread_rng();
let f: Fp6 = rng.gen::<Fp6>();
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<U256> = extract_stack(intrptr_frob);
let exp_frob: Vec<U256> = f.frob(n).on_stack();
assert_eq!(out_frob, exp_frob);
}
Ok(())
}
// #[test]
// fn test_frob_fp6() -> Result<()> {
// let mut rng = rand::thread_rng();
// let f: Fp6 = rng.gen::<Fp6>();
// 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<U256> = extract_stack(intrptr_frob);
// let exp_frob: Vec<U256> = f.frob(n).on_stack();
// assert_eq!(out_frob, exp_frob);
// }
// Ok(())
// }
fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryInitialization {
fn setup_frob_fp12_test(ptr: usize, f: Fp12<BN254>, n: usize) -> InterpreterMemoryInitialization {
InterpreterMemoryInitialization {
label: String::from("test_frob_fp254_12_") + &(n.to_string()),
stack: vec![U256::from(ptr)],
@ -155,7 +156,7 @@ fn setup_frob_fp12_test(ptr: usize, f: Fp12, n: usize) -> InterpreterMemoryIniti
fn test_frob_fp12() -> Result<()> {
let ptr: usize = 200;
let mut rng = rand::thread_rng();
let f: Fp12 = rng.gen::<Fp12>();
let f: Fp12<BN254> = rng.gen::<Fp12<BN254>>();
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();
@ -166,154 +167,154 @@ fn test_frob_fp12() -> Result<()> {
Ok(())
}
#[test]
fn test_inv_fp12() -> Result<()> {
let ptr: usize = 200;
let inv: usize = 212;
let mut rng = rand::thread_rng();
let f: Fp12 = rng.gen::<Fp12>();
// #[test]
// fn test_inv_fp12() -> Result<()> {
// let ptr: usize = 200;
// let inv: usize = 212;
// let mut rng = rand::thread_rng();
// let f: Fp12 = rng.gen::<Fp12>();
let setup = InterpreterMemoryInitialization {
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())],
};
let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap();
let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12);
let expected: Vec<U256> = f.inv().on_stack();
// let setup = InterpreterMemoryInitialization {
// 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())],
// };
// let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap();
// let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, inv..inv + 12);
// let expected: Vec<U256> = f.inv().on_stack();
assert_eq!(output, expected);
// assert_eq!(output, expected);
Ok(())
}
// Ok(())
// }
#[test]
fn test_invariant_exponent() -> Result<()> {
let ptr: usize = 200;
let mut rng = rand::thread_rng();
let f: Fp12 = rng.gen::<Fp12>();
// #[test]
// fn test_invariant_exponent() -> Result<()> {
// let ptr: usize = 200;
// let mut rng = rand::thread_rng();
// let f: Fp12 = rng.gen::<Fp12>();
let setup = InterpreterMemoryInitialization {
label: "bn254_invariant_exponent".to_string(),
stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)],
segment: BnPairing,
memory: vec![(ptr, f.on_stack())],
};
// let setup = InterpreterMemoryInitialization {
// label: "bn254_invariant_exponent".to_string(),
// stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)],
// segment: BnPairing,
// memory: vec![(ptr, f.on_stack())],
// };
let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap();
let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12);
let expected: Vec<U256> = invariant_exponent(f).on_stack();
// let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap();
// let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12);
// let expected: Vec<U256> = invariant_exponent(f).on_stack();
assert_eq!(output, expected);
// assert_eq!(output, expected);
Ok(())
}
// Ok(())
// }
// The curve is cyclic with generator (1, 2)
pub const CURVE_GENERATOR: Curve = {
Curve {
x: Fp { val: U256::one() },
y: Fp {
val: U256([2, 0, 0, 0]),
},
}
};
// // The curve is cyclic with generator (1, 2)
// pub const CURVE_GENERATOR: Curve = {
// Curve {
// x: Fp { val: U256::one() },
// y: Fp {
// 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: Fp {
val: U256([
0x46debd5cd992f6ed,
0x674322d4f75edadd,
0x426a00665e5c4479,
0x1800deef121f1e76,
]),
},
im: Fp {
val: U256([
0x97e485b7aef312c2,
0xf1aa493335a9e712,
0x7260bfb731fb5d25,
0x198e9393920d483a,
]),
},
},
y: Fp2 {
re: Fp {
val: U256([
0x4ce6cc0166fa7daa,
0xe3d1e7690c43d37b,
0x4aab71808dcb408f,
0x12c85ea5db8c6deb,
]),
},
im: Fp {
val: U256([
0x55acdadcd122975b,
0xbc4b313370b38ef3,
0xec9e99ad690c3395,
0x090689d0585ff075,
]),
},
},
}
};
// // The twisted curve is cyclic with generator (x, y) as follows
// pub const TWISTED_GENERATOR: TwistedCurve = {
// TwistedCurve {
// x: Fp2 {
// re: Fp {
// val: U256([
// 0x46debd5cd992f6ed,
// 0x674322d4f75edadd,
// 0x426a00665e5c4479,
// 0x1800deef121f1e76,
// ]),
// },
// im: Fp {
// val: U256([
// 0x97e485b7aef312c2,
// 0xf1aa493335a9e712,
// 0x7260bfb731fb5d25,
// 0x198e9393920d483a,
// ]),
// },
// },
// y: Fp2 {
// re: Fp {
// val: U256([
// 0x4ce6cc0166fa7daa,
// 0xe3d1e7690c43d37b,
// 0x4aab71808dcb408f,
// 0x12c85ea5db8c6deb,
// ]),
// },
// im: Fp {
// val: U256([
// 0x55acdadcd122975b,
// 0xbc4b313370b38ef3,
// 0xec9e99ad690c3395,
// 0x090689d0585ff075,
// ]),
// },
// },
// }
// };
#[test]
fn test_miller() -> Result<()> {
let ptr: usize = 200;
let out: usize = 206;
let inputs: Vec<U256> = 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,
];
// #[test]
// fn test_miller() -> Result<()> {
// let ptr: usize = 200;
// let out: usize = 206;
// let inputs: Vec<U256> = 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 setup = InterpreterMemoryInitialization {
label: "bn254_miller".to_string(),
stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)],
segment: BnPairing,
memory: vec![(ptr, inputs)],
};
let interpreter = run_interpreter_with_memory(setup).unwrap();
let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, out..out + 12);
let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack();
// 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)],
// };
// let interpreter = run_interpreter_with_memory(setup).unwrap();
// let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, out..out + 12);
// let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack();
assert_eq!(output, expected);
// assert_eq!(output, expected);
Ok(())
}
// Ok(())
// }
#[test]
fn test_tate() -> Result<()> {
let ptr: usize = 200;
let out: usize = 206;
let inputs: Vec<U256> = 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,
];
// #[test]
// fn test_tate() -> Result<()> {
// let ptr: usize = 200;
// let out: usize = 206;
// let inputs: Vec<U256> = 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 setup = InterpreterMemoryInitialization {
label: "bn254_tate".to_string(),
stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)],
segment: BnPairing,
memory: vec![(ptr, inputs)],
};
let interpreter = run_interpreter_with_memory(setup).unwrap();
let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, out..out + 12);
let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack();
// let setup = InterpreterMemoryInitialization {
// label: "bn254_tate".to_string(),
// stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)],
// segment: BnPairing,
// memory: vec![(ptr, inputs)],
// };
// let interpreter = run_interpreter_with_memory(setup).unwrap();
// let output: Vec<U256> = interpreter.extract_kernel_memory(BnPairing, out..out + 12);
// let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).on_stack();
assert_eq!(output, expected);
// assert_eq!(output, expected);
Ok(())
}
// Ok(())
// }

View File

@ -1,3 +1,4 @@
use std::mem::transmute;
use std::ops::{Add, Div, Mul, Neg, Sub};
use ethereum_types::{U256, U512};
@ -250,7 +251,7 @@ impl Div for BLS381 {
}
}
/// The degree 2 field extension Fp2 is given by adjoining i, the square root of -1, to Fp
/// The degree 2 field extension Fp2 is given by adjoining i, the square root of -1, to BN254
/// The arithmetic in this extension is standard complex arithmetic
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Fp2<T>
@ -263,7 +264,7 @@ where
impl<T> Distribution<Fp2<T>> for Standard
where
T: Distribution<T> + FieldExt,
T: FieldExt,
Standard: Distribution<T>,
{
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Fp2<T> {
@ -317,7 +318,7 @@ impl<T: FieldExt> Mul for Fp2<T> {
}
impl<T: FieldExt> Fp2<T> {
/// This function scalar multiplies an Fp2 by an Fp
/// This function scalar multiplies an Fp2 by an BN254
pub fn scale(self, x: T) -> Self {
Fp2 {
re: x * self.re,
@ -371,8 +372,10 @@ impl<T: FieldExt> Div for Fp2<T> {
/// Helper function which multiplies by the Fp2 element
/// whose cube root we will adjoin in the next extension
pub trait Adj {
pub trait Adj: Sized {
fn mul_adj(self) -> Self;
const FROB_T: [[Self; 6]; 2];
const FROB_Z: [Self; 12];
}
impl Adj for Fp2<BN254> {
@ -383,6 +386,393 @@ impl Adj for Fp2<BN254> {
im: self.re + nine * self.im,
}
}
const FROB_T: [[Fp2<BN254>; 6]; 2] = [
[
Fp2 {
re: BN254 { val: U256::one() },
im: BN254 { val: U256::zero() },
},
Fp2 {
re: BN254 {
val: U256([
0x99e39557176f553d,
0xb78cc310c2c3330c,
0x4c0bec3cf559b143,
0x2fb347984f7911f7,
]),
},
im: BN254 {
val: U256([
0x1665d51c640fcba2,
0x32ae2a1d0b7c9dce,
0x4ba4cc8bd75a0794,
0x16c9e55061ebae20,
]),
},
},
Fp2 {
re: BN254 {
val: U256([
0xe4bd44e5607cfd48,
0xc28f069fbb966e3d,
0x5e6dd9e7e0acccb0,
0x30644e72e131a029,
]),
},
im: BN254 { val: U256::zero() },
},
Fp2 {
re: BN254 {
val: U256([
0x7b746ee87bdcfb6d,
0x805ffd3d5d6942d3,
0xbaff1c77959f25ac,
0x0856e078b755ef0a,
]),
},
im: BN254 {
val: U256([
0x380cab2baaa586de,
0x0fdf31bf98ff2631,
0xa9f30e6dec26094f,
0x04f1de41b3d1766f,
]),
},
},
Fp2 {
re: BN254 {
val: U256([
0x5763473177fffffe,
0xd4f263f1acdb5c4f,
0x59e26bcea0d48bac,
0x0,
]),
},
im: BN254 { val: U256::zero() },
},
Fp2 {
re: BN254 {
val: U256([
0x62e913ee1dada9e4,
0xf71614d4b0b71f3a,
0x699582b87809d9ca,
0x28be74d4bb943f51,
]),
},
im: BN254 {
val: U256([
0xedae0bcec9c7aac7,
0x54f40eb4c3f6068d,
0xc2b86abcbe01477a,
0x14a88ae0cb747b99,
]),
},
},
],
[
Fp2 {
re: BN254 { val: U256::one() },
im: BN254 { val: U256::zero() },
},
Fp2 {
re: {
BN254 {
val: U256([
0x848a1f55921ea762,
0xd33365f7be94ec72,
0x80f3c0b75a181e84,
0x05b54f5e64eea801,
]),
}
},
im: {
BN254 {
val: U256([
0xc13b4711cd2b8126,
0x3685d2ea1bdec763,
0x9f3a80b03b0b1c92,
0x2c145edbe7fd8aee,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0x5763473177fffffe,
0xd4f263f1acdb5c4f,
0x59e26bcea0d48bac,
0x0,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0x0e1a92bc3ccbf066,
0xe633094575b06bcb,
0x19bee0f7b5b2444e,
0xbc58c6611c08dab,
]),
}
},
im: {
BN254 {
val: U256([
0x5fe3ed9d730c239f,
0xa44a9e08737f96e5,
0xfeb0f6ef0cd21d04,
0x23d5e999e1910a12,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0xe4bd44e5607cfd48,
0xc28f069fbb966e3d,
0x5e6dd9e7e0acccb0,
0x30644e72e131a029,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0xa97bda050992657f,
0xde1afb54342c724f,
0x1d9da40771b6f589,
0x1ee972ae6a826a7d,
]),
}
},
im: {
BN254 {
val: U256([
0x5721e37e70c255c9,
0x54326430418536d1,
0xd2b513cdbb257724,
0x10de546ff8d4ab51,
]),
}
},
},
],
];
const FROB_Z: [Fp2<BN254>; 12] = [
Fp2 {
re: { BN254 { val: U256::one() } },
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0xd60b35dadcc9e470,
0x5c521e08292f2176,
0xe8b99fdd76e68b60,
0x1284b71c2865a7df,
]),
}
},
im: {
BN254 {
val: U256([
0xca5cf05f80f362ac,
0x747992778eeec7e5,
0xa6327cfe12150b8e,
0x246996f3b4fae7e6,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0xe4bd44e5607cfd49,
0xc28f069fbb966e3d,
0x5e6dd9e7e0acccb0,
0x30644e72e131a029,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0xe86f7d391ed4a67f,
0x894cb38dbe55d24a,
0xefe9608cd0acaa90,
0x19dc81cfcc82e4bb,
]),
}
},
im: {
BN254 {
val: U256([
0x7694aa2bf4c0c101,
0x7f03a5e397d439ec,
0x06cbeee33576139d,
0xabf8b60be77d73,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0xe4bd44e5607cfd48,
0xc28f069fbb966e3d,
0x5e6dd9e7e0acccb0,
0x30644e72e131a029,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0x1264475e420ac20f,
0x2cfa95859526b0d4,
0x072fc0af59c61f30,
0x757cab3a41d3cdc,
]),
}
},
im: {
BN254 {
val: U256([
0xe85845e34c4a5b9c,
0xa20b7dfd71573c93,
0x18e9b79ba4e2606c,
0xca6b035381e35b6,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0x3c208c16d87cfd46,
0x97816a916871ca8d,
0xb85045b68181585d,
0x30644e72e131a029,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0x6615563bfbb318d7,
0x3b2f4c893f42a916,
0xcf96a5d90a9accfd,
0x1ddf9756b8cbf849,
]),
}
},
im: {
BN254 {
val: U256([
0x71c39bb757899a9b,
0x2307d819d98302a7,
0x121dc8b86f6c4ccf,
0x0bfab77f2c36b843,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0x5763473177fffffe,
0xd4f263f1acdb5c4f,
0x59e26bcea0d48bac,
0x0,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0x53b10eddb9a856c8,
0x0e34b703aa1bf842,
0xc866e529b0d4adcd,
0x1687cca314aebb6d,
]),
}
},
im: {
BN254 {
val: U256([
0xc58be1eae3bc3c46,
0x187dc4add09d90a0,
0xb18456d34c0b44c0,
0x2fb855bcd54a22b6,
]),
}
},
},
Fp2 {
re: {
BN254 {
val: U256([
0x5763473177ffffff,
0xd4f263f1acdb5c4f,
0x59e26bcea0d48bac,
0x0,
]),
}
},
im: { BN254 { val: U256::zero() } },
},
Fp2 {
re: {
BN254 {
val: U256([
0x29bc44b896723b38,
0x6a86d50bd34b19b9,
0xb120850727bb392d,
0x290c83bf3d14634d,
]),
}
},
im: {
BN254 {
val: U256([
0x53c846338c32a1ab,
0xf575ec93f71a8df9,
0x9f668e1adc9ef7f0,
0x23bd9e3da9136a73,
]),
}
},
},
];
}
impl Adj for Fp2<BLS381> {
@ -392,6 +782,8 @@ impl Adj for Fp2<BLS381> {
im: self.re + self.im,
}
}
const FROB_T: [[Fp2<BLS381>; 6]; 2] = [[Fp2::<BLS381>::ZERO; 6]; 2];
const FROB_Z: [Fp2<BLS381>; 12] = [Fp2::<BLS381>::ZERO; 12];
}
/// The degree 3 field extension Fp6 over Fp2 is given by adjoining t, where t^3 = 1 + i
@ -409,7 +801,7 @@ where
impl<T> Distribution<Fp6<T>> for Standard
where
T: Distribution<T> + FieldExt,
T: FieldExt,
Fp2<T>: Adj,
Standard: Distribution<T>,
{
@ -514,15 +906,6 @@ where
}
}
impl<T> Fp6<T>
where
T: FieldExt,
Fp2<T>: Adj,
{
const FROB_T: [[Fp2<T>; 6]; 2] = [[Fp2::<T>::ZERO; 6]; 2];
const FROB_Z: [Fp2<T>; 12] = [Fp2::<T>::ZERO; 12];
}
impl<T> Fp6<T>
where
T: FieldExt,
@ -538,8 +921,8 @@ where
/// are precomputed in the constant arrays FROB_T1 and FROB_T2
pub fn frob(self, n: usize) -> Fp6<T> {
let n = n % 6;
let frob_t1 = Fp6::<T>::FROB_T[0][n];
let frob_t2 = Fp6::<T>::FROB_T[1][n];
let frob_t1 = Fp2::<T>::FROB_T[0][n];
let frob_t2 = Fp2::<T>::FROB_T[1][n];
if n % 2 != 0 {
Fp6 {
@ -579,7 +962,7 @@ where
/// (x_n)_m = (x^(p^n))^(p^m) = x^(p^n * p^m) = x^(p^(n+m)) = x_{n+m}
/// By Galois Theory, given x: Fp6, the product
/// phi = x_0 * x_1 * x_2 * x_3 * x_4 * x_5
/// lands in Fp, and hence the inverse of x is given by
/// lands in BN254, and hence the inverse of x is given by
/// (x_1 * x_2 * x_3 * x_4 * x_5) / phi
/// We can save compute by rearranging the numerator:
/// (x_1 * x_3) * x_5 * (x_1 * x_3)_1
@ -612,8 +995,8 @@ where
}
}
/// The degree 2 field extension Fp12 over Fp6 is given by adjoining z, where z^2 = t.
/// It thus has basis 1, z over Fp6
/// The degree 2 field extension Fp12 over Fp6 is given by
/// adjoining z, where z^2 = t. It thus has basis 1, z over Fp6
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Fp12<T>
where
@ -641,7 +1024,7 @@ where
/// By Galois Theory, given x: Fp12, the product
/// phi = Prod_{i=0}^11 x_i
/// lands in Fp, and hence the inverse of x is given by
/// lands in BN254, and hence the inverse of x is given by
/// (Prod_{i=1}^11 x_i) / phi
/// The 6th Frob map is nontrivial but leaves Fp6 fixed and hence must be the conjugate:
/// x_6 = (a + bz)_6 = a - bz = x.conj()
@ -665,7 +1048,7 @@ where
impl<T> Distribution<Fp12<T>> for Standard
where
T: Distribution<T> + FieldExt,
T: FieldExt,
Fp2<T>: Adj,
Standard: Distribution<T>,
{
@ -773,7 +1156,7 @@ where
let n = n % 12;
Fp12 {
z0: self.z0.frob(n),
z1: self.z1.frob(n).scale(Fp6::<T>::FROB_Z[n]),
z1: self.z1.frob(n).scale(Fp2::<T>::FROB_Z[n]),
}
}
}
@ -791,6 +1174,13 @@ where
}
}
// trait Stack {
// fn on_stack(self) -> Vec<U256>;
// }
pub trait Stack {
fn on_stack(self) -> Vec<U256>;
}
impl Stack for Fp12<BN254> {
fn on_stack(self) -> Vec<U256> {
let f: [U256; 12] = unsafe { transmute(self) };
f.into_iter().collect()
}
}