Skip to content

Commit 776bd30

Browse files
committed
Remove Option from InvoiceRequest::signature
Refunds don't have signatures and now use their own abstraction. Therefore, signatures can be required in invoice requests as per the spec.
1 parent 0ebd19a commit 776bd30

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

lightning/src/offers/invoice_request.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,11 @@ impl<'a> UnsignedInvoiceRequest<'a> {
223223
unsigned_tlv_stream.write(&mut bytes).unwrap();
224224

225225
let pubkey = self.invoice_request.payer_id;
226-
let signature = Some(merkle::sign_message(sign, SIGNATURE_TAG, &bytes, pubkey)?);
226+
let signature = merkle::sign_message(sign, SIGNATURE_TAG, &bytes, pubkey)?;
227227

228228
// Append the signature TLV record to the bytes.
229229
let signature_tlv_stream = SignatureTlvStreamRef {
230-
signature: signature.as_ref(),
230+
signature: Some(&signature),
231231
};
232232
signature_tlv_stream.write(&mut bytes).unwrap();
233233

@@ -249,7 +249,7 @@ impl<'a> UnsignedInvoiceRequest<'a> {
249249
pub struct InvoiceRequest {
250250
pub(super) bytes: Vec<u8>,
251251
contents: InvoiceRequestContents,
252-
signature: Option<Signature>,
252+
signature: Signature,
253253
}
254254

255255
/// The contents of an [`InvoiceRequest`], which may be shared with an `Invoice`.
@@ -311,7 +311,7 @@ impl InvoiceRequest {
311311
/// Signature of the invoice request using [`payer_id`].
312312
///
313313
/// [`payer_id`]: Self::payer_id
314-
pub fn signature(&self) -> Option<Signature> {
314+
pub fn signature(&self) -> Signature {
315315
self.signature
316316
}
317317

@@ -320,7 +320,7 @@ impl InvoiceRequest {
320320
let (payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
321321
self.contents.as_tlv_stream();
322322
let signature_tlv_stream = SignatureTlvStreamRef {
323-
signature: self.signature.as_ref(),
323+
signature: Some(&self.signature),
324324
};
325325
(payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream)
326326
}
@@ -421,9 +421,11 @@ impl TryFrom<Vec<u8>> for InvoiceRequest {
421421
(payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream)
422422
)?;
423423

424-
if let Some(signature) = &signature {
425-
merkle::verify_signature(signature, SIGNATURE_TAG, &bytes, contents.payer_id)?;
426-
}
424+
let signature = match signature {
425+
None => return Err(ParseError::InvalidSemantics(SemanticError::MissingSignature)),
426+
Some(signature) => signature,
427+
};
428+
merkle::verify_signature(&signature, SIGNATURE_TAG, &bytes, contents.payer_id)?;
427429

428430
Ok(InvoiceRequest { bytes, contents, signature })
429431
}
@@ -471,7 +473,7 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
471473

472474
#[cfg(test)]
473475
mod tests {
474-
use super::{InvoiceRequest, InvoiceRequestTlvStreamRef};
476+
use super::{InvoiceRequest, InvoiceRequestTlvStreamRef, SIGNATURE_TAG};
475477

476478
use bitcoin::blockdata::constants::ChainHash;
477479
use bitcoin::network::constants::Network;
@@ -483,7 +485,7 @@ mod tests {
483485
use core::time::Duration;
484486
use crate::ln::features::InvoiceRequestFeatures;
485487
use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT};
486-
use crate::offers::merkle::{SignError, SignatureTlvStreamRef};
488+
use crate::offers::merkle::{SignError, SignatureTlvStreamRef, self};
487489
use crate::offers::offer::{Amount, OfferBuilder, OfferTlvStreamRef, Quantity};
488490
use crate::offers::parse::{ParseError, SemanticError};
489491
use crate::offers::payer::PayerTlvStreamRef;
@@ -536,7 +538,11 @@ mod tests {
536538
assert_eq!(invoice_request.quantity(), None);
537539
assert_eq!(invoice_request.payer_id(), payer_pubkey());
538540
assert_eq!(invoice_request.payer_note(), None);
539-
assert!(invoice_request.signature().is_some());
541+
assert!(
542+
merkle::verify_signature(
543+
&invoice_request.signature, SIGNATURE_TAG, &invoice_request.bytes, payer_pubkey()
544+
).is_ok()
545+
);
540546

541547
assert_eq!(
542548
invoice_request.as_tlv_stream(),
@@ -563,7 +569,7 @@ mod tests {
563569
payer_id: Some(&payer_pubkey()),
564570
payer_note: None,
565571
},
566-
SignatureTlvStreamRef { signature: invoice_request.signature().as_ref() },
572+
SignatureTlvStreamRef { signature: Some(&invoice_request.signature()) },
567573
),
568574
);
569575

@@ -1222,7 +1228,7 @@ mod tests {
12221228
}
12231229

12241230
#[test]
1225-
fn parses_invoice_request_without_signature() {
1231+
fn fails_parsing_invoice_request_without_signature() {
12261232
let mut buffer = Vec::new();
12271233
OfferBuilder::new("foo".into(), recipient_pubkey())
12281234
.amount_msats(1000)
@@ -1232,8 +1238,9 @@ mod tests {
12321238
.invoice_request
12331239
.write(&mut buffer).unwrap();
12341240

1235-
if let Err(e) = InvoiceRequest::try_from(buffer) {
1236-
panic!("error parsing invoice_request: {:?}", e);
1241+
match InvoiceRequest::try_from(buffer) {
1242+
Ok(_) => panic!("expected error"),
1243+
Err(e) => assert_eq!(e, ParseError::InvalidSemantics(SemanticError::MissingSignature)),
12371244
}
12381245
}
12391246

lightning/src/offers/parse.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ pub enum SemanticError {
159159
MissingPayerMetadata,
160160
/// A payer id was expected but was missing.
161161
MissingPayerId,
162+
/// A signature was expected but was missing.
163+
MissingSignature,
162164
}
163165

164166
impl From<bech32::Error> for ParseError {

0 commit comments

Comments
 (0)