1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! BIP 93 codex32 BCH primitives for HRP `"ms"` (regular code only).
//!
//! Vendored from md-codec's structure at the v0.34.0 promotion (descriptor-mnemonic
//! commit `94069ea`) per plan §2.B.2 / D22. ms1 strings are all regular-code length
//! per `consts::VALID_STR_LENGTHS`, so the long-code primitives are intentionally
//! absent (mk-codec carries the long-code variants).
//!
//! All public per plan D22 (no `pub(crate)` half-private items in ms-codec): the
//! downstream `bch_decode` module (B.4) re-declares the 3 internal consts locally
//! per the Q3 lock — they stay bare-private here.
//!
//! `MS_REGULAR_CONST` is the BIP-93 codex32 short-code target residue
//! ("SECRETSHARE32"); ms-codec is its single source of truth. (The toolkit's
//! former vendored copy was deleted in its v0.23.0 migration, which now
//! delegates to this crate. That copy held the pre-v0.2.1 WRONG value paired
//! with a wrong `POLYMOD_INIT` — see
//! `design/BUG_decode_with_correction_length_divergence.md`.)
/// BCH(93,80,8) generator polynomial coefficients (5 × 65-bit).
///
/// Identical across mk/ms/md (the polynomial is BIP-93's; only the per-HRP
/// target residue differs).
pub const GEN_REGULAR: = ;
/// MS-domain target residue: codex32's "SECRETSHARE32" Fe-vec packed
/// big-endian in 5-bit chunks — the value [`polymod_run`] (started from the
/// codex32 initial residue [`POLYMOD_INIT`]) produces for ANY valid ms1
/// input, independent of entropy length.
///
/// `SECRETSHARE32 = [s,e,c,r,e,t,s,h,a,r,e,3,2] = [16,25,24,3,25,11,16,23,29,3,25,17,10]`
/// packed as `Σ vᵢ << (5·(12−i))` → `0x10ce0795c2fd1e62a` (bit 64 set). This is
/// the BIP-93 codex32 short-code target the `rust-codex32` engine (which
/// `envelope.rs` uses to encode) checks against, so the hand-rolled path here
/// is byte-equivalent to codex32 for all ms1 lengths.
///
/// NOTE (v0.2.1 fix): the previous value `0x962958058f2c192a`, paired with a
/// wrong `POLYMOD_INIT`, was empirically lifted from a single 12-word vector
/// and only validated 16-byte seeds — see
/// `design/BUG_decode_with_correction_length_divergence.md`.
pub const MS_REGULAR_CONST: u128 = 0x10ce0795c2fd1e62a;
/// codex32 initial polymod residue: the field element `1` (BIP-173/BIP-93
/// bech32-style start state), processed against `hrp_expand("ms") || data`.
/// (Was wrongly `0x23181b3`, which made `polymod_run` length-variant for valid
/// codewords — the root cause of the 20/24/28/32-byte correction bug.)
const POLYMOD_INIT: u128 = 0x1;
const REGULAR_SHIFT: u32 = 60;
const REGULAR_MASK: u128 = 0x0fffffffffffffff;
/// Run the BCH polymod over `values` starting from the BIP-93 initial residue.
///
/// Returns the final residue; callers XOR against the per-HRP target
/// constant ([`MS_REGULAR_CONST`]) to produce a checksum or to verify
/// one. Inputs are 5-bit symbols (`u8` in `0..32`); larger values are
/// reduced modulo 32 by the underlying step.
/// BIP 173-style HRP expansion: `[c >> 5 for c in hrp] ++ [0] ++ [c & 31 for c in hrp]`.
/// 13-symbol regular-code BCH checksum over `hrp_expand(hrp) || data || [0; 13]`.
/// Verify a regular-code BCH checksum over the data-part-with-checksum.