@@ -13,7 +13,7 @@ use bitcoin::hashes::{Hash, HashEngine, sha256};
13
13
use bitcoin:: secp256k1:: { Message , PublicKey , Secp256k1 , self } ;
14
14
use bitcoin:: secp256k1:: schnorr:: Signature ;
15
15
use crate :: io;
16
- use crate :: util:: ser:: { BigSize , Readable } ;
16
+ use crate :: util:: ser:: { BigSize , Readable , Writeable , Writer } ;
17
17
18
18
use crate :: prelude:: * ;
19
19
@@ -194,14 +194,33 @@ impl<'a> Iterator for TlvStream<'a> {
194
194
}
195
195
}
196
196
197
+ /// Encoding for a pre-serialized TLV stream by excluding any signature TLV records.
198
+ ///
199
+ /// Panics if the wrapped bytes is not a well-formed TLV stream.
200
+ pub ( super ) struct WithoutSignatures < ' a > ( pub & ' a Vec < u8 > ) ;
201
+
202
+ impl < ' a > Writeable for WithoutSignatures < ' a > {
203
+ #[ inline]
204
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
205
+ let tlv_stream = TlvStream :: new ( & self . 0 [ ..] ) ;
206
+ for record in tlv_stream. skip_signatures ( ) {
207
+ writer. write_all ( record. record_bytes ) ?;
208
+ }
209
+ Ok ( ( ) )
210
+ }
211
+ }
212
+
197
213
#[ cfg( test) ]
198
214
mod tests {
215
+ use super :: { TlvStream , WithoutSignatures } ;
216
+
199
217
use bitcoin:: hashes:: { Hash , sha256} ;
200
218
use bitcoin:: secp256k1:: { KeyPair , Secp256k1 , SecretKey } ;
201
219
use core:: convert:: Infallible ;
202
220
use crate :: offers:: offer:: { Amount , OfferBuilder } ;
203
221
use crate :: offers:: invoice_request:: InvoiceRequest ;
204
222
use crate :: offers:: parse:: Bech32Encode ;
223
+ use crate :: util:: ser:: Writeable ;
205
224
206
225
#[ test]
207
226
fn calculates_merkle_root_hash ( ) {
@@ -253,6 +272,36 @@ mod tests {
253
272
) ;
254
273
}
255
274
275
+ #[ test]
276
+ fn skips_encoding_signature_tlv_records ( ) {
277
+ let secp_ctx = Secp256k1 :: new ( ) ;
278
+ let recipient_pubkey = {
279
+ let secret_key = SecretKey :: from_slice ( & [ 41 ; 32 ] ) . unwrap ( ) ;
280
+ KeyPair :: from_secret_key ( & secp_ctx, & secret_key) . public_key ( )
281
+ } ;
282
+ let payer_keys = {
283
+ let secret_key = SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ;
284
+ KeyPair :: from_secret_key ( & secp_ctx, & secret_key)
285
+ } ;
286
+
287
+ let invoice_request = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey)
288
+ . amount_msats ( 100 )
289
+ . build_unchecked ( )
290
+ . request_invoice ( vec ! [ 0 ; 8 ] , payer_keys. public_key ( ) ) . unwrap ( )
291
+ . build_unchecked ( )
292
+ . sign :: < _ , Infallible > ( |digest| Ok ( secp_ctx. sign_schnorr_no_aux_rand ( digest, & payer_keys) ) )
293
+ . unwrap ( ) ;
294
+
295
+ let mut bytes_without_signature = Vec :: new ( ) ;
296
+ WithoutSignatures ( & invoice_request. bytes ) . write ( & mut bytes_without_signature) . unwrap ( ) ;
297
+
298
+ assert_ne ! ( bytes_without_signature, invoice_request. bytes) ;
299
+ assert_eq ! (
300
+ TlvStream :: new( & bytes_without_signature) . count( ) ,
301
+ TlvStream :: new( & invoice_request. bytes) . count( ) - 1 ,
302
+ ) ;
303
+ }
304
+
256
305
impl AsRef < [ u8 ] > for InvoiceRequest {
257
306
fn as_ref ( & self ) -> & [ u8 ] {
258
307
& self . bytes
0 commit comments