Bump bech32 to 0.8.0 and use BIP-0350 Bech32m checksum

Replace BIP-0173 test vectors with those in BIP-0350.
This commit is contained in:
Clark Moody 2021-02-17 22:10:07 -06:00 committed by Dr Maxim Orlovsky
parent 5573a546ca
commit eeeb722155
No known key found for this signature in database
GPG Key ID: FFC0250947E5C6F7
1 changed files with 15 additions and 6 deletions

View File

@ -60,6 +60,8 @@ pub enum Error {
Bech32(bech32::Error), Bech32(bech32::Error),
/// The bech32 payload was empty /// The bech32 payload was empty
EmptyBech32Payload, EmptyBech32Payload,
/// The wrong checksum algorithm was used. See BIP-0350.
InvalidBech32Variant,
/// Script version must be 0 to 16 inclusive /// Script version must be 0 to 16 inclusive
InvalidWitnessVersion(u8), InvalidWitnessVersion(u8),
/// Unable to parse witness version from string /// Unable to parse witness version from string
@ -82,6 +84,7 @@ impl fmt::Display for Error {
Error::Base58(ref e) => write!(f, "base58: {}", e), Error::Base58(ref e) => write!(f, "base58: {}", e),
Error::Bech32(ref e) => write!(f, "bech32: {}", e), Error::Bech32(ref e) => write!(f, "bech32: {}", e),
Error::EmptyBech32Payload => write!(f, "the bech32 payload was empty"), Error::EmptyBech32Payload => write!(f, "the bech32 payload was empty"),
Error::InvalidBech32Variant => write!(f, "invalid bech32 checksum variant"),
Error::InvalidWitnessVersion(v) => write!(f, "invalid witness script version: {}", v), Error::InvalidWitnessVersion(v) => write!(f, "invalid witness script version: {}", v),
Error::UnparsableWitnessVersion(ref e) => write!(f, "Incorrect format of a witness version byte: {}", e), Error::UnparsableWitnessVersion(ref e) => write!(f, "Incorrect format of a witness version byte: {}", e),
Error::MalformedWitnessVersion => f.write_str("bitcoin script opcode does not match any known witness version, the script is malformed"), Error::MalformedWitnessVersion => f.write_str("bitcoin script opcode does not match any known witness version, the script is malformed"),
@ -319,6 +322,14 @@ impl WitnessVersion {
pub fn into_num(self) -> u8 { pub fn into_num(self) -> u8 {
self as u8 self as u8
} }
/// Determine the checksum variant. See BIP-0350 for specification.
pub fn bech32_variant(&self) -> bech32::Variant {
match self {
WitnessVersion::V0 => bech32::Variant::Bech32,
_ => bech32::Variant::Bech32m,
}
}
} }
impl From<WitnessVersion> for ::bech32::u5 { impl From<WitnessVersion> for ::bech32::u5 {
@ -634,7 +645,6 @@ impl fmt::Display for Address {
Network::Testnet | Network::Signet => "tb", Network::Testnet | Network::Signet => "tb",
Network::Regtest => "bcrt", Network::Regtest => "bcrt",
}; };
let bech_ver = if version.into_num() > 0 { bech32::Variant::Bech32m } else { bech32::Variant::Bech32 };
let mut upper_writer; let mut upper_writer;
let writer = if fmt.alternate() { let writer = if fmt.alternate() {
upper_writer = UpperWriter(fmt); upper_writer = UpperWriter(fmt);
@ -642,7 +652,7 @@ impl fmt::Display for Address {
} else { } else {
fmt as &mut dyn fmt::Write fmt as &mut dyn fmt::Write
}; };
let mut bech32_writer = bech32::Bech32Writer::new(hrp, bech_ver, writer)?; let mut bech32_writer = bech32::Bech32Writer::new(hrp, version.bech32_variant(), writer)?;
bech32::WriteBase32::write_u5(&mut bech32_writer, version.into())?; bech32::WriteBase32::write_u5(&mut bech32_writer, version.into())?;
bech32::ToBase32::write_base32(&prog, &mut bech32_writer) bech32::ToBase32::write_base32(&prog, &mut bech32_writer)
} }
@ -705,10 +715,9 @@ impl FromStr for Address {
return Err(Error::InvalidSegwitV0ProgramLength(program.len())); return Err(Error::InvalidSegwitV0ProgramLength(program.len()));
} }
// Bech32 encoding check // Encoding check
if (version.into_num() > 0 && variant != bech32::Variant::Bech32m) || if version.bech32_variant() != variant {
(version.into_num() == 0 && variant != bech32::Variant::Bech32) { return Err(Error::InvalidBech32Variant);
return Err(Error::InvalidWitnessVersion(version.into_num()))
} }
return Ok(Address { return Ok(Address {