bech32/primitives/
segwit.rs1use core::fmt;
9
10use crate::primitives::gf32::Fe32;
11
12pub const MAX_STRING_LENGTH: usize = 90;
19
20pub const VERSION_0: Fe32 = Fe32::Q;
22pub const VERSION_1: Fe32 = Fe32::P;
24
25pub fn is_valid_witness_version(witness_version: Fe32) -> bool {
27 validate_witness_version(witness_version).is_ok()
28}
29
30pub fn is_valid_witness_program_length(length: usize, witness_version: Fe32) -> bool {
32 validate_witness_program_length(length, witness_version).is_ok()
33}
34
35pub fn validate_witness_version(witness_version: Fe32) -> Result<(), InvalidWitnessVersionError> {
37 if witness_version.to_u8() > 16 {
38 Err(InvalidWitnessVersionError(witness_version))
39 } else {
40 Ok(())
41 }
42}
43
44pub fn validate_witness_program_length(
46 length: usize,
47 version: Fe32,
48) -> Result<(), WitnessLengthError> {
49 use WitnessLengthError::*;
50
51 if length < 2 {
52 return Err(TooShort);
53 }
54 if length > 40 {
55 return Err(TooLong);
56 }
57 if version == VERSION_0 && length != 20 && length != 32 {
58 return Err(InvalidSegwitV0);
59 }
60 Ok(())
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
65#[non_exhaustive]
66pub struct InvalidWitnessVersionError(pub Fe32);
67
68#[rustfmt::skip]
69impl fmt::Display for InvalidWitnessVersionError {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71 write!(f, "invalid segwit witness version: {} (bech32 character: '{}')", self.0.to_u8(), self.0)
72 }
73}
74
75#[cfg(feature = "std")]
76impl std::error::Error for InvalidWitnessVersionError {
77 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
82#[non_exhaustive]
83pub enum WitnessLengthError {
84 TooShort,
86 TooLong,
88 InvalidSegwitV0,
90}
91
92impl fmt::Display for WitnessLengthError {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 use WitnessLengthError::*;
95
96 match *self {
97 TooShort => write!(f, "witness program is less than 2 bytes long"),
98 TooLong => write!(f, "witness program is more than 40 bytes long"),
99 InvalidSegwitV0 => write!(f, "the segwit v0 witness is not 20 or 32 bytes long"),
100 }
101 }
102}
103
104#[cfg(feature = "std")]
105impl std::error::Error for WitnessLengthError {
106 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
107 use WitnessLengthError::*;
108
109 match *self {
110 TooShort | TooLong | InvalidSegwitV0 => None,
111 }
112 }
113}