Merge pull request #2966 from G8XSU/2647-distribute
[rust-lightning] / lightning / src / offers / offer.rs
index fc17ae48da16a641ee53932fdd2c9d32362c15e0..dd58c75cec27e600e803122d72d92036665b0976 100644 (file)
@@ -24,7 +24,7 @@
 //! use core::num::NonZeroU64;
 //! use core::time::Duration;
 //!
-//! use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, SecretKey};
+//! use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey};
 //! use lightning::offers::offer::{Offer, OfferBuilder, Quantity};
 //! use lightning::offers::parse::Bolt12ParseError;
 //! use lightning::util::ser::{Readable, Writeable};
@@ -39,7 +39,7 @@
 //! # #[cfg(feature = "std")]
 //! # fn build() -> Result<(), Bolt12ParseError> {
 //! let secp_ctx = Secp256k1::new();
-//! let keys = KeyPair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+//! let keys = Keypair::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
 //! let pubkey = PublicKey::from(keys);
 //!
 //! let expiration = SystemTime::now() + Duration::from_secs(24 * 60 * 60);
@@ -78,8 +78,8 @@
 //! [`ChannelManager::create_offer_builder`]: crate::ln::channelmanager::ChannelManager::create_offer_builder
 
 use bitcoin::blockdata::constants::ChainHash;
-use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{KeyPair, PublicKey, Secp256k1, self};
+use bitcoin::network::Network;
+use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, self};
 use core::hash::{Hash, Hasher};
 use core::num::NonZeroU64;
 use core::ops::Deref;
@@ -165,6 +165,7 @@ pub struct OfferBuilder<'a, M: MetadataStrategy, T: secp256k1::Signing> {
 ///
 /// [module-level documentation]: self
 #[cfg(c_bindings)]
+#[derive(Clone)]
 pub struct OfferWithExplicitMetadataBuilder<'a> {
        offer: OfferContents,
        metadata_strategy: core::marker::PhantomData<ExplicitMetadata>,
@@ -177,6 +178,7 @@ pub struct OfferWithExplicitMetadataBuilder<'a> {
 ///
 /// [module-level documentation]: self
 #[cfg(c_bindings)]
+#[derive(Clone)]
 pub struct OfferWithDerivedMetadataBuilder<'a> {
        offer: OfferContents,
        metadata_strategy: core::marker::PhantomData<DerivedMetadata>,
