X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Foffers%2Finvoice.rs;h=d432e2e139cb89cdd384b74be3142c0c543d0eba;hb=93afed56e8befba47199c19b4ca8263164eca36f;hp=1635d956cbe88d0b55f5726836eae926cac942bf;hpb=e1a6bc3cadb8c89ba38afb5846fb80f349d99449;p=rust-lightning diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 1635d956..d432e2e1 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -29,7 +29,7 @@ //! //! # use lightning::ln::PaymentHash; //! # use lightning::offers::invoice::BlindedPayInfo; -//! # use lightning::onion_message::BlindedPath; +//! # use lightning::blinded_path::BlindedPath; //! # //! # fn create_payment_paths() -> Vec<(BlindedPath, BlindedPayInfo)> { unimplemented!() } //! # fn create_payment_hash() -> PaymentHash { unimplemented!() } @@ -104,6 +104,7 @@ use bitcoin::util::schnorr::TweakedPublicKey; use core::convert::{Infallible, TryFrom}; use core::time::Duration; use crate::io; +use crate::blinded_path::BlindedPath; use crate::ln::PaymentHash; use crate::ln::features::{BlindedHopFeatures, Bolt12InvoiceFeatures}; use crate::ln::inbound_payment::ExpandedKey; @@ -115,7 +116,6 @@ use crate::offers::parse::{ParseError, ParsedMessage, SemanticError}; use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef}; use crate::offers::refund::{IV_BYTES as REFUND_IV_BYTES, Refund, RefundContents}; use crate::offers::signer; -use crate::onion_message::BlindedPath; use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer}; use crate::prelude::*; @@ -161,13 +161,12 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { created_at: Duration, payment_hash: PaymentHash ) -> Result { let amount_msats = Self::check_amount_msats(invoice_request)?; + let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, - fallbacks: None, features: Bolt12InvoiceFeatures::empty(), - signing_pubkey: invoice_request.contents.inner.offer.signing_pubkey(), - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&invoice_request.bytes, contents, None) @@ -177,13 +176,12 @@ impl<'a> InvoiceBuilder<'a, ExplicitSigningPubkey> { refund: &'a Refund, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, created_at: Duration, payment_hash: PaymentHash, signing_pubkey: PublicKey ) -> Result { + let amount_msats = refund.amount_msats(); let contents = InvoiceContents::ForRefund { refund: refund.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, - amount_msats: refund.amount_msats(), fallbacks: None, - features: Bolt12InvoiceFeatures::empty(), signing_pubkey, - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&refund.bytes, contents, None) @@ -196,17 +194,32 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { created_at: Duration, payment_hash: PaymentHash, keys: KeyPair ) -> Result { let amount_msats = Self::check_amount_msats(invoice_request)?; + let signing_pubkey = invoice_request.contents.inner.offer.signing_pubkey(); let contents = InvoiceContents::ForOffer { invoice_request: invoice_request.contents.clone(), - fields: InvoiceFields { - payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, - fallbacks: None, features: Bolt12InvoiceFeatures::empty(), - signing_pubkey: invoice_request.contents.inner.offer.signing_pubkey(), - }, + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), }; Self::new(&invoice_request.bytes, contents, Some(keys)) } + + pub(super) fn for_refund_using_keys( + refund: &'a Refund, payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, created_at: Duration, + payment_hash: PaymentHash, keys: KeyPair, + ) -> Result { + let amount_msats = refund.amount_msats(); + let signing_pubkey = keys.public_key(); + let contents = InvoiceContents::ForRefund { + refund: refund.contents.clone(), + fields: Self::fields( + payment_paths, created_at, payment_hash, amount_msats, signing_pubkey + ), + }; + + Self::new(&refund.bytes, contents, Some(keys)) + } } impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { @@ -224,6 +237,16 @@ impl<'a, S: SigningPubkeyStrategy> InvoiceBuilder<'a, S> { } } + fn fields( + payment_paths: Vec<(BlindedPath, BlindedPayInfo)>, created_at: Duration, + payment_hash: PaymentHash, amount_msats: u64, signing_pubkey: PublicKey + ) -> InvoiceFields { + InvoiceFields { + payment_paths, created_at, relative_expiry: None, payment_hash, amount_msats, + fallbacks: None, features: Bolt12InvoiceFeatures::empty(), signing_pubkey, + } + } + fn new( invreq_bytes: &'a Vec, contents: InvoiceContents, keys: Option ) -> Result { @@ -322,12 +345,9 @@ impl<'a> InvoiceBuilder<'a, DerivedSigningPubkey> { } let InvoiceBuilder { invreq_bytes, invoice, keys, .. } = self; - let keys = match &invoice { - InvoiceContents::ForOffer { .. } => keys.unwrap(), - InvoiceContents::ForRefund { .. } => unreachable!(), - }; - let unsigned_invoice = UnsignedInvoice { invreq_bytes, invoice }; + + let keys = keys.unwrap(); let invoice = unsigned_invoice .sign::<_, Infallible>(|digest| Ok(secp_ctx.sign_schnorr_no_aux_rand(digest, &keys))) .unwrap(); @@ -712,7 +732,7 @@ type BlindedPayInfoIter<'a> = core::iter::Map< >; /// Information needed to route a payment across a [`BlindedPath`]. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Hash, Eq, PartialEq)] pub struct BlindedPayInfo { /// Base fee charged (in millisatoshi) for the entire blinded path. pub fee_base_msat: u32, @@ -906,6 +926,7 @@ mod tests { use bitcoin::util::schnorr::TweakedPublicKey; use core::convert::TryFrom; use core::time::Duration; + use crate::blinded_path::{BlindedHop, BlindedPath}; use crate::chain::keysinterface::KeyMaterial; use crate::ln::features::Bolt12InvoiceFeatures; use crate::ln::inbound_payment::ExpandedKey; @@ -917,7 +938,6 @@ mod tests { use crate::offers::payer::PayerTlvStreamRef; use crate::offers::refund::RefundBuilder; use crate::offers::test_utils::*; - use crate::onion_message::{BlindedHop, BlindedPath}; use crate::util::ser::{BigSize, Iterable, Writeable}; trait ToBytes { @@ -1223,6 +1243,26 @@ mod tests { } } + #[test] + fn builds_invoice_from_refund_using_derived_keys() { + let expanded_key = ExpandedKey::new(&KeyMaterial([42; 32])); + let entropy = FixedEntropy {}; + let secp_ctx = Secp256k1::new(); + + let refund = RefundBuilder::new("foo".into(), vec![1; 32], payer_pubkey(), 1000).unwrap() + .build().unwrap(); + + if let Err(e) = refund + .respond_using_derived_keys_no_std( + payment_paths(), payment_hash(), now(), &expanded_key, &entropy + ) + .unwrap() + .build_and_sign(&secp_ctx) + { + panic!("error building invoice: {:?}", e); + } + } + #[test] fn builds_invoice_with_relative_expiry() { let now = now();