11
11
12
12
use bitcoin:: blockdata:: constants:: ChainHash ;
13
13
use bitcoin:: network:: constants:: Network ;
14
+ use bitcoin:: secp256k1:: PublicKey ;
14
15
use bitcoin:: secp256k1:: schnorr:: Signature ;
15
16
use bitcoin:: util:: address:: { Address , Payload , WitnessVersion } ;
16
17
use core:: convert:: TryFrom ;
@@ -48,7 +49,7 @@ const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice", "signature")
48
49
pub struct Invoice {
49
50
bytes : Vec < u8 > ,
50
51
contents : InvoiceContents ,
51
- signature : Option < Signature > ,
52
+ signature : Signature ,
52
53
}
53
54
54
55
/// The contents of an [`Invoice`] for responding to either an [`Offer`] or a [`Refund`].
@@ -82,7 +83,7 @@ struct InvoiceFields {
82
83
amount_msats : u64 ,
83
84
fallbacks : Option < Vec < FallbackAddress > > ,
84
85
features : Bolt12InvoiceFeatures ,
85
- code : Option < String > ,
86
+ signing_pubkey : PublicKey ,
86
87
}
87
88
88
89
impl Invoice {
@@ -186,16 +187,13 @@ impl Invoice {
186
187
& self . contents . fields ( ) . features
187
188
}
188
189
189
- /// A short string used for verifying the recipient when issuing a refund. The payer should only
190
- /// pay the invoice after confirming with recipient out-of-band that this code is correct.
191
- pub fn code ( & self ) -> Option < & str > {
192
- self . contents . fields ( ) . code . as_ref ( ) . map ( |code| code. as_str ( ) )
190
+ /// The public key used to sign invoices.
191
+ pub fn signing_pubkey ( & self ) -> PublicKey {
192
+ self . contents . fields ( ) . signing_pubkey
193
193
}
194
194
195
- /// Signature of the invoice using [`signing_pubkey`]. `None` for invoices paying refunds.
196
- ///
197
- /// [`signing_pubkey`]: crate::offers::offer::Offer::signing_pubkey
198
- pub fn signature ( & self ) -> Option < Signature > {
195
+ /// Signature of the invoice using [`Invoice::signing_pubkey`].
196
+ pub fn signature ( & self ) -> Signature {
199
197
self . signature
200
198
}
201
199
}
@@ -240,7 +238,7 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef, 160..240, {
240
238
( 170 , amount: ( u64 , HighZeroBytesDroppedBigSize ) ) ,
241
239
( 172 , fallbacks: ( Vec <FallbackAddress >, WithoutLength ) ) ,
242
240
( 174 , features: ( Bolt12InvoiceFeatures , WithoutLength ) ) ,
243
- ( 176 , code : ( String , WithoutLength ) ) ,
241
+ ( 176 , node_id : PublicKey ) ,
244
242
} ) ;
245
243
246
244
/// Information needed to route a payment across a [`BlindedPath`] hop.
@@ -303,18 +301,12 @@ impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Invoice {
303
301
( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream)
304
302
) ?;
305
303
306
- match & contents {
307
- InvoiceContents :: ForOffer { invoice_request, .. } => match & signature {
308
- None => return Err ( ParseError :: InvalidSemantics ( SemanticError :: MissingSignature ) ) ,
309
- Some ( signature) => {
310
- let pubkey = invoice_request. offer . signing_pubkey ( ) ;
311
- merkle:: verify_signature ( signature, SIGNATURE_TAG , & bytes, pubkey) ?;
312
- } ,
313
- } ,
314
- InvoiceContents :: ForRefund { .. } => if let Some ( _) = & signature {
315
- return Err ( ParseError :: InvalidSemantics ( SemanticError :: UnexpectedSignature ) ) ;
316
- } ,
317
- }
304
+ let signature = match signature {
305
+ None => return Err ( ParseError :: InvalidSemantics ( SemanticError :: MissingSignature ) ) ,
306
+ Some ( signature) => signature,
307
+ } ;
308
+ let pubkey = contents. fields ( ) . signing_pubkey ;
309
+ merkle:: verify_signature ( & signature, SIGNATURE_TAG , & bytes, pubkey) ?;
318
310
319
311
Ok ( Invoice { bytes, contents, signature } )
320
312
}
@@ -330,7 +322,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
330
322
invoice_request_tlv_stream,
331
323
InvoiceTlvStream {
332
324
paths, blindedpay, created_at, relative_expiry, payment_hash, amount, fallbacks,
333
- features, code ,
325
+ features, node_id ,
334
326
} ,
335
327
) = tlv_stream;
336
328
@@ -365,17 +357,18 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
365
357
366
358
let features = features. unwrap_or_else ( Bolt12InvoiceFeatures :: empty) ;
367
359
360
+ let signing_pubkey = match node_id {
361
+ None => return Err ( SemanticError :: MissingSigningPubkey ) ,
362
+ Some ( node_id) => node_id,
363
+ } ;
364
+
368
365
let fields = InvoiceFields {
369
366
paths, payinfo, created_at, relative_expiry, payment_hash, amount_msats, fallbacks,
370
- features, code ,
367
+ features, signing_pubkey ,
371
368
} ;
372
369
373
370
match offer_tlv_stream. node_id {
374
371
Some ( _) => {
375
- if fields. code . is_some ( ) {
376
- return Err ( SemanticError :: UnexpectedCode ) ;
377
- }
378
-
379
372
let invoice_request = InvoiceRequestContents :: try_from (
380
373
( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
381
374
) ?;
0 commit comments