X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Foffers%2Finvoice.rs;h=5bd5a95d8e627a3e69964db540fbffa554bbddf4;hb=0456b0e311a4996b00d715f9211adcabc06b37c7;hp=908d2d4bee6d2f6b9091ae0d62ce7e650cbfe754;hpb=448b191fec4c6d1e9638c82aade7385b1516aa5d;p=rust-lightning diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 908d2d4b..5bd5a95d 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -174,7 +174,7 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration, payment_hash: PaymentHash ) -> Result { - let amount_msats = Self::check_amount_msats(invoice_request)?; + let amount_msats = Self::amount_msats(invoice_request)?; let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), @@ -207,7 +207,7 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { invoice_request: &'a InvoiceRequest, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, created_at: Duration, payment_hash: PaymentHash, keys: KeyPair ) -> Result { - let amount_msats = Self::check_amount_msats(invoice_request)?; + let amount_msats = Self::amount_msats(invoice_request)?; let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), @@ -237,7 +237,9 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { } impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { - fn check_amount_msats(invoice_request: &InvoiceRequest) -> Result { + pub(crate) fn amount_msats( + invoice_request: &InvoiceRequest + ) -> Result { match invoice_request.amount_msats() { Some(amount_msats) => Ok(amount_msats), None => match invoice_request.contents.inner.offer.amount() { @@ -339,6 +341,12 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { } } + #[cfg(not(feature = "std"))] { + if self.invoice.is_offer_or_refund_expired_no_std(self.invoice.created_at()) { + return Err(Bolt12SemanticError::AlreadyExpired); + } + } + let InvoiceBuilder { invreq_bytes, invoice, .. } = self; Ok(UnsignedBolt12Invoice::new(invreq_bytes, invoice)) } @@ -355,6 +363,12 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { } } + #[cfg(not(feature = "std"))] { + if self.invoice.is_offer_or_refund_expired_no_std(self.invoice.created_at()) { + return Err(Bolt12SemanticError::AlreadyExpired); + } + } + let InvoiceBuilder { invreq_bytes, invoice, signing_pubkey_strategy: DerivedSigningPubkey(keys) } = self; @@ -425,6 +439,7 @@ impl UnsignedBolt12Invoice { bytes: self.bytes, contents: self.contents, signature, + tagged_hash: self.tagged_hash, }) } } @@ -449,6 +464,7 @@ pub struct Bolt12Invoice { bytes: Vec, contents: InvoiceContents, signature: Signature, + tagged_hash: TaggedHash, } /// The contents of an [`Bolt12Invoice`] for responding to either an [`Offer`] or a [`Refund`]. @@ -693,7 +709,7 @@ impl Bolt12Invoice { /// Hash that was used for signing the invoice. pub fn signable_hash(&self) -> [u8; 32] { - merkle::message_digest(SIGNATURE_TAG, &self.bytes).as_ref().clone() + self.tagged_hash.as_digest().as_ref().clone() } /// Verifies that the invoice was for a request or refund created using the given key. Returns @@ -727,6 +743,16 @@ impl InvoiceContents { } } + #[cfg(not(feature = "std"))] + fn is_offer_or_refund_expired_no_std(&self, duration_since_epoch: Duration) -> bool { + match self { + InvoiceContents::ForOffer { invoice_request, .. } => + invoice_request.inner.offer.is_expired_no_std(duration_since_epoch), + InvoiceContents::ForRefund { refund, .. } => + refund.is_expired_no_std(duration_since_epoch), + } + } + fn offer_chains(&self) -> Option> { match self { InvoiceContents::ForOffer { invoice_request, .. } => @@ -1188,11 +1214,11 @@ impl TryFrom> for Bolt12Invoice { None => return Err(Bolt12ParseError::InvalidSemantics(Bolt12SemanticError::MissingSignature)), Some(signature) => signature, }; - let message = TaggedHash::new(SIGNATURE_TAG, &bytes); + let tagged_hash = TaggedHash::new(SIGNATURE_TAG, &bytes); let pubkey = contents.fields().signing_pubkey; - merkle::verify_signature(&signature, message, pubkey)?; + merkle::verify_signature(&signature, &tagged_hash, pubkey)?; - Ok(Bolt12Invoice { bytes, contents, signature }) + Ok(Bolt12Invoice { bytes, contents, signature, tagged_hash }) } } @@ -1407,7 +1433,7 @@ mod tests { assert_eq!(invoice.signing_pubkey(), recipient_pubkey()); let message = TaggedHash::new(SIGNATURE_TAG, &invoice.bytes); - assert!(merkle::verify_signature(&invoice.signature, message, recipient_pubkey()).is_ok()); + assert!(merkle::verify_signature(&invoice.signature, &message, recipient_pubkey()).is_ok()); let digest = Message::from_slice(&invoice.signable_hash()).unwrap(); let pubkey = recipient_pubkey().into(); @@ -1504,7 +1530,7 @@ mod tests { assert_eq!(invoice.signing_pubkey(), recipient_pubkey()); let message = TaggedHash::new(SIGNATURE_TAG, &invoice.bytes); - assert!(merkle::verify_signature(&invoice.signature, message, recipient_pubkey()).is_ok()); + assert!(merkle::verify_signature(&invoice.signature, &message, recipient_pubkey()).is_ok()); assert_eq!( invoice.as_tlv_stream(),