mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-30 20:11:23 +00:00
ff: Add PrimeField::ReprEndianness associated type
This enables generic code to reliably operate on the bits of an encoded field element, by converting them to and from a known (little) endianness. The BitAnd and Shr bounds on PrimeField are now removed, as users can perform these operations themselves as needed.
This commit is contained in:
@@ -11,7 +11,7 @@ repository = "https://github.com/ebfull/ff"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", optional = true }
|
||||
byteorder = { version = "1", default-features = false }
|
||||
ff_derive = { version = "0.6", path = "ff_derive", optional = true }
|
||||
rand_core = { version = "0.5", default-features = false }
|
||||
subtle = { version = "2.2.1", default-features = false, features = ["i128"] }
|
||||
@@ -19,7 +19,7 @@ subtle = { version = "2.2.1", default-features = false, features = ["i128"] }
|
||||
[features]
|
||||
default = ["std"]
|
||||
derive = ["ff_derive"]
|
||||
std = ["byteorder"]
|
||||
std = []
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
@@ -31,6 +31,13 @@ impl FromStr for ReprEndianness {
|
||||
}
|
||||
|
||||
impl ReprEndianness {
|
||||
fn repr_endianness(&self) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
ReprEndianness::Big => quote! {::byteorder::BigEndian},
|
||||
ReprEndianness::Little => quote! {::byteorder::LittleEndian},
|
||||
}
|
||||
}
|
||||
|
||||
fn from_repr(&self, name: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
|
||||
let read_repr = match self {
|
||||
ReprEndianness::Big => quote! {
|
||||
@@ -885,6 +892,7 @@ fn prime_field_impl(
|
||||
let mont_reduce_self_params = mont_reduce_params(quote! {self}, limbs);
|
||||
let mont_reduce_other_params = mont_reduce_params(quote! {other}, limbs);
|
||||
|
||||
let repr_endianness = endianness.repr_endianness();
|
||||
let from_repr_impl = endianness.from_repr(name, limbs);
|
||||
let into_repr_impl = endianness.into_repr(repr, &mont_reduce_self_params, limbs);
|
||||
|
||||
@@ -1117,58 +1125,9 @@ fn prime_field_impl(
|
||||
}
|
||||
}
|
||||
|
||||
impl ::core::ops::BitAnd<u64> for #name {
|
||||
type Output = u64;
|
||||
|
||||
#[inline(always)]
|
||||
fn bitand(mut self, rhs: u64) -> u64 {
|
||||
self.mont_reduce(
|
||||
#mont_reduce_self_params
|
||||
);
|
||||
|
||||
self.0[0] & rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl ::core::ops::Shr<u32> for #name {
|
||||
type Output = #name;
|
||||
|
||||
#[inline(always)]
|
||||
fn shr(mut self, mut n: u32) -> #name {
|
||||
if n as usize >= 64 * #limbs {
|
||||
return Self::from(0);
|
||||
}
|
||||
|
||||
// Convert from Montgomery to native representation.
|
||||
self.mont_reduce(
|
||||
#mont_reduce_self_params
|
||||
);
|
||||
|
||||
while n >= 64 {
|
||||
let mut t = 0;
|
||||
for i in self.0.iter_mut().rev() {
|
||||
::core::mem::swap(&mut t, i);
|
||||
}
|
||||
n -= 64;
|
||||
}
|
||||
|
||||
if n > 0 {
|
||||
let mut t = 0;
|
||||
for i in self.0.iter_mut().rev() {
|
||||
let t2 = *i << (64 - n);
|
||||
*i >>= n;
|
||||
*i |= t;
|
||||
t = t2;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to Montgomery representation
|
||||
self * R2
|
||||
}
|
||||
}
|
||||
|
||||
impl ::ff::PrimeField for #name {
|
||||
type Repr = #repr;
|
||||
type ReprEndianness = #repr_endianness;
|
||||
|
||||
fn from_repr(r: #repr) -> Option<#name> {
|
||||
#from_repr_impl
|
||||
|
@@ -12,6 +12,7 @@ extern crate std;
|
||||
#[cfg(feature = "derive")]
|
||||
pub use ff_derive::*;
|
||||
|
||||
use byteorder::ByteOrder;
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
@@ -124,14 +125,36 @@ impl<T: Field> PowVartime<u64> for T {
|
||||
const LIMB_SIZE: u64 = 64;
|
||||
}
|
||||
|
||||
/// Helper trait for converting the binary representation of a prime field element into a
|
||||
/// specific endianness. This is useful when you need to act on the bit representation
|
||||
/// of an element generically, as the native binary representation of a prime field is
|
||||
/// field-dependent.
|
||||
pub trait Endianness: ByteOrder {
|
||||
/// Converts the provided representation between native and little-endian.
|
||||
fn toggle_little_endian<T: AsMut<[u8]>>(t: &mut T);
|
||||
}
|
||||
|
||||
impl Endianness for byteorder::BigEndian {
|
||||
fn toggle_little_endian<T: AsMut<[u8]>>(t: &mut T) {
|
||||
t.as_mut().reverse();
|
||||
}
|
||||
}
|
||||
|
||||
impl Endianness for byteorder::LittleEndian {
|
||||
fn toggle_little_endian<T: AsMut<[u8]>>(_: &mut T) {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
/// This represents an element of a prime field.
|
||||
pub trait PrimeField:
|
||||
Field + Ord + From<u64> + BitAnd<u64, Output = u64> + Shr<u32, Output = Self>
|
||||
{
|
||||
pub trait PrimeField: Field + Ord + From<u64> {
|
||||
/// The prime field can be converted back and forth into this binary
|
||||
/// representation.
|
||||
type Repr: Default + AsRef<[u8]> + AsMut<[u8]> + From<Self> + for<'r> From<&'r Self>;
|
||||
|
||||
/// This indicates the endianness of [`PrimeField::Repr`].
|
||||
type ReprEndianness: Endianness;
|
||||
|
||||
/// Interpret a string of numbers as a (congruent) prime field element.
|
||||
/// Does not accept unnecessary leading zeroes or a blank string.
|
||||
fn from_str(s: &str) -> Option<Self> {
|
||||
@@ -176,16 +199,15 @@ pub trait PrimeField:
|
||||
/// this prime field, failing if the input is not canonical (is not smaller than the
|
||||
/// field's modulus).
|
||||
///
|
||||
/// The byte representation is interpreted with the same endianness as is returned
|
||||
/// by [`PrimeField::into_repr`].
|
||||
/// The byte representation is interpreted with the endianness defined by
|
||||
/// [`PrimeField::ReprEndianness`].
|
||||
fn from_repr(_: Self::Repr) -> Option<Self>;
|
||||
|
||||
/// Converts an element of the prime field into the standard byte representation for
|
||||
/// this field.
|
||||
///
|
||||
/// Endianness of the byte representation is defined by the field implementation.
|
||||
/// Callers should assume that it is the standard endianness used to represent encoded
|
||||
/// elements of this particular field.
|
||||
/// The endianness of the byte representation is defined by
|
||||
/// [`PrimeField::ReprEndianness`].
|
||||
fn into_repr(&self) -> Self::Repr;
|
||||
|
||||
/// Returns true iff this element is odd.
|
||||
|
Reference in New Issue
Block a user