Skip to content

Commit 522276c

Browse files
committed
f - separate build and sign for missing semantic checking
1 parent b42ef4f commit 522276c

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

lightning/src/offers/invoice_request.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice_request", "sig
5454
/// .features(OfferFeatures::known())
5555
/// .quantity(5)?
5656
/// .payer_note("foo".to_string())
57-
/// .build_signed(|digest| secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))?
57+
/// .build()?
58+
/// .sign(|digest| secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))?
5859
/// .write(&mut buffer)
5960
/// .unwrap();
6061
/// # Ok(())
@@ -126,8 +127,35 @@ impl<'a> InvoiceRequestBuilder<'a> {
126127
self
127128
}
128129

129-
///
130-
pub fn build_signed<F>(mut self, sign: F) -> Result<InvoiceRequest, secp256k1::Error>
130+
/// Builds the [`InvoiceRequest`] after checking for valid semantics.
131+
pub fn build(self) -> Result<UnsignedInvoiceRequest<'a>, SemanticError> {
132+
let chain = self.invoice_request.chain.unwrap_or_else(|| self.offer.implied_chain());
133+
if !self.offer.supports_chain(chain) {
134+
return Err(SemanticError::UnsupportedChain);
135+
}
136+
137+
if self.offer.amount().is_some() && self.invoice_request.amount_msats.is_none() {
138+
return Err(SemanticError::MissingAmount);
139+
}
140+
141+
if self.offer.expects_quantity() && self.invoice_request.quantity.is_none() {
142+
return Err(SemanticError::InvalidQuantity);
143+
}
144+
145+
let InvoiceRequestBuilder { offer, invoice_request } = self;
146+
Ok(UnsignedInvoiceRequest { offer, invoice_request })
147+
}
148+
}
149+
150+
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
151+
pub struct UnsignedInvoiceRequest<'a> {
152+
offer: &'a Offer,
153+
invoice_request: InvoiceRequestContents,
154+
}
155+
156+
impl<'a> UnsignedInvoiceRequest<'a> {
157+
/// Signs the invoice request using the given function.
158+
pub fn sign<F>(mut self, sign: F) -> Result<InvoiceRequest, secp256k1::Error>
131159
where F: FnOnce(&Message) -> Signature
132160
{
133161
// Use the offer bytes instead of the offer TLV stream as the offer may have contained

lightning/src/offers/offer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ impl Offer {
182182
self.contents.supports_chain(chain)
183183
}
184184

185+
pub(super) fn implied_chain(&self) -> BlockHash {
186+
self.contents.implied_chain()
187+
}
188+
185189
///
186190
pub fn metadata(&self) -> Option<&Vec<u8>> {
187191
self.contents.metadata.as_ref()

0 commit comments

Comments
 (0)