X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Foffers%2Frefund.rs;h=03253fb6400bfe2c1261fcb2b00f13bc6eff1779;hb=195e666953afef108ed4c47abba8b6414f8f15fc;hp=f4e9c4a8cc782978273ace12889751e0d1d4921c;hpb=b1ad95158e8cea0119df31fb5318a31fcc70e927;p=rust-lightning diff --git a/lightning/src/offers/refund.rs b/lightning/src/offers/refund.rs index f4e9c4a8..03253fb6 100644 --- a/lightning/src/offers/refund.rs +++ b/lightning/src/offers/refund.rs @@ -84,7 +84,7 @@ use bitcoin::blockdata::constants::ChainHash; use bitcoin::network::constants::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; -use core::convert::TryFrom; +use core::hash::{Hash, Hasher}; use core::ops::Deref; use core::str::FromStr; use core::time::Duration; @@ -96,7 +96,7 @@ use crate::ln::channelmanager::PaymentId; use crate::ln::features::InvoiceRequestFeatures; use crate::ln::inbound_payment::{ExpandedKey, IV_LEN, Nonce}; use crate::ln::msgs::{DecodeError, MAX_VALUE_MSAT}; -use crate::offers::invoice::{BlindedPayInfo, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}; +use crate::offers::invoice::BlindedPayInfo; use crate::offers::invoice_request::{InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef}; use crate::offers::offer::{OfferTlvStream, OfferTlvStreamRef}; use crate::offers::parse::{Bech32Encode, Bolt12ParseError, Bolt12SemanticError, ParsedMessage}; @@ -105,6 +105,16 @@ use crate::offers::signer::{Metadata, MetadataMaterial, self}; use crate::util::ser::{SeekReadable, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; +#[cfg(not(c_bindings))] +use { + crate::offers::invoice::{DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder}, +}; +#[cfg(c_bindings)] +use { + crate::offers::invoice::{InvoiceWithDerivedSigningPubkeyBuilder, InvoiceWithExplicitSigningPubkeyBuilder}, +}; + +#[allow(unused_imports)] use crate::prelude::*; #[cfg(feature = "std")] @@ -365,6 +375,16 @@ for RefundMaybeWithDerivedMetadataBuilder<'a> { } } +#[cfg(c_bindings)] +impl<'a> From> +for RefundBuilder<'a, secp256k1::All> { + fn from(builder: RefundMaybeWithDerivedMetadataBuilder<'a>) -> Self { + let RefundMaybeWithDerivedMetadataBuilder { refund, secp_ctx } = builder; + + Self { refund, secp_ctx } + } +} + /// A `Refund` is a request to send an [`Bolt12Invoice`] without a preceding [`Offer`]. /// /// Typically, after an invoice is paid, the recipient may publish a refund allowing the sender to @@ -374,7 +394,6 @@ for RefundMaybeWithDerivedMetadataBuilder<'a> { /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice /// [`Offer`]: crate::offers::offer::Offer #[derive(Clone, Debug)] -#[cfg_attr(test, derive(PartialEq))] pub struct Refund { pub(super) bytes: Vec, pub(super) contents: RefundContents, @@ -480,7 +499,9 @@ impl Refund { pub fn payer_note(&self) -> Option { self.contents.payer_note() } +} +macro_rules! respond_with_explicit_signing_pubkey_methods { ($self: ident, $builder: ty) => { /// Creates an [`InvoiceBuilder`] for the refund with the given required fields and using the /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time. /// @@ -492,14 +513,14 @@ impl Refund { /// [`Duration`]: core::time::Duration #[cfg(feature = "std")] pub fn respond_with( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, + &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, signing_pubkey: PublicKey, - ) -> Result, Bolt12SemanticError> { + ) -> Result<$builder, Bolt12SemanticError> { let created_at = std::time::SystemTime::now() .duration_since(std::time::SystemTime::UNIX_EPOCH) .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"); - self.respond_with_no_std(payment_paths, payment_hash, signing_pubkey, created_at) + $self.respond_with_no_std(payment_paths, payment_hash, signing_pubkey, created_at) } /// Creates an [`InvoiceBuilder`] for the refund with the given required fields. @@ -525,16 +546,18 @@ impl Refund { /// /// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at pub fn respond_with_no_std( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, + &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, signing_pubkey: PublicKey, created_at: Duration - ) -> Result, Bolt12SemanticError> { - if self.features().requires_unknown_bits() { + ) -> Result<$builder, Bolt12SemanticError> { + if $self.features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } - InvoiceBuilder::for_refund(self, payment_paths, created_at, payment_hash, signing_pubkey) + <$builder>::for_refund($self, payment_paths, created_at, payment_hash, signing_pubkey) } +} } +macro_rules! respond_with_derived_signing_pubkey_methods { ($self: ident, $builder: ty) => { /// Creates an [`InvoiceBuilder`] for the refund using the given required fields and that uses /// derived signing keys to sign the [`Bolt12Invoice`]. /// @@ -545,9 +568,9 @@ impl Refund { /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice #[cfg(feature = "std")] pub fn respond_using_derived_keys( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, + &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, expanded_key: &ExpandedKey, entropy_source: ES - ) -> Result, Bolt12SemanticError> + ) -> Result<$builder, Bolt12SemanticError> where ES::Target: EntropySource, { @@ -555,7 +578,7 @@ impl Refund { .duration_since(std::time::SystemTime::UNIX_EPOCH) .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"); - self.respond_using_derived_keys_no_std( + $self.respond_using_derived_keys_no_std( payment_paths, payment_hash, created_at, expanded_key, entropy_source ) } @@ -569,22 +592,36 @@ impl Refund { /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn respond_using_derived_keys_no_std( - &self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, + &$self, payment_paths: Vec<(BlindedPayInfo, BlindedPath)>, payment_hash: PaymentHash, created_at: core::time::Duration, expanded_key: &ExpandedKey, entropy_source: ES - ) -> Result, Bolt12SemanticError> + ) -> Result<$builder, Bolt12SemanticError> where ES::Target: EntropySource, { - if self.features().requires_unknown_bits() { + if $self.features().requires_unknown_bits() { return Err(Bolt12SemanticError::UnknownRequiredFeatures); } let nonce = Nonce::from_entropy_source(entropy_source); let keys = signer::derive_keys(nonce, expanded_key); - InvoiceBuilder::for_refund_using_keys(self, payment_paths, created_at, payment_hash, keys) + <$builder>::for_refund_using_keys($self, payment_paths, created_at, payment_hash, keys) } +} } - #[cfg(test)] +#[cfg(not(c_bindings))] +impl Refund { + respond_with_explicit_signing_pubkey_methods!(self, InvoiceBuilder); + respond_with_derived_signing_pubkey_methods!(self, InvoiceBuilder); +} + +#[cfg(c_bindings)] +impl Refund { + respond_with_explicit_signing_pubkey_methods!(self, InvoiceWithExplicitSigningPubkeyBuilder); + respond_with_derived_signing_pubkey_methods!(self, InvoiceWithDerivedSigningPubkeyBuilder); +} + +#[cfg(test)] +impl Refund { fn as_tlv_stream(&self) -> RefundTlvStreamRef { self.contents.as_tlv_stream() } @@ -596,6 +633,20 @@ impl AsRef<[u8]> for Refund { } } +impl PartialEq for Refund { + fn eq(&self, other: &Self) -> bool { + self.bytes.eq(&other.bytes) + } +} + +impl Eq for Refund {} + +impl Hash for Refund { + fn hash(&self, state: &mut H) { + self.bytes.hash(state); + } +} + impl RefundContents { pub fn description(&self) -> PrintableString { PrintableString(&self.description) @@ -853,9 +904,10 @@ mod tests { use bitcoin::blockdata::constants::ChainHash; use bitcoin::network::constants::Network; use bitcoin::secp256k1::{KeyPair, Secp256k1, SecretKey}; - use core::convert::TryFrom; + use core::time::Duration; - use crate::blinded_path::{BlindedHop, BlindedPath}; + + use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode}; use crate::sign::KeyMaterial; use crate::ln::channelmanager::PaymentId; use crate::ln::features::{InvoiceRequestFeatures, OfferFeatures}; @@ -868,6 +920,7 @@ mod tests { use crate::offers::test_utils::*; use crate::util::ser::{BigSize, Writeable}; use crate::util::string::PrintableString; + use crate::prelude::*; trait ToBytes { fn to_bytes(&self) -> Vec; @@ -1009,7 +1062,7 @@ mod tests { let payment_id = PaymentId([1; 32]); let blinded_path = BlindedPath { - introduction_node_id: pubkey(40), + introduction_node: IntroductionNode::NodeId(pubkey(40)), blinding_point: pubkey(41), blinded_hops: vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, @@ -1098,7 +1151,7 @@ mod tests { fn builds_refund_with_paths() { let paths = vec![ BlindedPath { - introduction_node_id: pubkey(40), + introduction_node: IntroductionNode::NodeId(pubkey(40)), blinding_point: pubkey(41), blinded_hops: vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, @@ -1106,7 +1159,7 @@ mod tests { ], }, BlindedPath { - introduction_node_id: pubkey(40), + introduction_node: IntroductionNode::NodeId(pubkey(40)), blinding_point: pubkey(41), blinded_hops: vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] }, @@ -1315,7 +1368,7 @@ mod tests { let past_expiry = Duration::from_secs(0); let paths = vec![ BlindedPath { - introduction_node_id: pubkey(40), + introduction_node: IntroductionNode::NodeId(pubkey(40)), blinding_point: pubkey(41), blinded_hops: vec![ BlindedHop { blinded_node_id: pubkey(43), encrypted_payload: vec![0; 43] }, @@ -1323,7 +1376,7 @@ mod tests { ], }, BlindedPath { - introduction_node_id: pubkey(40), + introduction_node: IntroductionNode::NodeId(pubkey(40)), blinding_point: pubkey(41), blinded_hops: vec![ BlindedHop { blinded_node_id: pubkey(45), encrypted_payload: vec![0; 45] },