@@ -662,6 +664,12 @@ impl Offer {
        pub fn expects_quantity(&self) -> bool {
                self.contents.expects_quantity()
        }
+
+       pub(super) fn verify<T: secp256k1::Signing>(
+               &self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
+       ) -> Result<(OfferId, Option<Keypair>), ()> {
+               self.contents.verify(&self.bytes, key, secp_ctx)
+       }
 }
 
 macro_rules! request_invoice_derived_payer_id { ($self: ident, $builder: ty) => {
@@ -907,7 +915,7 @@ impl OfferContents {
        /// Verifies that the offer metadata was produced from the offer in the TLV stream.
        pub(super) fn verify<T: secp256k1::Signing>(
                &self, bytes: &[u8], key: &ExpandedKey, secp_ctx: &Secp256k1<T>
-       ) -> Result<(OfferId, Option<KeyPair>), ()> {
+       ) -> Result<(OfferId, Option<Keypair>), ()> {
                match self.metadata() {
                        Some(metadata) => {
                                let tlv_stream = TlvStream::new(bytes).range(OFFER_TYPES).filter(|record| {
@@ -964,6 +972,13 @@ impl OfferContents {
        }
 }
 
+impl Readable for Offer {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               let bytes: WithoutLength<Vec<u8>> = Readable::read(reader)?;
+               Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue)
+       }
+}
+
 impl Writeable for Offer {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                WithoutLength(&self.bytes).write(writer)
@@ -1138,7 +1153,7 @@ mod tests {
        };
 
        use bitcoin::blockdata::constants::ChainHash;
-       use bitcoin::network::constants::Network;
+       use bitcoin::network::Network;
        use bitcoin::secp256k1::Secp256k1;
        use core::num::NonZeroU64;
        use core::time::Duration;
@@ -1172,6 +1187,7 @@ mod tests {
                assert_eq!(offer.paths(), &[]);
                assert_eq!(offer.issuer(), None);
                assert_eq!(offer.supported_quantity(), Quantity::One);
+               assert!(!offer.expects_quantity());
                assert_eq!(offer.signing_pubkey(), Some(pubkey(42)));
 
                assert_eq!(
@@ -1546,6 +1562,7 @@ mod tests {
                        .build()
                        .unwrap();
                let tlv_stream = offer.as_tlv_stream();
+               assert!(!offer.expects_quantity());
                assert_eq!(offer.supported_quantity(), Quantity::One);
                assert_eq!(tlv_stream.quantity_max, None);
 
@@ -1554,6 +1571,7 @@ mod tests {
                        .build()
                        .unwrap();
                let tlv_stream = offer.as_tlv_stream();
+               assert!(offer.expects_quantity());
                assert_eq!(offer.supported_quantity(), Quantity::Unbounded);
                assert_eq!(tlv_stream.quantity_max, Some(0));
 
@@ -1562,6 +1580,7 @@ mod tests {
                        .build()
                        .unwrap();
                let tlv_stream = offer.as_tlv_stream();
+               assert!(offer.expects_quantity());
                assert_eq!(offer.supported_quantity(), Quantity::Bounded(ten));
                assert_eq!(tlv_stream.quantity_max, Some(10));
 
@@ -1570,6 +1589,7 @@ mod tests {
                        .build()
                        .unwrap();
                let tlv_stream = offer.as_tlv_stream();
+               assert!(offer.expects_quantity());
                assert_eq!(offer.supported_quantity(), Quantity::Bounded(one));
                assert_eq!(tlv_stream.quantity_max, Some(1));
 
@@ -1579,6 +1599,7 @@ mod tests {
                        .build()
                        .unwrap();
                let tlv_stream = offer.as_tlv_stream();
+               assert!(!offer.expects_quantity());
                assert_eq!(offer.supported_quantity(), Quantity::One);
                assert_eq!(tlv_stream.quantity_max, None);
        }
@@ -1858,6 +1879,9 @@ mod bolt12_tests {
                        // with blinded path via Bob (0x424242...), blinding 020202...
                        "lno1pgx9getnwss8vetrw3hhyucs5ypjgef743p5fzqq9nqxh0ah7y87rzv3ud0eleps9kl2d5348hq2k8qzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgqpqqqqqqqqqqqqqqqqqqqqqqqqqqqzqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqqzq3zyg3zyg3zyg3vggzamrjghtt05kvkvpcp0a79gmy3nt6jsn98ad2xs8de6sl9qmgvcvs",
 
+                       // ... and with sciddir introduction node
+                       "lno1pgx9getnwss8vetrw3hhyucs3yqqqqqqqqqqqqp2qgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqqyqqqqqqqqqqqqqqqqqqqqqqqqqqqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqqgzyg3zyg3zyg3z93pqthvwfzadd7jejes8q9lhc4rvjxd022zv5l44g6qah82ru5rdpnpj",
+
                        // ... and with second blinded path via Carol (0x434343...), blinding 020202...
                        "lno1pgx9getnwss8vetrw3hhyucsl5q5yqeyv5l2cs6y3qqzesrth7mlzrlp3xg7xhulusczm04x6g6nms9trspqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqqsqqqqqqqqqqqqqqqqqqqqqqqqqqpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsqpqg3zyg3zyg3zygz0uc7h32x9s0aecdhxlk075kn046aafpuuyw8f5j652t3vha2yqrsyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsqzqqqqqqqqqqqqqqqqqqqqqqqqqqqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqqyzyg3zyg3zyg3zzcss9mk8y3wkklfvevcrszlmu23kfrxh49px20665dqwmn4p72pksese",