Skip to content

Commit e398536

Browse files
authored
primefield: add monty_field_arithmetic! macro (#1547)
Previously the only option for adding a field arithmetic backend was the `monty_field_fiat_arithmetic!` macro, which is designed to plug into `fiat-crypto` synthesized code. In the past we have only used fiat-crypto for our field element implementations (aside from `p256` and `k256` which have handwritten implementations). However, the inner field element type of newtypes written by the `monty_field_element!` macro is `primefield::MontyFieldElement` which is a full-fledged generic field element implementation itself. To use it, we just need to emit the same set of `const fn`s as the `monty_field_fiat_arithmetic!` macro and delegate to the inner type, which is what this PR does.
1 parent 9ab4189 commit e398536

File tree

2 files changed

+95
-10
lines changed

2 files changed

+95
-10
lines changed

primefield/src/macros.rs

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,6 @@ macro_rules! monty_field_params_with_root_of_unity {
9595
/// - `pub fn is_zero`
9696
/// - `pub fn double`
9797
///
98-
/// NOTE: field implementations must provide their own inherent impls of
99-
/// the following methods in order for the code generated by this macro to
100-
/// compile:
101-
///
102-
/// - `pub fn invert`
103-
/// - `pub fn sqrt`
104-
///
10598
/// # Trait impls
10699
/// - `ConditionallySelectable`
107100
/// - `ConstantTimeEq`
@@ -616,6 +609,100 @@ macro_rules! monty_field_element {
616609
};
617610
}
618611

612+
/// Add `const fn` methods to the given field element for performing field arithmetic operations,
613+
/// e.g. `add`, `double`, `sub`, `multiply`, `neg`.
614+
///
615+
/// This macro wraps a generic field implementation provided by the `crypto-bigint` crate, which is
616+
/// exposed as the [`primefield::MontyFieldElement`] type.
617+
#[macro_export]
618+
macro_rules! monty_field_arithmetic {
619+
(
620+
name: $fe:tt,
621+
params: $params:ty,
622+
uint: $uint:ty
623+
) => {
624+
impl $fe {
625+
/// Decode [`
626+
#[doc = stringify!($fe)]
627+
/// `] from [`
628+
#[doc = stringify!($uint)]
629+
/// `] converting it into Montgomery form.
630+
///
631+
/// Does *not* perform a check that the field element does not overflow the order.
632+
///
633+
/// Used incorrectly this can lead to invalid results!
634+
#[inline]
635+
pub(crate) const fn from_uint_unchecked(w: $uint) -> Self {
636+
// TODO(tarcieri): this reduces every time, maybe we can find a way to skip that?
637+
Self($crate::MontyFieldElement::from_uint_reduced(&w))
638+
}
639+
640+
/// Translate [`
641+
#[doc = stringify!($fe)]
642+
/// `] out of the Montgomery domain, returning a [`
643+
#[doc = stringify!($uint)]
644+
/// `] in canonical form.
645+
#[inline]
646+
pub const fn to_canonical(self) -> $uint {
647+
self.0.to_canonical()
648+
}
649+
650+
/// Add elements.
651+
#[inline]
652+
pub const fn add(&self, rhs: &Self) -> Self {
653+
Self(self.0.add(&rhs.0))
654+
}
655+
656+
/// Double element (add it to itself).
657+
#[inline]
658+
#[must_use]
659+
pub const fn double(&self) -> Self {
660+
Self(self.0.double())
661+
}
662+
663+
/// Subtract elements.
664+
#[inline]
665+
pub const fn sub(&self, rhs: &Self) -> Self {
666+
Self(self.0.sub(&rhs.0))
667+
}
668+
669+
/// Multiply elements.
670+
#[inline]
671+
pub const fn multiply(&self, rhs: &Self) -> Self {
672+
Self(self.0.multiply(&rhs.0))
673+
}
674+
675+
/// Negate element.
676+
#[inline]
677+
pub const fn neg(&self) -> Self {
678+
Self(self.0.neg())
679+
}
680+
681+
/// Compute modular square.
682+
#[inline]
683+
#[must_use]
684+
pub const fn square(&self) -> Self {
685+
Self(self.0.square())
686+
}
687+
688+
/// Compute
689+
#[doc = stringify!($fe)]
690+
/// inversion: `1 / self`.
691+
#[inline]
692+
pub fn invert(&self) -> $crate::subtle::CtOption<Self> {
693+
self.0.invert().map(|fe| Self(fe))
694+
}
695+
696+
/// Compute field inversion as a `const fn`. Panics if `self` is zero.
697+
///
698+
/// This is mainly intended for inverting constants at compile time.
699+
pub const fn const_invert(&self) -> Self {
700+
Self(self.0.const_invert())
701+
}
702+
}
703+
};
704+
}
705+
619706
/// Emit a `core::ops` trait wrapper for an inherent method which is expected to be provided by a
620707
/// backend arithmetic implementation (e.g. `fiat-crypto`)
621708
#[macro_export]

primefield/src/macros/fiat.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
44
/// Add `fiat-crypto` synthesized arithmetic impls to the given field element.
55
///
6-
/// This method wraps a field implementation generated by the `word-by-word-montgomery` backend
6+
/// This macro wraps a field implementation generated by the `word-by-word-montgomery` backend
77
/// (other field implementations are not supported).
8-
///
9-
/// This provides a complete arithmetic implementation except for `sqrt`.
108
#[macro_export]
119
macro_rules! monty_field_fiat_arithmetic {
1210
(

0 commit comments

Comments
 (0)