-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
…dResidueError` c209ce8 polynomial: expand unit tests (Andrew Poelstra) dfc29ad fieldvec: add a bunch of unit tests (Andrew Poelstra) 0e3d954 polynomial: make Eq/PartialEq take leading zeros into account (Andrew Poelstra) d08da46 correction: introduce CorrectableError trait (Andrew Poelstra) 4c6010e primitives: introduce InvalidResidueError (Andrew Poelstra) b76adbe polynomial: add some extra functionality enabled by FieldVec (Andrew Poelstra) 690fc7d polynomial: use FieldVec in Polynomial (Andrew Poelstra) f2ec582 primitives: introduce FieldVec type (Andrew Poelstra) Pull request description: This introduces a new internal type `FieldVec` which is basically a backing array for checksum residues with some fiddly logic to work in a noalloc context. Unlike ArrayVec or other similar types, this one's semantics are "an unbounded vector if you have an allocator, a bounded vector otherwise". If you go outside of the bounds without an allocator the code will panic, but our use of it ensures that this is never exposed to a user. It also assumes that it's holding a `Default` type which lets us avoid unsafety (and dismisses the potential performance cost because this array is never expected to have more than 10 or 20 elements, even when it is "unbounded"). Using this backing, it improves `Polynomial` and removes the alloc bound from it; using this, it puts `Polynomial` into a new `InvalidResidueError` type, which will allow users to extract the necessary information from a checksum error to run the error correction algorithm. (The resulting change to an error type makes this an API-breaking change, though I don't think that anything else here is API-breaking.) The next PR will actually implement correction :). ACKs for top commit: tcharding: ACK c209ce8 clarkmoody: ACK c209ce8 Tree-SHA512: 16a23bd88101be549c9d50f6b32f669688dfb1efbd6e842c1c3db2203d1775e647f0909c4a65191fd332cd07778c0431ae7b4635909a00f7c2d86135fae042e2
- Loading branch information
Showing
9 changed files
with
1,061 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
//! Error Correction | ||
//! | ||
//! Implements the Berlekamp-Massey algorithm to locate errors, with Forney's | ||
//! equation to identify the error values, in a BCH-encoded string. | ||
//! | ||
|
||
use crate::primitives::decode::{ | ||
CheckedHrpstringError, ChecksumError, InvalidResidueError, SegwitHrpstringError, | ||
}; | ||
#[cfg(feature = "alloc")] | ||
use crate::DecodeError; | ||
|
||
/// **One more than** the maximum length (in characters) of a checksum which | ||
/// can be error-corrected without an allocator. | ||
/// | ||
/// When the **alloc** feature is enabled, this constant is practically irrelevant. | ||
/// When the feature is disabled, it represents a length beyond which this library | ||
/// does not support error correction. | ||
/// | ||
/// If you need this value to be increased, please file an issue describing your | ||
/// usecase. Bear in mind that an increased value will increase memory usage for | ||
/// all users, and the focus of this library is the Bitcoin ecosystem, so we may | ||
/// not be able to accept your request. | ||
// This constant is also used when comparing bech32 residues against the | ||
// bech32/bech32m targets, which should work with no-alloc. Therefore this | ||
// constant must be > 6 (the length of the bech32(m) checksum). | ||
// | ||
// Otherwise it basically represents a tradeoff between stack usage and the | ||
// size of error types, vs functionality in a no-alloc setting. The value | ||
// of 7 covers bech32 and bech32m. To get the descriptor checksum we need a | ||
// value and the descriptor checksum. To also get codex32 it should be >13, | ||
// and for "long codex32" >15 ... but consider that no-alloc contexts are | ||
// likely to be underpowered and will struggle to do correction on these | ||
// big codes anyway. | ||
// | ||
// Perhaps we will want to add a feature gate, off by default, that boosts | ||
// this to 16, or maybe even higher. But we will wait for implementors who | ||
// complain. | ||
pub const NO_ALLOC_MAX_LENGTH: usize = 7; | ||
|
||
/// Trait describing an error for which an error correction algorithm is applicable. | ||
/// | ||
/// Essentially, this trait represents an error which contains an [`InvalidResidueError`] | ||
/// variant. | ||
pub trait CorrectableError { | ||
/// Given a decoding error, if this is a "checksum failed" error, extract | ||
/// that specific error type. | ||
/// | ||
/// There are many ways in which decoding a checksummed string might fail. | ||
/// If the string was well-formed in all respects except that the final | ||
/// checksum characters appear to be wrong, it is possible to run an | ||
/// error correction algorithm to attempt to extract errors. | ||
/// | ||
/// In all other cases we do not have enough information to do correction. | ||
/// | ||
/// This is the function that implementors should implement. | ||
fn residue_error(&self) -> Option<&InvalidResidueError>; | ||
} | ||
|
||
impl CorrectableError for InvalidResidueError { | ||
fn residue_error(&self) -> Option<&InvalidResidueError> { Some(self) } | ||
} | ||
|
||
impl CorrectableError for ChecksumError { | ||
fn residue_error(&self) -> Option<&InvalidResidueError> { | ||
match self { | ||
ChecksumError::InvalidResidue(ref e) => Some(e), | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
impl CorrectableError for SegwitHrpstringError { | ||
fn residue_error(&self) -> Option<&InvalidResidueError> { | ||
match self { | ||
SegwitHrpstringError::Checksum(ref e) => e.residue_error(), | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
impl CorrectableError for CheckedHrpstringError { | ||
fn residue_error(&self) -> Option<&InvalidResidueError> { | ||
match self { | ||
CheckedHrpstringError::Checksum(ref e) => e.residue_error(), | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "alloc")] | ||
impl CorrectableError for crate::segwit::DecodeError { | ||
fn residue_error(&self) -> Option<&InvalidResidueError> { self.0.residue_error() } | ||
} | ||
|
||
#[cfg(feature = "alloc")] | ||
impl CorrectableError for DecodeError { | ||
fn residue_error(&self) -> Option<&InvalidResidueError> { | ||
match self { | ||
DecodeError::Checksum(ref e) => e.residue_error(), | ||
_ => None, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.