mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-17 05:03:07 +00:00
Secp256K1 scalar field
This commit is contained in:
parent
db464f739e
commit
869a5860f4
@ -2,3 +2,4 @@ pub mod curve_adds;
|
||||
pub mod curve_multiplication;
|
||||
pub mod curve_summation;
|
||||
pub mod curve_types;
|
||||
//pub mod secp256k1_curve;
|
||||
81
src/curve/secp256k1_curve.rs
Normal file
81
src/curve/secp256k1_curve.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use crate::curve::curve_types::{AffinePoint, Curve};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::secp256k1_base::Secp256K1Base;
|
||||
use crate::field::secp256k1_scalar::Secp256K1Scalar;
|
||||
|
||||
// Parameters taken from the implementation of Bls12-377 in Zexe found here:
|
||||
// https://github.com/scipr-lab/zexe/blob/master/algebra/src/curves/bls12_377/g1.rs
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Secp256K1;
|
||||
|
||||
impl Curve for Bls12377 {
|
||||
type BaseField = Bls12377Base;
|
||||
type ScalarField = Bls12377Scalar;
|
||||
|
||||
const A: Bls12377Base = Bls12377Base::ZERO;
|
||||
const B: Bls12377Base = Bls12377Base::ONE;
|
||||
const GENERATOR_AFFINE: AffinePoint<Self> = AffinePoint {
|
||||
x: BLS12_377_GENERATOR_X,
|
||||
y: BLS12_377_GENERATOR_Y,
|
||||
zero: false,
|
||||
};
|
||||
}
|
||||
|
||||
/// 81937999373150964239938255573465948239988671502647976594219695644855304257327692006745978603320413799295628339695
|
||||
const BLS12_377_GENERATOR_X: Bls12377Base = Bls12377Base {
|
||||
limbs: [2742467569752756724, 14217256487979144792, 6635299530028159197, 8509097278468658840,
|
||||
14518893593143693938, 46181716169194829]
|
||||
};
|
||||
|
||||
/// 241266749859715473739788878240585681733927191168601896383759122102112907357779751001206799952863815012735208165030
|
||||
const BLS12_377_GENERATOR_Y: Bls12377Base = Bls12377Base {
|
||||
limbs: [9336971515457667571, 28021381849722296, 18085035374859187530, 14013031479170682136,
|
||||
3369780711397861396, 35370409237953649]
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{blake_hash_usize_to_curve, Bls12377, Bls12377Scalar, Curve, Field, ProjectivePoint};
|
||||
|
||||
#[test]
|
||||
fn test_double_affine() {
|
||||
for i in 0..100 {
|
||||
let p = blake_hash_usize_to_curve::<Bls12377>(i);
|
||||
assert_eq!(
|
||||
p.double(),
|
||||
p.to_projective().double().to_affine());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_naive_multiplication() {
|
||||
let g = Bls12377::GENERATOR_PROJECTIVE;
|
||||
let ten = Bls12377Scalar::from_canonical_u64(10);
|
||||
let product = mul_naive(ten, g);
|
||||
let sum = g + g + g + g + g + g + g + g + g + g;
|
||||
assert_eq!(product, sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_g1_multiplication() {
|
||||
let lhs = Bls12377Scalar::from_canonical([11111111, 22222222, 33333333, 44444444]);
|
||||
assert_eq!(Bls12377::convert(lhs) * Bls12377::GENERATOR_PROJECTIVE, mul_naive(lhs, Bls12377::GENERATOR_PROJECTIVE));
|
||||
}
|
||||
|
||||
/// A simple, somewhat inefficient implementation of multiplication which is used as a reference
|
||||
/// for correctness.
|
||||
fn mul_naive(lhs: Bls12377Scalar, rhs: ProjectivePoint<Bls12377>) -> ProjectivePoint<Bls12377> {
|
||||
let mut g = rhs;
|
||||
let mut sum = ProjectivePoint::ZERO;
|
||||
for limb in lhs.to_canonical().iter() {
|
||||
for j in 0..64 {
|
||||
if (limb >> j & 1u64) != 0u64 {
|
||||
sum = sum + g;
|
||||
}
|
||||
g = g.double();
|
||||
}
|
||||
}
|
||||
sum
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,8 @@ pub(crate) mod interpolation;
|
||||
mod inversion;
|
||||
pub(crate) mod packable;
|
||||
pub(crate) mod packed_field;
|
||||
pub mod secp256k1;
|
||||
pub mod secp256k1_base;
|
||||
pub mod secp256k1_scalar;
|
||||
|
||||
#[cfg(target_feature = "avx2")]
|
||||
pub(crate) mod packed_avx2;
|
||||
|
||||
@ -88,7 +88,7 @@ impl Field for Secp256K1Base {
|
||||
// Sage: `g = GF(p).multiplicative_generator()`
|
||||
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([5, 0, 0, 0]);
|
||||
|
||||
// Sage: `g_2 = g^((p - 1) / 2)`
|
||||
// Sage: `g_2 = power_mod(g, (p - 1) // 2), p)`
|
||||
const POWER_OF_TWO_GENERATOR: Self = Self::NEG_ONE;
|
||||
|
||||
const BITS: usize = 256;
|
||||
253
src/field/secp256k1_scalar.rs
Normal file
253
src/field/secp256k1_scalar.rs
Normal file
@ -0,0 +1,253 @@
|
||||
use std::convert::TryInto;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
|
||||
use itertools::Itertools;
|
||||
use num::bigint::{BigUint, RandBigInt};
|
||||
use num::{Integer, One};
|
||||
use rand::Rng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::goldilocks_field::GoldilocksField;
|
||||
|
||||
/// The base field of the secp256k1 elliptic curve.
|
||||
///
|
||||
/// Its order is
|
||||
/// ```ignore
|
||||
/// P = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
|
||||
/// = 115792089237316195423570985008687907852837564279074904382605163141518161494337
|
||||
/// = 2**256 - 432420386565659656852420866394968145599
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||
pub struct Secp256K1Scalar(pub [u64; 4]);
|
||||
|
||||
fn biguint_from_array(arr: [u64; 4]) -> BigUint {
|
||||
BigUint::from_slice(&[
|
||||
arr[0] as u32,
|
||||
(arr[0] >> 32) as u32,
|
||||
arr[1] as u32,
|
||||
(arr[1] >> 32) as u32,
|
||||
arr[2] as u32,
|
||||
(arr[2] >> 32) as u32,
|
||||
arr[3] as u32,
|
||||
(arr[3] >> 32) as u32,
|
||||
])
|
||||
}
|
||||
|
||||
impl Default for Secp256K1Scalar {
|
||||
fn default() -> Self {
|
||||
Self::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Secp256K1Scalar {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.to_biguint() == other.to_biguint()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Secp256K1Scalar {}
|
||||
|
||||
impl Hash for Secp256K1Scalar {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.to_biguint().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Secp256K1Scalar {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.to_biguint(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Secp256K1Scalar {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Debug::fmt(&self.to_biguint(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Secp256K1Scalar {
|
||||
// TODO: fix
|
||||
type PrimeField = GoldilocksField;
|
||||
|
||||
const ZERO: Self = Self([0; 4]);
|
||||
const ONE: Self = Self([1, 0, 0, 0]);
|
||||
const TWO: Self = Self([2, 0, 0, 0]);
|
||||
const NEG_ONE: Self = Self([
|
||||
0xBFD25E8CD0364140,
|
||||
0xBAAEDCE6AF48A03B,
|
||||
0xFFFFFFFFFFFFFC2F,
|
||||
0xFFFFFFFFFFFFFFFF
|
||||
]);
|
||||
|
||||
// TODO: fix
|
||||
const CHARACTERISTIC: u64 = 0;
|
||||
|
||||
const TWO_ADICITY: usize = 6;
|
||||
|
||||
// Sage: `g = GF(p).multiplicative_generator()`
|
||||
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([7, 0, 0, 0]);
|
||||
|
||||
// Sage: `g_2 = power_mod(g, (p - 1) // 2^6), p)`
|
||||
// 5480320495727936603795231718619559942670027629901634955707709633242980176626
|
||||
const POWER_OF_TWO_GENERATOR: Self = Self([
|
||||
0x992f4b5402b052f2,
|
||||
0x98BDEAB680756045,
|
||||
0xDF9879A3FBC483A8,
|
||||
0xC1DC060E7A91986,
|
||||
]);
|
||||
|
||||
const BITS: usize = 256;
|
||||
|
||||
fn order() -> BigUint {
|
||||
BigUint::from_slice(&[
|
||||
0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFC2F, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF
|
||||
])
|
||||
}
|
||||
|
||||
fn try_inverse(&self) -> Option<Self> {
|
||||
if self.is_zero() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Fermat's Little Theorem
|
||||
Some(self.exp_biguint(&(Self::order() - BigUint::one() - BigUint::one())))
|
||||
}
|
||||
|
||||
fn to_biguint(&self) -> BigUint {
|
||||
let mut result = biguint_from_array(self.0);
|
||||
if result >= Self::order() {
|
||||
result -= Self::order();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn from_biguint(val: BigUint) -> Self {
|
||||
Self(
|
||||
val.to_u64_digits()
|
||||
.into_iter()
|
||||
.pad_using(4, |_| 0)
|
||||
.collect::<Vec<_>>()[..]
|
||||
.try_into()
|
||||
.expect("error converting to u64 array"),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_canonical_u64(n: u64) -> Self {
|
||||
Self([n, 0, 0, 0])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_noncanonical_u128(n: u128) -> Self {
|
||||
Self([n as u64, (n >> 64) as u64, 0, 0])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_noncanonical_u96(n: (u64, u32)) -> Self {
|
||||
Self([n.0, n.1 as u64, 0, 0])
|
||||
}
|
||||
|
||||
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
|
||||
Self::from_biguint(rng.gen_biguint_below(&Self::order()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Secp256K1Scalar {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
if self.is_zero() {
|
||||
Self::ZERO
|
||||
} else {
|
||||
Self::from_biguint(Self::order() - self.to_biguint())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Secp256K1Scalar {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
let mut result = self.to_biguint() + rhs.to_biguint();
|
||||
if result >= Self::order() {
|
||||
result -= Self::order();
|
||||
}
|
||||
Self::from_biguint(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Secp256K1Scalar {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for Secp256K1Scalar {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::ZERO, |acc, x| acc + x)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Secp256K1Scalar {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
||||
fn sub(self, rhs: Self) -> Self {
|
||||
self + -rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Secp256K1Scalar {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Secp256K1Scalar {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
Self::from_biguint((self.to_biguint() * rhs.to_biguint()).mod_floor(&Self::order()))
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Secp256K1Scalar {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, rhs: Self) {
|
||||
*self = *self * rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl Product for Secp256K1Scalar {
|
||||
#[inline]
|
||||
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div for Secp256K1Scalar {
|
||||
type Output = Self;
|
||||
|
||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
self * rhs.inverse()
|
||||
}
|
||||
}
|
||||
|
||||
impl DivAssign for Secp256K1Scalar {
|
||||
fn div_assign(&mut self, rhs: Self) {
|
||||
*self = *self / rhs;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user