@@ -8,8 +8,8 @@ use core::num::ParseIntError;
8
8
use core:: str;
9
9
use core:: str:: FromStr ;
10
10
11
+ use bech32:: primitives:: decode:: { CheckedHrpstring , CheckedHrpstringError } ;
11
12
use bech32:: { Bech32 , Fe32 , Fe32IterExt } ;
12
- use bech32:: primitives:: decode:: { CheckedHrpstring , CheckedHrpstringError , ChecksumError } ;
13
13
14
14
use bitcoin:: { PubkeyHash , ScriptHash , WitnessVersion } ;
15
15
use bitcoin:: hashes:: Hash ;
@@ -39,19 +39,37 @@ pub trait FromBase32: Sized {
39
39
// FromBase32 implementations are here, because the trait is in this module.
40
40
41
41
impl FromBase32 for Vec < u8 > {
42
- type Err = CheckedHrpstringError ;
42
+ type Err = Bolt11ParseError ;
43
43
44
44
fn from_base32 ( data : & [ Fe32 ] ) -> Result < Self , Self :: Err > {
45
45
Ok ( data. iter ( ) . copied ( ) . fes_to_bytes ( ) . collect :: < Self > ( ) )
46
46
}
47
47
}
48
48
49
+ impl < const N : usize > FromBase32 for [ u8 ; N ] {
50
+ type Err = Bolt11ParseError ;
51
+
52
+ fn from_base32 ( data : & [ Fe32 ] ) -> Result < Self , Self :: Err > {
53
+ data. iter ( ) . copied ( ) . fes_to_bytes ( ) . collect :: < Vec < _ > > ( ) . try_into ( ) . map_err ( |_| {
54
+ Bolt11ParseError :: InvalidSliceLength (
55
+ data. len ( ) ,
56
+ ( N * 8 + 4 ) / 5 ,
57
+ "<[u8; N]>::from_base32()" . into ( ) ,
58
+ )
59
+ } )
60
+ }
61
+ }
62
+
49
63
impl FromBase32 for PaymentSecret {
50
- type Err = CheckedHrpstringError ;
64
+ type Err = Bolt11ParseError ;
51
65
52
66
fn from_base32 ( field_data : & [ Fe32 ] ) -> Result < Self , Self :: Err > {
53
67
if field_data. len ( ) != 52 {
54
- return Err ( CheckedHrpstringError :: Checksum ( ChecksumError :: InvalidLength ) ) // TODO(bech32): not entirely accurate
68
+ return Err ( Bolt11ParseError :: InvalidSliceLength (
69
+ field_data. len ( ) ,
70
+ 52 ,
71
+ "PaymentSecret::from_base32()" . into ( ) ,
72
+ ) ) ;
55
73
}
56
74
let data_bytes = Vec :: < u8 > :: from_base32 ( field_data) ?;
57
75
let mut payment_secret = [ 0 ; 32 ] ;
@@ -61,28 +79,45 @@ impl FromBase32 for PaymentSecret {
61
79
}
62
80
63
81
impl FromBase32 for Bolt11InvoiceFeatures {
64
- type Err = CheckedHrpstringError ;
82
+ type Err = Bolt11ParseError ;
65
83
84
+ /// Convert to byte values, by packing the 5-bit groups,
85
+ /// putting the 5-bit values from left to-right (reverse order),
86
+ /// starting from the rightmost bit,
87
+ /// and taking the resulting 8-bit values (right to left),
88
+ /// with the leading 0's skipped.
66
89
fn from_base32 ( field_data : & [ Fe32 ] ) -> Result < Self , Self :: Err > {
67
- // Explanation for the "7": the normal way to round up when dividing is to add the divisor
68
- // minus one before dividing
69
- let length_bytes = ( field_data. len ( ) * 5 + 7 ) / 8 as usize ;
70
- let mut res_bytes: Vec < u8 > = vec ! [ 0 ; length_bytes] ;
71
- for ( u5_idx, chunk) in field_data. iter ( ) . enumerate ( ) {
72
- let bit_pos_from_right_0_indexed = ( field_data. len ( ) - u5_idx - 1 ) * 5 ;
73
- let new_byte_idx = ( bit_pos_from_right_0_indexed / 8 ) as usize ;
74
- let new_bit_pos = bit_pos_from_right_0_indexed % 8 ;
75
- let chunk_u16 = chunk. to_u8 ( ) as u16 ;
76
- res_bytes[ new_byte_idx] |= ( ( chunk_u16 << new_bit_pos) & 0xff ) as u8 ;
77
- if new_byte_idx != length_bytes - 1 {
78
- res_bytes[ new_byte_idx + 1 ] |= ( ( chunk_u16 >> ( 8 -new_bit_pos) ) & 0xff ) as u8 ;
90
+ // Fe32 conversion cannot be used, because this unpacks from right, right-to-left
91
+ // Carry bits, 0, 1, 2, 3, or 4 bits
92
+ let mut carry_bits = 0 ;
93
+ let mut carry = 0u8 ;
94
+ let mut output = Vec :: < u8 > :: new ( ) ;
95
+
96
+ // Iterate over input in reverse
97
+ for curr_in in field_data. iter ( ) . rev ( ) {
98
+ let curr_in_as_u8 = curr_in. to_u8 ( ) ;
99
+ if carry_bits >= 3 {
100
+ // we have a new full byte -- 3, 4 or 5 carry bits, plus 5 new ones
101
+ // For combining with carry '|', '^', or '+' can be used (disjoint bit positions)
102
+ let next = carry + ( curr_in_as_u8 << carry_bits) ;
103
+ output. push ( next) ;
104
+ carry = curr_in_as_u8 >> ( 8 - carry_bits) ;
105
+ carry_bits -= 3 ; // added 5, removed 8
106
+ } else {
107
+ // only 0, 1, or 2 carry bits, plus 5 new ones
108
+ carry += curr_in_as_u8 << carry_bits;
109
+ carry_bits += 5 ;
79
110
}
80
111
}
81
- // Trim the highest feature bits.
82
- while !res_bytes . is_empty ( ) && res_bytes [ res_bytes . len ( ) - 1 ] == 0 {
83
- res_bytes . pop ( ) ;
112
+ // No more inputs, output remaining (if any)
113
+ if carry_bits > 0 {
114
+ output . push ( carry ) ;
84
115
}
85
- Ok ( Bolt11InvoiceFeatures :: from_le_bytes ( res_bytes) )
116
+ // Trim the highest feature bits
117
+ while !output. is_empty ( ) && output[ output. len ( ) - 1 ] == 0 {
118
+ output. pop ( ) ;
119
+ }
120
+ Ok ( Bolt11InvoiceFeatures :: from_le_bytes ( output) )
86
121
}
87
122
}
88
123
@@ -342,7 +377,7 @@ impl FromStr for SignedRawBolt11Invoice {
342
377
}
343
378
344
379
let raw_hrp: RawHrp = hrp. to_string ( ) . to_lowercase ( ) . parse ( ) ?;
345
- let data_part = RawDataPart :: from_base32 ( & data[ ..data. len ( ) - SIGNATURE_LEN5 ] ) ?;
380
+ let data_part = RawDataPart :: from_base32 ( & data[ ..data. len ( ) - SIGNATURE_LEN5 ] ) ?;
346
381
347
382
Ok ( SignedRawBolt11Invoice {
348
383
raw_invoice : RawBolt11Invoice {
@@ -351,9 +386,9 @@ impl FromStr for SignedRawBolt11Invoice {
351
386
} ,
352
387
hash : RawBolt11Invoice :: hash_from_parts (
353
388
hrp. to_string ( ) . as_bytes ( ) ,
354
- & data[ ..data. len ( ) - SIGNATURE_LEN5 ]
389
+ & data[ ..data. len ( ) - SIGNATURE_LEN5 ] ,
355
390
) ,
356
- signature : Bolt11InvoiceSignature :: from_base32 ( & data[ data. len ( ) - SIGNATURE_LEN5 ..] ) ?,
391
+ signature : Bolt11InvoiceSignature :: from_base32 ( & data[ data. len ( ) - SIGNATURE_LEN5 ..] ) ?,
357
392
} )
358
393
}
359
394
}
@@ -415,7 +450,11 @@ impl FromBase32 for PositiveTimestamp {
415
450
416
451
fn from_base32 ( b32 : & [ Fe32 ] ) -> Result < Self , Self :: Err > {
417
452
if b32. len ( ) != 7 {
418
- return Err ( Bolt11ParseError :: InvalidSliceLength ( "PositiveTimestamp::from_base32()" . into ( ) ) ) ;
453
+ return Err ( Bolt11ParseError :: InvalidSliceLength (
454
+ b32. len ( ) ,
455
+ 7 ,
456
+ "PositiveTimestamp::from_base32()" . into ( ) ,
457
+ ) ) ;
419
458
}
420
459
let timestamp: u64 = parse_u64_be ( b32)
421
460
. expect ( "7*5bit < 64bit, no overflow possible" ) ;
@@ -430,7 +469,11 @@ impl FromBase32 for Bolt11InvoiceSignature {
430
469
type Err = Bolt11ParseError ;
431
470
fn from_base32 ( signature : & [ Fe32 ] ) -> Result < Self , Self :: Err > {
432
471
if signature. len ( ) != 104 {
433
- return Err ( Bolt11ParseError :: InvalidSliceLength ( "Bolt11InvoiceSignature::from_base32()" . into ( ) ) ) ;
472
+ return Err ( Bolt11ParseError :: InvalidSliceLength (
473
+ signature. len ( ) ,
474
+ 104 ,
475
+ "Bolt11InvoiceSignature::from_base32()" . into ( ) ,
476
+ ) ) ;
434
477
}
435
478
let recoverable_signature_bytes = Vec :: < u8 > :: from_base32 ( signature) ?;
436
479
let signature = & recoverable_signature_bytes[ 0 ..64 ] ;
@@ -483,7 +526,9 @@ fn parse_tagged_parts(data: &[Fe32]) -> Result<Vec<RawTaggedField>, Bolt11ParseE
483
526
Ok ( field) => {
484
527
parts. push ( RawTaggedField :: KnownSemantics ( field) )
485
528
} ,
486
- Err ( Bolt11ParseError :: Skip ) |Err ( Bolt11ParseError :: Bech32Error ( _) ) => {
529
+ Err ( Bolt11ParseError :: Skip )
530
+ | Err ( Bolt11ParseError :: InvalidSliceLength ( _, _, _) )
531
+ | Err ( Bolt11ParseError :: Bech32Error ( _) ) => {
487
532
parts. push ( RawTaggedField :: UnknownSemantics ( field. into ( ) ) )
488
533
} ,
489
534
Err ( e) => { return Err ( e) }
@@ -688,9 +733,6 @@ impl Display for Bolt11ParseError {
688
733
Bolt11ParseError :: Bech32Error ( ref e) => {
689
734
write ! ( f, "Invalid bech32: {}" , e)
690
735
}
691
- Bolt11ParseError :: GenericBech32Error => {
692
- write ! ( f, "Invalid bech32" )
693
- }
694
736
Bolt11ParseError :: ParseAmountError ( ref e) => {
695
737
write ! ( f, "Invalid amount in hrp ({})" , e)
696
738
}
@@ -700,9 +742,13 @@ impl Display for Bolt11ParseError {
700
742
Bolt11ParseError :: DescriptionDecodeError ( ref e) => {
701
743
write ! ( f, "Description is not a valid utf-8 string: {}" , e)
702
744
}
703
- Bolt11ParseError :: InvalidSliceLength ( ref function) => {
704
- write ! ( f, "Slice in function {} had the wrong length" , function)
705
- }
745
+ Bolt11ParseError :: InvalidSliceLength ( ref len, ref expected, ref function) => {
746
+ write ! (
747
+ f,
748
+ "Slice had length {} instead of {} in function {}" ,
749
+ len, expected, function
750
+ )
751
+ } ,
706
752
Bolt11ParseError :: BadPrefix => f. write_str ( "did not begin with 'ln'" ) ,
707
753
Bolt11ParseError :: UnknownCurrency => f. write_str ( "currency code unknown" ) ,
708
754
Bolt11ParseError :: UnknownSiPrefix => f. write_str ( "unknown SI prefix" ) ,
@@ -767,9 +813,7 @@ from_error!(Bolt11ParseError::DescriptionDecodeError, str::Utf8Error);
767
813
768
814
impl From < CheckedHrpstringError > for Bolt11ParseError {
769
815
fn from ( e : CheckedHrpstringError ) -> Self {
770
- match e {
771
- _ => Bolt11ParseError :: Bech32Error ( e)
772
- }
816
+ Self :: Bech32Error ( e)
773
817
}
774
818
}
775
819
0 commit comments