Skip to content

Commit 4bd258b

Browse files
committed
f - separate build and sign for missing semantic checking
1 parent b593f07 commit 4bd258b

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
@@ -53,7 +53,8 @@ const SIGNATURE_TAG: &'static str = concat!("lightning", "invoice_request", "sig
5353
/// .features(OfferFeatures::known())
5454
/// .quantity(5)?
5555
/// .payer_note("foo".to_string())
56-
/// .build_signed(|digest| secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))?
56+
/// .build()?
57+
/// .sign(|digest| secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))?
5758
/// .write(&mut buffer)
5859
/// .unwrap();
5960
/// # Ok(())
@@ -124,8 +125,35 @@ impl<'a> InvoiceRequestBuilder<'a> {
124125
self
125126
}
126127

127-
///
128-
pub fn build_signed<F>(self, sign: F) -> Result<InvoiceRequest, secp256k1::Error>
128+
/// Builds the [`InvoiceRequest`] after checking for valid semantics.
129+
pub fn build(self) -> Result<UnsignedInvoiceRequest<'a>, SemanticError> {
130+
let chain = self.invoice_request.chain.unwrap_or_else(|| self.offer.implied_chain());
131+
if !self.offer.supports_chain(chain) {
132+
return Err(SemanticError::UnsupportedChain);
133+
}
134+
135+
if self.offer.amount().is_some() && self.invoice_request.amount_msats.is_none() {
136+
return Err(SemanticError::MissingAmount);
137+
}
138+
139+
if self.offer.expects_quantity() && self.invoice_request.quantity.is_none() {
140+
return Err(SemanticError::InvalidQuantity);
141+
}
142+
143+
let InvoiceRequestBuilder { offer, invoice_request } = self;
144+
Ok(UnsignedInvoiceRequest { offer, invoice_request })
145+
}
146+
}
147+
148+
/// A semantically valid [`InvoiceRequest`] that hasn't been signed.
149+
pub struct UnsignedInvoiceRequest<'a> {
150+
offer: &'a Offer,
151+
invoice_request: InvoiceRequestContents,
152+
}
153+
154+
impl<'a> UnsignedInvoiceRequest<'a> {
155+
/// Signs the invoice request using the given function.
156+
pub fn sign<F>(self, sign: F) -> Result<InvoiceRequest, secp256k1::Error>
129157
where F: FnOnce(&Message) -> Signature
130158
{
131159
// 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
@@ -181,6 +181,10 @@ impl Offer {
181181
self.contents.supports_chain(chain)
182182
}
183183

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

0 commit comments

Comments
 (0)