abstraction

This commit is contained in:
Dmitry Vagner 2023-04-26 17:21:52 -07:00
parent 537debdc2e
commit 6599c90a6e
3 changed files with 101 additions and 71 deletions

View File

@ -5,32 +5,32 @@ use rand::Rng;
use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254};
// The curve consists of pairs (x, y): (BN254, BN254) | y^2 = x^3 + 2
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Curve {
pub x: BN254,
pub y: BN254,
pub struct Curve<T>
where
T: FieldExt,
{
pub x: T,
pub y: T,
}
// The curve is cyclic with generator (1, 2)
pub const CURVE_GENERATOR: Curve = {
Curve {
x: BN254 { val: U256::one() },
y: BN254 {
val: U256([2, 0, 0, 0]),
},
impl<T: FieldExt> Curve<T> {
pub fn unit() -> Self {
Curve {
x: T::UNIT,
y: T::UNIT,
}
}
};
}
/// Standard addition formula for elliptic curves, restricted to the cases
/// where neither inputs nor output would ever be the identity O. source:
/// https://en.wikipedia.org/wiki/Elliptic_curve#Algebraic_interpretation
impl Add for Curve {
impl<T: FieldExt> Add for Curve<T> {
type Output = Self;
fn add(self, other: Self) -> Self {
let m = if self == other {
BN254::new(3) * self.x * self.x / (BN254::new(2) * self.y)
T::new(3) * self.x * self.x / (T::new(2) * self.y)
} else {
(other.y - self.y) / (other.x - self.x)
};
@ -42,8 +42,8 @@ impl Add for Curve {
}
}
impl Neg for Curve {
type Output = Curve;
impl<T: FieldExt> Neg for Curve<T> {
type Output = Curve<T>;
fn neg(self) -> Self {
Curve {
@ -53,37 +53,48 @@ impl Neg for Curve {
}
}
impl Mul<i32> for Curve {
type Output = Curve;
fn mul(self, other: i32) -> Self {
let mut result: Curve = self;
if other.is_negative() {
result = -result;
}
let mut multiplier = result;
let mut exp = other.abs() as usize;
while exp > 0 {
if exp % 2 == 1 {
result = result + multiplier;
}
exp >>= 1;
multiplier = multiplier + multiplier;
}
result
}
pub trait CurveGroup {
const GENERATOR: Self;
}
// The twisted curve consists of pairs (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i)
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct TwistedCurve {
pub x: Fp2<BN254>,
pub y: Fp2<BN254>,
/// The BN curve consists of pairs
/// (x, y): (BN254, BN254) | y^2 = x^3 + 2
// with generator given by (1, 2)
impl CurveGroup for Curve<BN254> {
const GENERATOR: Curve<BN254> = Curve {
x: BN254 { val: U256::one() },
y: BN254 {
val: U256([2, 0, 0, 0]),
},
};
}
// The twisted curve is cyclic with generator (x, y) as follows
pub const TWISTED_GENERATOR: TwistedCurve = {
TwistedCurve {
// impl<T: FieldExt: Add> Mul<i32> for Curve {
// type Output = Curve;
// fn mul(self, other: i32) -> Self {
// let mut result: Curve = self;
// if other.is_negative() {
// result = -result;
// }
// let mut multiplier = result;
// let mut exp = other.unsigned_abs() as usize;
// while exp > 0 {
// if exp % 2 == 1 {
// result = result + multiplier;
// }
// exp >>= 1;
// multiplier = multiplier + multiplier;
// }
// result
// }
// }
/// The twisted curve consists of pairs
/// (x, y): (Fp2<BN254>, Fp2<BN254>) | y^2 = x^3 + 3/(9 + i)
/// with generator given as follows
impl CurveGroup for Curve<Fp2<BN254>> {
const GENERATOR: Curve<Fp2<BN254>> = Curve {
x: Fp2 {
re: BN254 {
val: U256([
@ -120,11 +131,11 @@ pub const TWISTED_GENERATOR: TwistedCurve = {
]),
},
},
}
};
};
}
// The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element
pub fn tate(p: Curve, q: TwistedCurve) -> Fp12<BN254> {
pub fn tate(p: Curve<BN254>, q: Curve<Fp2<BN254>>) -> Fp12<BN254> {
let miller_output = miller_loop(p, q);
final_exponent(miller_output)
}
@ -132,7 +143,7 @@ pub fn tate(p: Curve, q: TwistedCurve) -> Fp12<BN254> {
/// Standard code for miller loop, can be found on page 99 at this url:
/// https://static1.squarespace.com/static/5fdbb09f31d71c1227082339/t/5ff394720493bd28278889c6/1609798774687/PairingsForBeginners.pdf#page=107
/// where EXP is a hardcoding of the array of Booleans that the loop traverses
pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12<BN254> {
pub fn miller_loop(p: Curve<BN254>, q: Curve<Fp2<BN254>>) -> Fp12<BN254> {
let mut r = p;
let mut acc: Fp12<BN254> = Fp12::<BN254>::UNIT;
let mut line: Fp12<BN254>;
@ -151,14 +162,14 @@ pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12<BN254> {
}
/// The sloped line function for doubling a point
pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12<BN254> {
pub fn tangent(p: Curve<BN254>, q: Curve<Fp2<BN254>>) -> Fp12<BN254> {
let cx = -BN254::new(3) * p.x * p.x;
let cy = BN254::new(2) * p.y;
sparse_embed(p.y * p.y - BN254::new(9), q.x * cx, q.y * cy)
}
/// The sloped line function for adding two points
pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12<BN254> {
pub fn cord(p1: Curve<BN254>, p2: Curve<BN254>, q: Curve<Fp2<BN254>>) -> Fp12<BN254> {
let cx = p2.y - p1.y;
let cy = p1.x - p2.x;
sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x * cx, q.y * cy)

View File

@ -4,14 +4,12 @@ use anyhow::Result;
use ethereum_types::U256;
use rand::Rng;
use crate::bn254_pairing::{
final_exponent, gen_fp12_sparse, miller_loop, CURVE_GENERATOR, TWISTED_GENERATOR,
};
use crate::bn254_pairing::{final_exponent, gen_fp12_sparse, miller_loop, Curve, CurveGroup};
use crate::cpu::kernel::interpreter::{
run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization,
};
use crate::cpu::kernel::tests::u256ify;
use crate::extension_tower::{FieldExt, Fp12, Fp6, Stack, BN254};
use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254};
use crate::memory::segments::Segment::BnPairing;
fn extract_stack(interpreter: Interpreter<'static>) -> Vec<U256> {
@ -204,8 +202,8 @@ fn test_bn_final_exponent() -> Result<()> {
}
fn pairing_input() -> Vec<U256> {
let curve_gen: [U256; 2] = unsafe { transmute(CURVE_GENERATOR) };
let twisted_gen: [U256; 4] = unsafe { transmute(TWISTED_GENERATOR) };
let curve_gen: [U256; 2] = unsafe { transmute(Curve::<BN254>::GENERATOR) };
let twisted_gen: [U256; 4] = unsafe { transmute(Curve::<Fp2<BN254>>::GENERATOR) };
let mut input = curve_gen.to_vec();
input.extend_from_slice(&twisted_gen);
input
@ -225,7 +223,7 @@ fn test_bn_miller() -> Result<()> {
};
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 expected = miller_loop(Curve::<BN254>::GENERATOR, Curve::<Fp2<BN254>>::GENERATOR).on_stack();
assert_eq!(output, expected);

View File

@ -7,6 +7,7 @@ use rand::Rng;
pub trait FieldExt:
Copy
+ std::cmp::PartialEq
+ std::ops::Add<Output = Self>
+ std::ops::Neg<Output = Self>
+ std::ops::Sub<Output = Self>
@ -15,6 +16,7 @@ pub trait FieldExt:
{
const ZERO: Self;
const UNIT: Self;
fn new(val: usize) -> Self;
fn inv(self) -> Self;
}
@ -30,14 +32,6 @@ pub struct BN254 {
pub val: U256,
}
impl BN254 {
pub fn new(val: usize) -> BN254 {
BN254 {
val: U256::from(val),
}
}
}
impl Distribution<BN254> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BN254 {
let xs = rng.gen::<[u64; 4]>();
@ -91,6 +85,11 @@ impl Mul for BN254 {
impl FieldExt for BN254 {
const ZERO: Self = BN254 { val: U256::zero() };
const UNIT: Self = BN254 { val: U256::one() };
fn new(val: usize) -> BN254 {
BN254 {
val: U256::from(val),
}
}
fn inv(self) -> BN254 {
let exp = BN_BASE - 2;
let mut current = self;
@ -131,12 +130,6 @@ pub struct BLS381 {
}
impl BLS381 {
pub fn new(val: usize) -> BLS381 {
BLS381 {
val: U512::from(val),
}
}
pub fn lo(self) -> U256 {
U256(self.val.0[..4].try_into().unwrap())
}
@ -234,6 +227,11 @@ impl Mul for BLS381 {
impl FieldExt for BLS381 {
const ZERO: Self = BLS381 { val: U512::zero() };
const UNIT: Self = BLS381 { val: U512::one() };
fn new(val: usize) -> BLS381 {
BLS381 {
val: U512::from(val),
}
}
fn inv(self) -> BLS381 {
let exp = BLS_BASE - 2;
let mut current = self;
@ -365,6 +363,14 @@ impl<T: FieldExt> FieldExt for Fp2<T> {
re: T::UNIT,
im: T::ZERO,
};
fn new(val: usize) -> Fp2<T> {
Fp2 {
re: T::new(val),
im: T::ZERO,
}
}
/// The inverse of z is given by z'/||z||^2 since ||z||^2 = zz'
fn inv(self) -> Fp2<T> {
let norm_sq = self.norm_sq();
@ -974,6 +980,14 @@ where
t1: Fp2::<T>::ZERO,
t2: Fp2::<T>::ZERO,
};
fn new(val: usize) -> Fp6<T> {
Fp6 {
t0: Fp2::<T>::new(val),
t1: Fp2::<T>::ZERO,
t2: Fp2::<T>::ZERO,
}
}
/// Let x_n = x^(p^n) and note that
/// x_0 = x^(p^0) = x^1 = x
@ -1040,6 +1054,13 @@ where
z1: Fp6::<T>::ZERO,
};
fn new(val: usize) -> Fp12<T> {
Fp12 {
z0: Fp6::<T>::new(val),
z1: Fp6::<T>::ZERO,
}
}
/// By Galois Theory, given x: Fp12, the product
/// phi = Prod_{i=0}^11 x_i
/// lands in BN254, and hence the inverse of x is given by