@@ -89,7 +89,8 @@ impl FromBase32 for Bolt11InvoiceFeatures {
89
89
// Carry bits, 0, 1, 2, 3, or 4 bits
90
90
let mut carry_bits = 0 ;
91
91
let mut carry = 0u8 ;
92
- let mut output = Vec :: < u8 > :: new ( ) ;
92
+ let expected_raw_length = ( field_data. len ( ) * 5 + 7 ) / 8 ;
93
+ let mut output = Vec :: < u8 > :: with_capacity ( expected_raw_length) ;
93
94
94
95
// Iterate over input in reverse
95
96
for curr_in in field_data. iter ( ) . rev ( ) {
@@ -107,14 +108,21 @@ impl FromBase32 for Bolt11InvoiceFeatures {
107
108
carry_bits += 5 ;
108
109
}
109
110
}
111
+
110
112
// No more inputs, output remaining (if any)
111
113
if carry_bits > 0 {
112
114
output. push ( carry) ;
113
115
}
116
+
117
+ // This is to double check the estimated length and
118
+ // satisfying mutation test on the capacity, which is mutatable
119
+ debug_assert_eq ! ( output. len( ) , expected_raw_length) ;
120
+
114
121
// Trim the highest feature bits
115
122
while !output. is_empty ( ) && output[ output. len ( ) - 1 ] == 0 {
116
123
output. pop ( ) ;
117
124
}
125
+
118
126
Ok ( Bolt11InvoiceFeatures :: from_le_bytes ( output) )
119
127
}
120
128
}
@@ -364,7 +372,7 @@ impl FromStr for SignedRawBolt11Invoice {
364
372
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
365
373
let parsed = CheckedHrpstring :: new :: < Bech32 > ( s) ?;
366
374
let hrp = parsed. hrp ( ) ;
367
- // Access original non-packed 32 byte values (as Fe32s)
375
+ // Access original non-packed 32 byte values (as Fe32s) (iterator type is needed for API hack)
368
376
let data: Vec < _ > = parsed. fe32_iter :: < alloc:: boxed:: Box < dyn Iterator < Item = u8 > > > ( ) . collect ( ) ;
369
377
370
378
const SIGNATURE_LEN5 : usize = 104 ; // 32-bit values, 65 bytes
@@ -470,7 +478,7 @@ impl FromBase32 for Bolt11InvoiceSignature {
470
478
"Bolt11InvoiceSignature::from_base32()" . into ( ) ,
471
479
) ) ;
472
480
}
473
- let recoverable_signature_bytes = Vec :: < u8 > :: from_base32 ( signature) ?;
481
+ let recoverable_signature_bytes = < [ u8 ; 65 ] >:: from_base32 ( signature) ?;
474
482
let signature = & recoverable_signature_bytes[ 0 ..64 ] ;
475
483
let recovery_id = RecoveryId :: from_i32 ( recoverable_signature_bytes[ 64 ] as i32 ) ?;
476
484
@@ -582,7 +590,7 @@ impl FromBase32 for Sha256 {
582
590
// "A reader MUST skip over […] a p, [or] h […] field that does not have data_length 52 […]."
583
591
Err ( Bolt11ParseError :: Skip )
584
592
} else {
585
- Ok ( Sha256 ( sha256:: Hash :: from_slice ( & Vec :: < u8 > :: from_base32 ( field_data) ?)
593
+ Ok ( Sha256 ( sha256:: Hash :: from_slice ( & < [ u8 ; 32 ] >:: from_base32 ( field_data) ?)
586
594
. expect ( "length was checked before (52 u5 -> 32 u8)" ) ) )
587
595
}
588
596
}
@@ -608,7 +616,7 @@ impl FromBase32 for PayeePubKey {
608
616
// "A reader MUST skip over […] a n […] field that does not have data_length 53 […]."
609
617
Err ( Bolt11ParseError :: Skip )
610
618
} else {
611
- let data_bytes = Vec :: < u8 > :: from_base32 ( field_data) ?;
619
+ let data_bytes = < [ u8 ; 33 ] >:: from_base32 ( field_data) ?;
612
620
let pub_key = PublicKey :: from_slice ( & data_bytes) ?;
613
621
Ok ( pub_key. into ( ) )
614
622
}
0 commit comments