diff --git a/src/lib.rs b/src/lib.rs index afc8cd99..2cc18a99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,7 +95,7 @@ //! //! ``` //! # #[cfg(feature = "alloc")] { -//! use bech32::Checksum; +//! use bech32::{Checksum, Fe32, Fe1024}; //! //! /// The codex32 checksum algorithm, defined in BIP-93. //! #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -103,6 +103,10 @@ //! //! impl Checksum for Codex32 { //! type MidstateRepr = u128; +//! type CorrectionField = bech32::primitives::gf32_ext::Fe32Ext<2>; +//! const ROOT_GENERATOR: Self::CorrectionField = Fe1024::new([Fe32::_9, Fe32::_9]); +//! const ROOT_EXPONENTS: core::ops::RangeInclusive = 77..=84; +//! //! const CHECKSUM_LENGTH: usize = 13; //! const CODE_LENGTH: usize = 93; //! // Copied from BIP-93 diff --git a/src/primitives/checksum.rs b/src/primitives/checksum.rs index 3e5f82f7..50bebb75 100644 --- a/src/primitives/checksum.rs +++ b/src/primitives/checksum.rs @@ -23,6 +23,10 @@ use crate::Fe32; /// /// For users, this can be treated as a marker trait; none of the associated data /// are end-user relevant. +/// +/// For developers, implementations of this trait can be computed by starting with +/// a couple of values and using the [`PrintImpl`] object to generate the rest. +/// See the documentation for that type and its unit tests for examples. pub trait Checksum { /// An unsigned integer type capable of holding a packed version of the generator /// polynomial (without its leading 1) and target residue (which will have the @@ -37,6 +41,16 @@ pub trait Checksum { /// be pretty efficient no matter what. type MidstateRepr: PackedFe32; + /// The extension field in which error correction happens. + type CorrectionField: super::ExtensionField; + + /// The generator of the consecutive roots of the generator polynomial. + const ROOT_GENERATOR: Self::CorrectionField; + + /// The consecutive powers of [`Self::ROOT_GENERATOR`] which are roots + /// of the generator polynomial. + const ROOT_EXPONENTS: core::ops::RangeInclusive; + /// The length of the code. /// /// The length of the code is how long a coded message can be (including the @@ -224,7 +238,7 @@ impl<'a, ExtField> PrintImpl<'a, ExtField> { #[cfg(feature = "alloc")] impl<'a, ExtField> fmt::Display for PrintImpl<'a, ExtField> where - ExtField: super::ExtensionField + From, + ExtField: super::Bech32Field + super::ExtensionField, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Generator polynomial as a polynomial over GF1024 @@ -234,7 +248,7 @@ where v.extend(self.generator.iter().cloned().map(ExtField::from)); Polynomial::new(v) }; - let (_gen, length, _exponents) = gen_poly.bch_generator_primitive_element(); + let (gen, length, exponents) = gen_poly.bch_generator_primitive_element(); write!(f, "// Code block generated by Checksum::print_impl polynomial ")?; for fe in self.generator { @@ -251,6 +265,18 @@ where " type MidstateRepr = {}; // checksum packs into {} bits", self.midstate_repr, self.bit_len )?; + f.write_str("\n")?; + writeln!(f, " type CorrectionField = {};", core::any::type_name::())?; + f.write_str(" const ROOT_GENERATOR: Self::CorrectionField = ")?; + gen.format_as_rust_code(f)?; + f.write_str(";\n")?; + writeln!( + f, + " const ROOT_EXPONENTS: core::ops::RangeInclusive = {}..={};", + exponents.start(), + exponents.end() + )?; + f.write_str("\n")?; writeln!(f, " const CODE_LENGTH: usize = {};", length)?; writeln!(f, " const CHECKSUM_LENGTH: usize = {};", gen_poly.degree())?; writeln!(f, " const GENERATOR_SH: [{}; 5] = [", self.midstate_repr)?; @@ -263,9 +289,10 @@ where writeln!(f, " ];")?; writeln!( f, - " const TARGET_RESIDUE: {} = {:?};", + " const TARGET_RESIDUE: {} = 0x{:0width$x};", self.midstate_repr, - u128::pack(self.target.iter().copied().map(From::from)) + u128::pack(self.target.iter().copied().map(From::from)), + width = self.hex_width, )?; f.write_str("}") } diff --git a/src/primitives/field.rs b/src/primitives/field.rs index 5f8636dc..9ac5ef7e 100644 --- a/src/primitives/field.rs +++ b/src/primitives/field.rs @@ -2,6 +2,7 @@ //! Generic Field Traits +use core::iter::{Skip, Take}; use core::{fmt, hash, iter, ops}; /// A generic field. @@ -10,6 +11,7 @@ pub trait Field: + PartialEq + Eq + Clone + + Default + hash::Hash + fmt::Debug + fmt::Display @@ -51,29 +53,6 @@ pub trait Field: /// prime factors which each appearing once, this array would have size `2^n`. const MULTIPLICATIVE_ORDER_FACTORS: &'static [usize]; - /// Adds a value to `self`. This is a helper function for implementing the - /// [`ops::Add`] and [`ops::AddAssign`] traits, which should probably be called - /// instead of calling this. - fn _add(&self, other: &Self) -> Self; - - /// Subtracts a value from `self`. This is a helper function for implementing the - /// [`ops::Sub`] and [`ops::SubAssign`] traits, which should probably be called - /// instead of calling this. - fn _sub(&self, other: &Self) -> Self; - - /// Multiplies a value by `self`. This is a helper function for implementing the - /// [`ops::Mul`] and [`ops::MulAssign`] traits, which should probably be called - /// instead of calling this. - fn _mul(&self, other: &Self) -> Self; - - /// Divides a value from `self`. This is a helper function for implementing the - /// [`ops::Div`] and [`ops::DivAssign`] traits, which should probably be called - /// instead of calling this. - fn _div(&self, other: &Self) -> Self; - - /// Computes the additive inverse of an element. - fn _neg(self) -> Self; - /// Computes the multiplicative inverse of an element. fn multiplicative_inverse(self) -> Self; @@ -110,6 +89,20 @@ pub trait Field: "bug: `ExtensionField::MULTIPLICATIVE_ORDER_FACTORS` did not include full group order" ); } + + /// Constructs an iterator over all the powers of an element from 0 onward. + fn powers(self) -> Powers { Powers { base: self, next: Self::ONE } } + + /// Constructs an iterator over all the powers of an element within a given range. + /// + /// # Panics + /// + /// Panics if given a range whose start is greater than its end, or whose range + /// is from 0 to `usize::MAX`. Its intended use is with [`crate::Checksum::ROOT_EXPONENTS`] + /// for which neither of these conditions should ever be true. + fn powers_range(self, range: ops::RangeInclusive) -> Take>> { + self.powers().skip(*range.start()).take(*range.end() - range.start() + 1) + } } /// Trait describing a simple extension field (field obtained from another by @@ -141,58 +134,83 @@ pub trait ExtensionField: Field + From { const EXT_ELEM: Self; } +mod private { + /// Sealing trait. + pub trait Sealed {} + + impl Sealed for crate::Fe32 {} + impl Sealed for crate::Fe1024 {} + impl Sealed for crate::Fe32768 {} +} + +/// Sealed trait which extends [`Field`] with extra functionality +/// needed internally to this library. +/// +/// This trait should not be used directly by users of the library. +pub trait Bech32Field: private::Sealed + Sized { + /// Adds a value to `self`. This is a helper function for implementing the + /// [`ops::Add`] and [`ops::AddAssign`] traits. + fn _add(&self, other: &Self) -> Self; + + /// Subtracts a value from `self`. This is a helper function for implementing the + /// [`ops::Sub`] and [`ops::SubAssign`] traits. + fn _sub(&self, other: &Self) -> Self { + self._add(other) // all fields in this library are binary fields + } + + /// Multiplies a value by `self`. This is a helper function for implementing the + /// [`ops::Mul`] and [`ops::MulAssign`] traits. + fn _mul(&self, other: &Self) -> Self; + + /// Divides a value from `self`. This is a helper function for implementing the + /// [`ops::Div`] and [`ops::DivAssign`] traits. + fn _div(&self, other: &Self) -> Self; + + /// Computes the additive inverse of an element. + fn _neg(self) -> Self; + + /// Utility method to format a field element as Rust code. + fn format_as_rust_code(&self, f: &mut fmt::Formatter) -> fmt::Result; +} + macro_rules! impl_ops_for_fe { (impl for $op:ident) => { // add impl core::ops::Add<$op> for $op { type Output = Self; #[inline] - fn add(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._add(&other) - } + fn add(self, other: $op) -> $op { $crate::primitives::Bech32Field::_add(&self, &other) } } impl core::ops::Add<&$op> for $op { type Output = Self; #[inline] - fn add(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._add(other) - } + fn add(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_add(&self, other) } } impl core::ops::Add<$op> for &$op { type Output = $op; #[inline] - fn add(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._add(&other) - } + fn add(self, other: $op) -> $op { $crate::primitives::Bech32Field::_add(self, &other) } } impl core::ops::Add<&$op> for &$op { type Output = $op; #[inline] - fn add(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._add(other) - } + fn add(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_add(self, other) } } impl core::ops::AddAssign for $op { #[inline] fn add_assign(&mut self, other: $op) { - use $crate::primitives::Field as _; - *self = self._add(&other) + *self = $crate::primitives::Bech32Field::_add(self, &other) } } impl core::ops::AddAssign<&$op> for $op { #[inline] fn add_assign(&mut self, other: &$op) { - use $crate::primitives::Field as _; - *self = self._add(other) + *self = $crate::primitives::Bech32Field::_add(self, other) } } @@ -200,52 +218,38 @@ macro_rules! impl_ops_for_fe { impl core::ops::Sub<$op> for $op { type Output = Self; #[inline] - fn sub(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._sub(&other) - } + fn sub(self, other: $op) -> $op { $crate::primitives::Bech32Field::_sub(&self, &other) } } impl core::ops::Sub<&$op> for $op { type Output = Self; #[inline] - fn sub(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._sub(other) - } + fn sub(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_sub(&self, other) } } impl core::ops::Sub<$op> for &$op { type Output = $op; #[inline] - fn sub(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._sub(&other) - } + fn sub(self, other: $op) -> $op { $crate::primitives::Bech32Field::_sub(self, &other) } } impl core::ops::Sub<&$op> for &$op { type Output = $op; #[inline] - fn sub(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._sub(other) - } + fn sub(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_sub(self, other) } } impl core::ops::SubAssign for $op { #[inline] fn sub_assign(&mut self, other: $op) { - use $crate::primitives::Field as _; - *self = self._sub(&other) + *self = $crate::primitives::Bech32Field::_sub(self, &other) } } impl core::ops::SubAssign<&$op> for $op { #[inline] fn sub_assign(&mut self, other: &$op) { - use $crate::primitives::Field as _; - *self = self._sub(other) + *self = $crate::primitives::Bech32Field::_sub(self, other) } } @@ -253,52 +257,38 @@ macro_rules! impl_ops_for_fe { impl core::ops::Mul<$op> for $op { type Output = Self; #[inline] - fn mul(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._mul(&other) - } + fn mul(self, other: $op) -> $op { $crate::primitives::Bech32Field::_mul(&self, &other) } } impl core::ops::Mul<&$op> for $op { type Output = Self; #[inline] - fn mul(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._mul(other) - } + fn mul(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_mul(&self, other) } } impl core::ops::Mul<$op> for &$op { type Output = $op; #[inline] - fn mul(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._mul(&other) - } + fn mul(self, other: $op) -> $op { $crate::primitives::Bech32Field::_mul(self, &other) } } impl core::ops::Mul<&$op> for &$op { type Output = $op; #[inline] - fn mul(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._mul(other) - } + fn mul(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_mul(self, other) } } impl core::ops::MulAssign for $op { #[inline] fn mul_assign(&mut self, other: $op) { - use $crate::primitives::Field as _; - *self = self._mul(&other) + *self = $crate::primitives::Bech32Field::_mul(self, &other) } } impl core::ops::MulAssign<&$op> for $op { #[inline] fn mul_assign(&mut self, other: &$op) { - use $crate::primitives::Field as _; - *self = self._mul(other) + *self = $crate::primitives::Bech32Field::_mul(self, other) } } @@ -306,52 +296,38 @@ macro_rules! impl_ops_for_fe { impl core::ops::Div<$op> for $op { type Output = Self; #[inline] - fn div(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._div(&other) - } + fn div(self, other: $op) -> $op { $crate::primitives::Bech32Field::_div(&self, &other) } } impl core::ops::Div<&$op> for $op { type Output = Self; #[inline] - fn div(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._div(other) - } + fn div(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_div(&self, other) } } impl core::ops::Div<$op> for &$op { type Output = $op; #[inline] - fn div(self, other: $op) -> $op { - use $crate::primitives::Field as _; - self._div(&other) - } + fn div(self, other: $op) -> $op { $crate::primitives::Bech32Field::_div(self, &other) } } impl core::ops::Div<&$op> for &$op { type Output = $op; #[inline] - fn div(self, other: &$op) -> $op { - use $crate::primitives::Field as _; - self._div(other) - } + fn div(self, other: &$op) -> $op { $crate::primitives::Bech32Field::_div(self, other) } } impl core::ops::DivAssign for $op { #[inline] fn div_assign(&mut self, other: $op) { - use $crate::primitives::Field as _; - *self = self._div(&other) + *self = $crate::primitives::Bech32Field::_div(self, &other) } } impl core::ops::DivAssign<&$op> for $op { #[inline] fn div_assign(&mut self, other: &$op) { - use $crate::primitives::Field as _; - *self = self._div(other) + *self = $crate::primitives::Bech32Field::_div(self, other) } } @@ -359,10 +335,7 @@ macro_rules! impl_ops_for_fe { impl core::ops::Neg for $op { type Output = Self; #[inline] - fn neg(self) -> Self { - use $crate::primitives::Field as _; - self._neg() - } + fn neg(self) -> Self { $crate::primitives::Bech32Field::_neg(self) } } // sum @@ -380,3 +353,35 @@ macro_rules! impl_ops_for_fe { }; } pub(super) use impl_ops_for_fe; + +/// An iterator over the powers of a field, starting from zero. +/// +/// This iterator starts from 1, but has an optimized version of [`Iterator::nth`] +/// which allows efficient construction. +pub struct Powers { + base: F, + next: F, +} + +impl Iterator for Powers { + type Item = F; + + fn next(&mut self) -> Option { + let ret = Some(self.next.clone()); + self.next *= &self.base; + ret + } + + /// Compute next by calling `F::powi`. + /// + /// The default implementation of `nth` will simply call the iterator `n` + /// times, throwing away the result, which takes O(n) field multiplications. + /// For a power iterator we can do much better, taking O(log(n)) multiplications. + /// + /// This is important because this method is called internally by `Iterator::skip`. + fn nth(&mut self, n: usize) -> Option { + let ni64 = (n % F::MULTIPLICATIVE_ORDER) as i64; // cast ok since modulus should be small + self.next *= self.base.powi(ni64); + self.next() + } +} diff --git a/src/primitives/gf32.rs b/src/primitives/gf32.rs index c4fe0702..4076e87e 100644 --- a/src/primitives/gf32.rs +++ b/src/primitives/gf32.rs @@ -18,6 +18,7 @@ use core::{fmt, num}; #[cfg(all(test, mutate))] use mutagen::mutate; +use super::{Bech32Field, Field}; use crate::error::write_err; /// Logarithm table of each bech32 element, as a power of alpha = Z. @@ -256,16 +257,9 @@ impl AsRef for Fe32 { fn as_ref(&self) -> &u8 { &self.0 } } -impl super::Field for Fe32 { - const ZERO: Self = Fe32::Q; - const ONE: Self = Fe32::P; - const GENERATOR: Self = Fe32::Z; - const MULTIPLICATIVE_ORDER: usize = 31; - const MULTIPLICATIVE_ORDER_FACTORS: &'static [usize] = &[1, 31]; - +impl Bech32Field for Fe32 { fn _add(&self, other: &Fe32) -> Fe32 { Fe32(self.0 ^ other.0) } - // Subtraction is the same as addition in a characteristic-2 field - fn _sub(&self, other: &Fe32) -> Fe32 { self._add(other) } + fn _mul(&self, other: &Fe32) -> Fe32 { if self.0 == 0 || other.0 == 0 { Fe32(0) @@ -276,6 +270,7 @@ impl super::Field for Fe32 { Fe32(LOG_INV[((log1 + log2) % mult_order) as usize]) } } + fn _div(&self, other: &Fe32) -> Fe32 { if self.0 == 0 { Fe32(0) @@ -291,11 +286,35 @@ impl super::Field for Fe32 { fn _neg(self) -> Self { self } + fn format_as_rust_code(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ch = self.to_char().to_ascii_uppercase(); + if ch.is_ascii_digit() { + write!(f, "Fe32::_{}", ch) + } else { + write!(f, "Fe32::{}", ch) + } + } +} + +impl Field for Fe32 { + const ZERO: Self = Fe32::Q; + const ONE: Self = Fe32::P; + const GENERATOR: Self = Fe32::Z; + const MULTIPLICATIVE_ORDER: usize = 31; + const MULTIPLICATIVE_ORDER_FACTORS: &'static [usize] = &[1, 31]; + fn multiplicative_inverse(self) -> Self { Self::ONE._div(&self) } } super::impl_ops_for_fe!(impl for Fe32); +impl super::ExtensionField for Fe32 { + type BaseField = Self; + const DEGREE: usize = 1; + const POLYNOMIAL: Self = Fe32::Q; + const EXT_ELEM: Self = Fe32::P; +} + /// A galois field error when converting from a character. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[non_exhaustive] diff --git a/src/primitives/gf32_ext.rs b/src/primitives/gf32_ext.rs index faff434b..a074305a 100644 --- a/src/primitives/gf32_ext.rs +++ b/src/primitives/gf32_ext.rs @@ -13,7 +13,7 @@ use core::{fmt, ops}; -use super::field::{ExtensionField, Field}; +use super::field::{Bech32Field, ExtensionField, Field}; use crate::Fe32; /// An element of the extension field. @@ -24,6 +24,11 @@ pub struct Fe32Ext { inner: [Fe32; DEG], } +// For some reason this cannot be derived. +impl Default for Fe32Ext { + fn default() -> Self { Fe32Ext { inner: [Fe32::Q; DEG] } } +} + impl From for Fe32Ext { fn from(fe: Fe32) -> Self { let mut ret = Self { inner: [Fe32::Q; DEG] }; @@ -110,6 +115,30 @@ where /// The field of order 1024. pub type Fe1024 = Fe32Ext<2>; +impl Bech32Field for Fe1024 { + #[inline] + fn _add(&self, other: &Self) -> Self { + Self::new([self.inner[0] + other.inner[0], self.inner[1] + other.inner[1]]) + } + + #[inline] + fn _mul(&self, other: &Self) -> Self { self.mul_by_elem(other) } + + #[inline] + fn _div(&self, other: &Self) -> Self { other.multiplicative_inverse() * self } + + #[inline] + fn _neg(self) -> Self { self } + + fn format_as_rust_code(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("Fe1024::new([")?; + self.inner[0].format_as_rust_code(f)?; + f.write_str(", ")?; + self.inner[1].format_as_rust_code(f)?; + f.write_str("])") + } +} + impl Field for Fe1024 { /// The zero element of the field. const ZERO: Self = Self::new([Fe32::Q, Fe32::Q]); @@ -129,23 +158,6 @@ impl Field for Fe1024 { const MULTIPLICATIVE_ORDER_FACTORS: &'static [usize] = &[1, 3, 11, 31, 33, 93, 341, 1023]; - #[inline] - fn _add(&self, other: &Self) -> Self { - Self::new([self.inner[0] + other.inner[0], self.inner[1] + other.inner[1]]) - } - - #[inline] - fn _sub(&self, other: &Self) -> Self { self._add(other) } - - #[inline] - fn _mul(&self, other: &Self) -> Self { self.mul_by_elem(other) } - - #[inline] - fn _div(&self, other: &Self) -> Self { other.multiplicative_inverse() * self } - - #[inline] - fn _neg(self) -> Self { self } - fn multiplicative_inverse(self) -> Self { // Aliases to make the below equations easier to read let a0 = self.inner[0]; @@ -186,6 +198,36 @@ impl ExtensionField for Fe1024 { /// The field of order 32768. pub type Fe32768 = Fe32Ext<3>; +impl Bech32Field for Fe32768 { + #[inline] + fn _add(&self, other: &Self) -> Self { + Self::new([ + self.inner[0] + other.inner[0], + self.inner[1] + other.inner[1], + self.inner[2] + other.inner[2], + ]) + } + + #[inline] + fn _mul(&self, other: &Self) -> Self { self.mul_by_elem(other) } + + #[inline] + fn _div(&self, other: &Self) -> Self { other.multiplicative_inverse() * self } + + #[inline] + fn _neg(self) -> Self { self } + + fn format_as_rust_code(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("Fe32768::new([")?; + self.inner[0].format_as_rust_code(f)?; + f.write_str(", ")?; + self.inner[1].format_as_rust_code(f)?; + f.write_str(", ")?; + self.inner[2].format_as_rust_code(f)?; + f.write_str("])") + } +} + impl Field for Fe32768 { /// The zero element of the field. const ZERO: Self = Self::new([Fe32::Q, Fe32::Q, Fe32::Q]); @@ -206,27 +248,6 @@ impl Field for Fe32768 { const MULTIPLICATIVE_ORDER_FACTORS: &'static [usize] = &[1, 7, 31, 151, 217, 1057, 4681, 32767]; - #[inline] - fn _add(&self, other: &Self) -> Self { - Self::new([ - self.inner[0] + other.inner[0], - self.inner[1] + other.inner[1], - self.inner[2] + other.inner[2], - ]) - } - - #[inline] - fn _sub(&self, other: &Self) -> Self { self._add(other) } - - #[inline] - fn _mul(&self, other: &Self) -> Self { self.mul_by_elem(other) } - - #[inline] - fn _div(&self, other: &Self) -> Self { other.multiplicative_inverse() * self } - - #[inline] - fn _neg(self) -> Self { self } - fn multiplicative_inverse(self) -> Self { // Unlike in the GF1024 case we don't bother being generic over // arbitrary values of POLYNOMIAL, since doing so means a ton diff --git a/src/primitives/mod.rs b/src/primitives/mod.rs index 28ca963a..fcc82023 100644 --- a/src/primitives/mod.rs +++ b/src/primitives/mod.rs @@ -16,10 +16,12 @@ pub mod segwit; use checksum::{Checksum, PackedNull}; use field::impl_ops_for_fe; -pub use field::{ExtensionField, Field}; +pub use field::{Bech32Field, ExtensionField, Field}; #[cfg(feature = "alloc")] use polynomial::Polynomial; +use crate::{Fe1024, Fe32}; + /// The "null checksum" used on bech32 strings for which we want to do no checksum checking. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum NoChecksum {} @@ -38,6 +40,11 @@ pub enum Bech32m {} impl Checksum for NoChecksum { type MidstateRepr = PackedNull; + + type CorrectionField = Fe32; // needs to be a `Field` + const ROOT_GENERATOR: Self::CorrectionField = Fe32::P; + const ROOT_EXPONENTS: core::ops::RangeInclusive = 0..=0; + const CODE_LENGTH: usize = usize::MAX; const CHECKSUM_LENGTH: usize = 0; const GENERATOR_SH: [PackedNull; 5] = [PackedNull; 5]; @@ -49,6 +56,11 @@ const GEN: [u32; 5] = [0x3b6a_57b2, 0x2650_8e6d, 0x1ea1_19fa, 0x3d42_33dd, 0x2a1 impl Checksum for Bech32 { type MidstateRepr = u32; + + type CorrectionField = Fe1024; + const ROOT_GENERATOR: Self::CorrectionField = Fe1024::new([Fe32::P, Fe32::X]); + const ROOT_EXPONENTS: core::ops::RangeInclusive = 997..=999; + const CODE_LENGTH: usize = 1023; const CHECKSUM_LENGTH: usize = 6; const GENERATOR_SH: [u32; 5] = GEN; @@ -57,6 +69,11 @@ impl Checksum for Bech32 { // Same as Bech32 except TARGET_RESIDUE is different impl Checksum for Bech32m { type MidstateRepr = u32; + + type CorrectionField = Fe1024; + const ROOT_GENERATOR: Self::CorrectionField = Fe1024::new([Fe32::P, Fe32::X]); + const ROOT_EXPONENTS: core::ops::RangeInclusive = 997..=999; + const CODE_LENGTH: usize = 1023; const CHECKSUM_LENGTH: usize = 6; const GENERATOR_SH: [u32; 5] = GEN;