Skip to content

Commit 86a5bdc

Browse files
committed
Merge rust-bitcoin#203: Extend Field and Checksum for error correction
f47ec0b field: add Powers iterator (Andrew Poelstra) c389d72 checksum: add new error-correction fields to the Checksum trait (Andrew Poelstra) 14e4f7b field: add Default bound to Field (Andrew Poelstra) 011674d field: add format_as_rust_code utility method (Andrew Poelstra) 3c97cd1 field: split trait into "normal" field trait and sealed trait (Andrew Poelstra) 8eaec9d field: use UFCS in macro (Andrew Poelstra) Pull request description: The first couple commits of this PR split the `Field` trait into two -- a general `Field` trait which has the algebraic functionality of a field, and a sealed `Bech32Field` trait which has the functionality that is specific to this crate. The rest add new functionality to the traits which describe extra properties of our checksums needed for error correction. The next PRs will: * Introduce a `FieldVec` type to back `Polynomial` to make it work in a no-alloc setting (at least for small checksums, for a configurable notion of "small") * Implement error correction :) ACKs for top commit: clarkmoody: ACK f47ec0b Tree-SHA512: 880e0e4cb2f21effd657ef57ddff45a807f55283f7a0fad6aeec67518f0bbec0daa719bbedd5c9490dd1ed22538ea3a9b071db3cb6eac142cbd91d1e65919103
2 parents 7a6d9cc + f47ec0b commit 86a5bdc

File tree

6 files changed

+254
-161
lines changed

6 files changed

+254
-161
lines changed

src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,18 @@
9595
//!
9696
//! ```
9797
//! # #[cfg(feature = "alloc")] {
98-
//! use bech32::Checksum;
98+
//! use bech32::{Checksum, Fe32, Fe1024};
9999
//!
100100
//! /// The codex32 checksum algorithm, defined in BIP-93.
101101
//! #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
102102
//! pub enum Codex32 {}
103103
//!
104104
//! impl Checksum for Codex32 {
105105
//! type MidstateRepr = u128;
106+
//! type CorrectionField = bech32::primitives::gf32_ext::Fe32Ext<2>;
107+
//! const ROOT_GENERATOR: Self::CorrectionField = Fe1024::new([Fe32::_9, Fe32::_9]);
108+
//! const ROOT_EXPONENTS: core::ops::RangeInclusive<usize> = 77..=84;
109+
//!
106110
//! const CHECKSUM_LENGTH: usize = 13;
107111
//! const CODE_LENGTH: usize = 93;
108112
//! // Copied from BIP-93

src/primitives/checksum.rs

+31-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ use crate::Fe32;
2323
///
2424
/// For users, this can be treated as a marker trait; none of the associated data
2525
/// are end-user relevant.
26+
///
27+
/// For developers, implementations of this trait can be computed by starting with
28+
/// a couple of values and using the [`PrintImpl`] object to generate the rest.
29+
/// See the documentation for that type and its unit tests for examples.
2630
pub trait Checksum {
2731
/// An unsigned integer type capable of holding a packed version of the generator
2832
/// polynomial (without its leading 1) and target residue (which will have the
@@ -37,6 +41,16 @@ pub trait Checksum {
3741
/// be pretty efficient no matter what.
3842
type MidstateRepr: PackedFe32;
3943

44+
/// The extension field in which error correction happens.
45+
type CorrectionField: super::ExtensionField<BaseField = Fe32>;
46+
47+
/// The generator of the consecutive roots of the generator polynomial.
48+
const ROOT_GENERATOR: Self::CorrectionField;
49+
50+
/// The consecutive powers of [`Self::ROOT_GENERATOR`] which are roots
51+
/// of the generator polynomial.
52+
const ROOT_EXPONENTS: core::ops::RangeInclusive<usize>;
53+
4054
/// The length of the code.
4155
///
4256
/// 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> {
224238
#[cfg(feature = "alloc")]
225239
impl<'a, ExtField> fmt::Display for PrintImpl<'a, ExtField>
226240
where
227-
ExtField: super::ExtensionField + From<Fe32>,
241+
ExtField: super::Bech32Field + super::ExtensionField<BaseField = Fe32>,
228242
{
229243
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230244
// Generator polynomial as a polynomial over GF1024
@@ -234,7 +248,7 @@ where
234248
v.extend(self.generator.iter().cloned().map(ExtField::from));
235249
Polynomial::new(v)
236250
};
237-
let (_gen, length, _exponents) = gen_poly.bch_generator_primitive_element();
251+
let (gen, length, exponents) = gen_poly.bch_generator_primitive_element();
238252

239253
write!(f, "// Code block generated by Checksum::print_impl polynomial ")?;
240254
for fe in self.generator {
@@ -251,6 +265,18 @@ where
251265
" type MidstateRepr = {}; // checksum packs into {} bits",
252266
self.midstate_repr, self.bit_len
253267
)?;
268+
f.write_str("\n")?;
269+
writeln!(f, " type CorrectionField = {};", core::any::type_name::<ExtField>())?;
270+
f.write_str(" const ROOT_GENERATOR: Self::CorrectionField = ")?;
271+
gen.format_as_rust_code(f)?;
272+
f.write_str(";\n")?;
273+
writeln!(
274+
f,
275+
" const ROOT_EXPONENTS: core::ops::RangeInclusive<usize> = {}..={};",
276+
exponents.start(),
277+
exponents.end()
278+
)?;
279+
f.write_str("\n")?;
254280
writeln!(f, " const CODE_LENGTH: usize = {};", length)?;
255281
writeln!(f, " const CHECKSUM_LENGTH: usize = {};", gen_poly.degree())?;
256282
writeln!(f, " const GENERATOR_SH: [{}; 5] = [", self.midstate_repr)?;
@@ -263,9 +289,10 @@ where
263289
writeln!(f, " ];")?;
264290
writeln!(
265291
f,
266-
" const TARGET_RESIDUE: {} = {:?};",
292+
" const TARGET_RESIDUE: {} = 0x{:0width$x};",
267293
self.midstate_repr,
268-
u128::pack(self.target.iter().copied().map(From::from))
294+
u128::pack(self.target.iter().copied().map(From::from)),
295+
width = self.hex_width,
269296
)?;
270297
f.write_str("}")
271298
}

0 commit comments

Comments
 (0)