plonky2/field/src/secp256k1_scalar.rs

280 lines
6.7 KiB
Rust
Raw Normal View History

use alloc::vec::Vec;
use core::fmt::{self, Debug, Display, Formatter};
use core::hash::{Hash, Hasher};
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2021-10-05 18:02:08 -07:00
2021-10-05 21:32:23 -07:00
use itertools::Itertools;
2022-08-06 11:35:32 -04:00
use num::bigint::BigUint;
2021-10-06 11:09:51 -07:00
use num::{Integer, One};
2021-10-05 18:02:08 -07:00
use serde::{Deserialize, Serialize};
use crate::types::{Field, PrimeField, Sample};
2021-10-05 18:02:08 -07:00
2021-10-06 11:44:02 -07:00
/// The base field of the secp256k1 elliptic curve.
2021-10-05 18:02:08 -07:00
///
/// Its order is
/// ```ignore
2021-10-28 19:54:39 -07:00
/// P = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
/// = 115792089237316195423570985008687907852837564279074904382605163141518161494337
/// = 2**256 - 432420386565659656852420866394968145599
2021-10-05 18:02:08 -07:00
/// ```
#[derive(Copy, Clone, Serialize, Deserialize)]
2021-10-28 19:54:39 -07:00
pub struct Secp256K1Scalar(pub [u64; 4]);
2021-10-06 11:20:11 -07:00
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,
])
}
2021-10-05 18:02:08 -07:00
2021-10-28 19:54:39 -07:00
impl Default for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn default() -> Self {
Self::ZERO
}
}
2021-10-28 19:54:39 -07:00
impl PartialEq for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn eq(&self, other: &Self) -> bool {
self.to_canonical_biguint() == other.to_canonical_biguint()
2021-10-05 18:02:08 -07:00
}
}
2021-10-28 19:54:39 -07:00
impl Eq for Secp256K1Scalar {}
2021-10-05 18:02:08 -07:00
2021-10-28 19:54:39 -07:00
impl Hash for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn hash<H: Hasher>(&self, state: &mut H) {
self.to_canonical_biguint().hash(state)
2021-10-05 18:02:08 -07:00
}
}
2021-10-28 19:54:39 -07:00
impl Display for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.to_canonical_biguint(), f)
2021-10-05 18:02:08 -07:00
}
}
2021-10-28 19:54:39 -07:00
impl Debug for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.to_canonical_biguint(), f)
2021-10-05 18:02:08 -07:00
}
}
impl Sample for Secp256K1Scalar {
#[inline]
fn sample<R>(rng: &mut R) -> Self
where
R: rand::RngCore + ?Sized,
{
use num::bigint::RandBigInt;
Self::from_noncanonical_biguint(rng.gen_biguint_below(&Self::order()))
}
}
2021-10-28 19:54:39 -07:00
impl Field for Secp256K1Scalar {
2021-10-06 11:20:11 -07:00
const ZERO: Self = Self([0; 4]);
const ONE: Self = Self([1, 0, 0, 0]);
const TWO: Self = Self([2, 0, 0, 0]);
2021-10-05 21:32:18 -07:00
const NEG_ONE: Self = Self([
2021-10-28 19:54:39 -07:00
0xBFD25E8CD0364140,
0xBAAEDCE6AF48A03B,
2021-11-30 15:00:12 -08:00
0xFFFFFFFFFFFFFFFE,
2021-11-10 11:49:50 -08:00
0xFFFFFFFFFFFFFFFF,
2021-10-05 21:32:18 -07:00
]);
2021-10-05 18:02:08 -07:00
2021-10-28 19:54:39 -07:00
const TWO_ADICITY: usize = 6;
2021-12-14 17:12:14 +01:00
const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY;
2021-10-05 22:01:18 -07:00
2021-10-28 19:54:39 -07:00
// 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,
]);
2021-10-05 18:02:08 -07:00
2021-11-10 11:49:30 -08:00
const BITS: usize = 256;
2021-10-05 18:02:08 -07:00
fn order() -> BigUint {
2021-10-05 21:32:18 -07:00
BigUint::from_slice(&[
2021-11-30 15:00:12 -08:00
0xD0364141, 0xBFD25E8C, 0xAF48A03B, 0xBAAEDCE6, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
2021-11-10 11:49:50 -08:00
0xFFFFFFFF,
2021-10-05 21:32:18 -07:00
])
2021-10-05 18:02:08 -07:00
}
2021-12-14 17:12:14 +01:00
fn characteristic() -> BigUint {
Self::order()
}
2021-10-05 18:02:08 -07:00
fn try_inverse(&self) -> Option<Self> {
if self.is_zero() {
return None;
}
// Fermat's Little Theorem
2021-10-05 21:32:18 -07:00
Some(self.exp_biguint(&(Self::order() - BigUint::one() - BigUint::one())))
2021-10-05 18:02:08 -07:00
}
fn from_noncanonical_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"),
)
}
2021-10-05 18:02:08 -07:00
#[inline]
fn from_canonical_u64(n: u64) -> Self {
2021-10-06 11:20:11 -07:00
Self([n, 0, 0, 0])
2021-10-05 18:02:08 -07:00
}
#[inline]
fn from_noncanonical_u128(n: u128) -> Self {
2021-10-06 11:20:11 -07:00
Self([n as u64, (n >> 64) as u64, 0, 0])
2021-10-05 18:02:08 -07:00
}
#[inline]
fn from_noncanonical_u96(n: (u64, u32)) -> Self {
2021-10-06 11:20:11 -07:00
Self([n.0, n.1 as u64, 0, 0])
2021-10-05 18:02:08 -07:00
}
2023-07-04 17:21:27 +08:00
fn from_noncanonical_i64(n: i64) -> Self {
let f = Self::from_canonical_u64(n.unsigned_abs());
2023-07-11 12:05:22 -07:00
if n < 0 {
-f
} else {
f
}
2023-07-04 17:21:27 +08:00
}
fn from_noncanonical_u64(n: u64) -> Self {
Self::from_canonical_u64(n)
}
2021-10-05 18:02:08 -07:00
}
impl PrimeField for Secp256K1Scalar {
fn to_canonical_biguint(&self) -> BigUint {
let mut result = biguint_from_array(self.0);
if result >= Self::order() {
result -= Self::order();
}
result
}
}
2021-10-28 19:54:39 -07:00
impl Neg for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
type Output = Self;
#[inline]
fn neg(self) -> Self {
if self.is_zero() {
Self::ZERO
} else {
Self::from_noncanonical_biguint(Self::order() - self.to_canonical_biguint())
2021-10-05 18:02:08 -07:00
}
}
}
2021-10-28 19:54:39 -07:00
impl Add for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
let mut result = self.to_canonical_biguint() + rhs.to_canonical_biguint();
2021-10-06 11:34:50 -07:00
if result >= Self::order() {
2021-10-05 21:32:18 -07:00
result -= Self::order();
2021-10-05 18:02:08 -07:00
}
Self::from_noncanonical_biguint(result)
2021-10-05 18:02:08 -07:00
}
}
2021-10-28 19:54:39 -07:00
impl AddAssign for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
2021-10-28 19:54:39 -07:00
impl Sum for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, |acc, x| acc + x)
}
}
2021-10-28 19:54:39 -07:00
impl Sub for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
type Output = Self;
#[inline]
#[allow(clippy::suspicious_arithmetic_impl)]
fn sub(self, rhs: Self) -> Self {
2021-10-06 11:34:50 -07:00
self + -rhs
2021-10-05 18:02:08 -07:00
}
}
2021-10-28 19:54:39 -07:00
impl SubAssign for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
2021-10-28 19:54:39 -07:00
impl Mul for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
Self::from_noncanonical_biguint(
(self.to_canonical_biguint() * rhs.to_canonical_biguint()).mod_floor(&Self::order()),
)
2021-10-05 18:02:08 -07:00
}
}
2021-10-28 19:54:39 -07:00
impl MulAssign for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
2021-10-28 19:54:39 -07:00
impl Product for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
#[inline]
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.reduce(|acc, x| acc * x).unwrap_or(Self::ONE)
}
}
2021-10-28 19:54:39 -07:00
impl Div for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
type Output = Self;
#[allow(clippy::suspicious_arithmetic_impl)]
fn div(self, rhs: Self) -> Self::Output {
self * rhs.inverse()
}
}
2021-10-28 19:54:39 -07:00
impl DivAssign for Secp256K1Scalar {
2021-10-05 18:02:08 -07:00
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
2021-10-06 11:20:11 -07:00
}
2021-11-30 15:00:12 -08:00
#[cfg(test)]
mod tests {
use crate::test_field_arithmetic;
test_field_arithmetic!(crate::secp256k1_scalar::Secp256K1Scalar);
2021-11-30 15:00:12 -08:00
}