mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-12 01:55:48 +00:00
Add multiplicative generator and other useful constants.
This commit is contained in:
parent
9aceb63e7e
commit
b1f392ac99
@ -36,8 +36,9 @@ pub fn prime_field(
|
|||||||
|
|
||||||
// We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
|
// We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
|
||||||
// nonresidue.
|
// nonresidue.
|
||||||
let generator: Option<BigUint> = fetch_attr("PrimeFieldGenerator", &ast.attrs)
|
let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs)
|
||||||
.map(|i| i.parse().expect("PrimeFieldGenerator must be a number."));
|
.expect("Please supply a PrimeFieldGenerator attribute")
|
||||||
|
.parse().expect("PrimeFieldGenerator should be a number");
|
||||||
|
|
||||||
// The arithmetic in this library only works if the modulus*2 is smaller than the backing
|
// The arithmetic in this library only works if the modulus*2 is smaller than the backing
|
||||||
// representation. Compute the number of limbs we need.
|
// representation. Compute the number of limbs we need.
|
||||||
@ -256,7 +257,8 @@ fn prime_field_repr_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn biguint_to_u64_vec(
|
fn biguint_to_u64_vec(
|
||||||
mut v: BigUint
|
mut v: BigUint,
|
||||||
|
limbs: usize
|
||||||
) -> Vec<u64>
|
) -> Vec<u64>
|
||||||
{
|
{
|
||||||
let m = BigUint::one() << 64;
|
let m = BigUint::one() << 64;
|
||||||
@ -267,6 +269,10 @@ fn biguint_to_u64_vec(
|
|||||||
v = v >> 64;
|
v = v >> 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ret.len() < limbs {
|
||||||
|
ret.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,7 +328,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
repr: &syn::Ident,
|
repr: &syn::Ident,
|
||||||
modulus: BigUint,
|
modulus: BigUint,
|
||||||
limbs: usize,
|
limbs: usize,
|
||||||
generator: Option<BigUint>
|
generator: BigUint
|
||||||
) -> quote::Tokens
|
) -> quote::Tokens
|
||||||
{
|
{
|
||||||
let modulus_num_bits = biguint_num_bits(modulus.clone());
|
let modulus_num_bits = biguint_num_bits(modulus.clone());
|
||||||
@ -332,19 +338,23 @@ fn prime_field_constants_and_sqrt(
|
|||||||
let r = (BigUint::one() << (limbs * 64)) % &modulus;
|
let r = (BigUint::one() << (limbs * 64)) % &modulus;
|
||||||
|
|
||||||
// modulus - 1 = 2^s * t
|
// modulus - 1 = 2^s * t
|
||||||
let mut s = 0;
|
let mut s: usize = 0;
|
||||||
let mut t = &modulus - BigUint::from_str("1").unwrap();
|
let mut t = &modulus - BigUint::from_str("1").unwrap();
|
||||||
while t.is_even() {
|
while t.is_even() {
|
||||||
t = t >> 1;
|
t = t >> 1;
|
||||||
s += 1;
|
s += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute root of unity given the generator
|
||||||
|
let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus, limbs);
|
||||||
|
let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs);
|
||||||
|
|
||||||
let sqrt_impl =
|
let sqrt_impl =
|
||||||
if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() {
|
if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() {
|
||||||
let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2);
|
let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs);
|
||||||
|
|
||||||
// Compute -R as (m - r)
|
// Compute -R as (m - r)
|
||||||
let rneg = biguint_to_u64_vec(&modulus - &r);
|
let rneg = biguint_to_u64_vec(&modulus - &r, limbs);
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
impl ::ff::SqrtField for #name {
|
impl ::ff::SqrtField for #name {
|
||||||
@ -368,11 +378,9 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
|
} else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
|
||||||
let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1);
|
let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs);
|
||||||
let generator = generator.expect("PrimeFieldGenerator attribute should be provided; should be a generator of order p - 1 and quadratic nonresidue.");
|
let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs);
|
||||||
let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus);
|
let t = biguint_to_u64_vec(t.clone(), limbs);
|
||||||
let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1);
|
|
||||||
let t = biguint_to_u64_vec(t.clone());
|
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
impl ::ff::SqrtField for #name {
|
impl ::ff::SqrtField for #name {
|
||||||
@ -425,10 +433,10 @@ fn prime_field_constants_and_sqrt(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Compute R^2 mod m
|
// Compute R^2 mod m
|
||||||
let r2 = biguint_to_u64_vec((&r * &r) % &modulus);
|
let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs);
|
||||||
|
|
||||||
let r = biguint_to_u64_vec(r);
|
let r = biguint_to_u64_vec(r, limbs);
|
||||||
let modulus = biguint_to_u64_vec(modulus);
|
let modulus = biguint_to_u64_vec(modulus, limbs);
|
||||||
|
|
||||||
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
|
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
|
||||||
let mut inv = 1u64;
|
let mut inv = 1u64;
|
||||||
@ -458,6 +466,16 @@ fn prime_field_constants_and_sqrt(
|
|||||||
/// -(m^{-1} mod m) mod m
|
/// -(m^{-1} mod m) mod m
|
||||||
const INV: u64 = #inv;
|
const INV: u64 = #inv;
|
||||||
|
|
||||||
|
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
|
||||||
|
/// nonresidue.
|
||||||
|
const GENERATOR: #repr = #repr(#generator);
|
||||||
|
|
||||||
|
/// 2^s * t = MODULUS - 1 with t odd
|
||||||
|
const S: usize = #s;
|
||||||
|
|
||||||
|
/// 2^s root of unity computed by GENERATOR^t
|
||||||
|
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity);
|
||||||
|
|
||||||
#sqrt_impl
|
#sqrt_impl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -736,6 +754,18 @@ fn prime_field_impl(
|
|||||||
fn capacity() -> u32 {
|
fn capacity() -> u32 {
|
||||||
Self::num_bits() - 1
|
Self::num_bits() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn multiplicative_generator() -> Self {
|
||||||
|
#name(GENERATOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn s() -> usize {
|
||||||
|
S
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_of_unity() -> Self {
|
||||||
|
#name(ROOT_OF_UNITY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::ff::Field for #name {
|
impl ::ff::Field for #name {
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -147,6 +147,17 @@ pub trait PrimeField: Field
|
|||||||
/// Returns how many bits of information can be reliably stored in the
|
/// Returns how many bits of information can be reliably stored in the
|
||||||
/// field element.
|
/// field element.
|
||||||
fn capacity() -> u32;
|
fn capacity() -> u32;
|
||||||
|
|
||||||
|
/// Returns the multiplicative generator of `char()` - 1 order. This element
|
||||||
|
/// must also be quadratic nonresidue.
|
||||||
|
fn multiplicative_generator() -> Self;
|
||||||
|
|
||||||
|
/// Returns s such that 2^s * t = `char()` - 1 with t odd.
|
||||||
|
fn s() -> usize;
|
||||||
|
|
||||||
|
/// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()`
|
||||||
|
/// by t.
|
||||||
|
fn root_of_unity() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BitIterator<E> {
|
pub struct BitIterator<E> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user