Actual no_std support
[rust-lightning] / lightning / src / util / events.rs
index 7ce738898759752f11bf96779d1648bf4446dad0..74490eb348b6f78eff96088b4db81b24ce1432ad 100644 (file)
 use ln::msgs;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 use chain::keysinterface::SpendableOutputDescriptor;
-use util::ser::{Writeable, Writer, MaybeReadable, Readable};
+use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
 
 use bitcoin::blockdata::script::Script;
 
 use bitcoin::secp256k1::key::PublicKey;
 
+use io;
 use prelude::*;
 use core::time::Duration;
 use core::ops::Deref;
 
+/// Some information provided on receipt of payment depends on whether the payment received is a
+/// spontaneous payment or a "conventional" lightning payment that's paying an invoice.
+#[derive(Clone, Debug)]
+pub enum PaymentPurpose {
+       /// Information for receiving a payment that we generated an invoice for.
+       InvoicePayment {
+               /// The preimage to the payment_hash, if the payment hash (and secret) were fetched via
+               /// [`ChannelManager::create_inbound_payment`]. If provided, this can be handed directly to
+               /// [`ChannelManager::claim_funds`].
+               ///
+               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+               /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+               payment_preimage: Option<PaymentPreimage>,
+               /// The "payment secret". This authenticates the sender to the recipient, preventing a
+               /// number of deanonymization attacks during the routing process.
+               /// It is provided here for your reference, however its accuracy is enforced directly by
+               /// [`ChannelManager`] using the values you previously provided to
+               /// [`ChannelManager::create_inbound_payment`] or
+               /// [`ChannelManager::create_inbound_payment_for_hash`].
+               ///
+               /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+               payment_secret: PaymentSecret,
+               /// This is the `user_payment_id` which was provided to
+               /// [`ChannelManager::create_inbound_payment_for_hash`] or
+               /// [`ChannelManager::create_inbound_payment`]. It has no meaning inside of LDK and is
+               /// simply copied here. It may be used to correlate PaymentReceived events with invoice
+               /// metadata stored elsewhere.
+               ///
+               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+               user_payment_id: u64,
+       },
+       /// Because this is a spontaneous payment, the payer generated their own preimage rather than us
+       /// (the payee) providing a preimage.
+       SpontaneousPayment(PaymentPreimage),
+}
+
 /// An Event which you should probably take some action in response to.
 ///
 /// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
@@ -63,37 +103,13 @@ pub enum Event {
        PaymentReceived {
                /// The hash for which the preimage should be handed to the ChannelManager.
                payment_hash: PaymentHash,
-               /// The preimage to the payment_hash, if the payment hash (and secret) were fetched via
-               /// [`ChannelManager::create_inbound_payment`]. If provided, this can be handed directly to
-               /// [`ChannelManager::claim_funds`].
-               ///
-               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-               /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
-               payment_preimage: Option<PaymentPreimage>,
-               /// The "payment secret". This authenticates the sender to the recipient, preventing a
-               /// number of deanonymization attacks during the routing process.
-               /// It is provided here for your reference, however its accuracy is enforced directly by
-               /// [`ChannelManager`] using the values you previously provided to
-               /// [`ChannelManager::create_inbound_payment`] or
-               /// [`ChannelManager::create_inbound_payment_for_hash`].
-               ///
-               /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
-               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
-               payment_secret: PaymentSecret,
                /// The value, in thousandths of a satoshi, that this payment is for. Note that you must
                /// compare this to the expected value before accepting the payment (as otherwise you are
                /// providing proof-of-payment for less than the value you expected!).
                amt: u64,
-               /// This is the `user_payment_id` which was provided to
-               /// [`ChannelManager::create_inbound_payment_for_hash`] or
-               /// [`ChannelManager::create_inbound_payment`]. It has no meaning inside of LDK and is
-               /// simply copied here. It may be used to correlate PaymentReceived events with invoice
-               /// metadata stored elsewhere.
-               ///
-               /// [`ChannelManager::create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-               /// [`ChannelManager::create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
-               user_payment_id: u64,
+               /// Information for claiming this received payment, based on whether the purpose of the
+               /// payment is to pay an invoice or to send a spontaneous payment.
+               purpose: PaymentPurpose,
        },
        /// Indicates an outbound payment we made succeeded (ie it made it all the way to its target
        /// and we got back the payment preimage for it).
@@ -126,7 +142,8 @@ pub enum Event {
                /// now + 5*time_forwardable).
                time_forwardable: Duration,
        },
-       /// Used to indicate that an output was generated on-chain which you should know how to spend.
+       /// Used to indicate that an output which you should know how to spend was confirmed on chain
+       /// and is now spendable.
        /// Such an output will *not* ever be spent by rust-lightning, and are not at risk of your
        /// counterparty spending them due to some kind of timeout. Thus, you need to store them
        /// somewhere and spend them when you create on-chain transactions.
@@ -137,24 +154,41 @@ pub enum Event {
 }
 
 impl Writeable for Event {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                match self {
                        &Event::FundingGenerationReady { .. } => {
                                0u8.write(writer)?;
                                // We never write out FundingGenerationReady events as, upon disconnection, peers
                                // drop any channels which have not yet exchanged funding_signed.
                        },
-                       &Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, ref amt, ref user_payment_id } => {
+                       &Event::PaymentReceived { ref payment_hash, ref amt, ref purpose } => {
                                1u8.write(writer)?;
-                               payment_hash.write(writer)?;
-                               payment_preimage.write(writer)?;
-                               payment_secret.write(writer)?;
-                               amt.write(writer)?;
-                               user_payment_id.write(writer)?;
+                               let mut payment_secret = None;
+                               let mut user_payment_id = None;
+                               let payment_preimage;
+                               match &purpose {
+                                       PaymentPurpose::InvoicePayment { payment_preimage: preimage, payment_secret: secret, user_payment_id: id } => {
+                                               payment_secret = Some(secret);
+                                               payment_preimage = *preimage;
+                                               user_payment_id = Some(id);
+                                       },
+                                       PaymentPurpose::SpontaneousPayment(preimage) => {
+                                               payment_preimage = Some(*preimage);
+                                       }
+                               }
+                               write_tlv_fields!(writer, {
+                                       (0, payment_hash, required),
+                                       (2, payment_secret, option),
+                                       (4, amt, required),
+                                       (6, user_payment_id, option),
+                                       (8, payment_preimage, option),
+                               });
                        },
                        &Event::PaymentSent { ref payment_preimage } => {
                                2u8.write(writer)?;
-                               payment_preimage.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_preimage, required),
+                               });
                        },
                        &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest,
                                #[cfg(test)]
@@ -163,61 +197,121 @@ impl Writeable for Event {
                                ref error_data,
                        } => {
                                3u8.write(writer)?;
-                               payment_hash.write(writer)?;
-                               rejected_by_dest.write(writer)?;
                                #[cfg(test)]
                                error_code.write(writer)?;
                                #[cfg(test)]
                                error_data.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_hash, required),
+                                       (2, rejected_by_dest, required),
+                               });
                        },
                        &Event::PendingHTLCsForwardable { time_forwardable: _ } => {
                                4u8.write(writer)?;
+                               write_tlv_fields!(writer, {});
                                // We don't write the time_fordwardable out at all, as we presume when the user
                                // deserializes us at least that much time has elapsed.
                        },
                        &Event::SpendableOutputs { ref outputs } => {
                                5u8.write(writer)?;
-                               (outputs.len() as u64).write(writer)?;
-                               for output in outputs.iter() {
-                                       output.write(writer)?;
-                               }
+                               write_tlv_fields!(writer, {
+                                       (0, VecWriteWrapper(outputs), required),
+                               });
                        },
                }
                Ok(())
        }
 }
 impl MaybeReadable for Event {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
                match Readable::read(reader)? {
                        0u8 => Ok(None),
-                       1u8 => Ok(Some(Event::PaymentReceived {
-                                       payment_hash: Readable::read(reader)?,
-                                       payment_preimage: Readable::read(reader)?,
-                                       payment_secret: Readable::read(reader)?,
-                                       amt: Readable::read(reader)?,
-                                       user_payment_id: Readable::read(reader)?,
-                               })),
-                       2u8 => Ok(Some(Event::PaymentSent {
-                                       payment_preimage: Readable::read(reader)?,
-                               })),
-                       3u8 => Ok(Some(Event::PaymentFailed {
-                                       payment_hash: Readable::read(reader)?,
-                                       rejected_by_dest: Readable::read(reader)?,
+                       1u8 => {
+                               let f = || {
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut payment_preimage = None;
+                                       let mut payment_secret = None;
+                                       let mut amt = 0;
+                                       let mut user_payment_id = None;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_hash, required),
+                                               (2, payment_secret, option),
+                                               (4, amt, required),
+                                               (6, user_payment_id, option),
+                                               (8, payment_preimage, option),
+                                       });
+                                       let purpose = match payment_secret {
+                                               Some(secret) => PaymentPurpose::InvoicePayment {
+                                                       payment_preimage,
+                                                       payment_secret: secret,
+                                                       user_payment_id: if let Some(id) = user_payment_id {
+                                                               id
+                                                       } else { return Err(msgs::DecodeError::InvalidValue) }
+                                               },
+                                               None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()),
+                                               None => return Err(msgs::DecodeError::InvalidValue),
+                                       };
+                                       Ok(Some(Event::PaymentReceived {
+                                               payment_hash,
+                                               amt,
+                                               purpose,
+                                       }))
+                               };
+                               f()
+                       },
+                       2u8 => {
+                               let f = || {
+                                       let mut payment_preimage = PaymentPreimage([0; 32]);
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_preimage, required),
+                                       });
+                                       Ok(Some(Event::PaymentSent {
+                                               payment_preimage,
+                                       }))
+                               };
+                               f()
+                       },
+                       3u8 => {
+                               let f = || {
                                        #[cfg(test)]
-                                       error_code: Readable::read(reader)?,
+                                       let error_code = Readable::read(reader)?;
                                        #[cfg(test)]
-                                       error_data: Readable::read(reader)?,
-                               })),
-                       4u8 => Ok(Some(Event::PendingHTLCsForwardable {
-                                       time_forwardable: Duration::from_secs(0)
-                               })),
+                                       let error_data = Readable::read(reader)?;
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut rejected_by_dest = false;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_hash, required),
+                                               (2, rejected_by_dest, required),
+                                       });
+                                       Ok(Some(Event::PaymentFailed {
+                                               payment_hash,
+                                               rejected_by_dest,
+                                               #[cfg(test)]
+                                               error_code,
+                                               #[cfg(test)]
+                                               error_data,
+                                       }))
+                               };
+                               f()
+                       },
+                       4u8 => {
+                               let f = || {
+                                       read_tlv_fields!(reader, {});
+                                       Ok(Some(Event::PendingHTLCsForwardable {
+                                               time_forwardable: Duration::from_secs(0)
+                                       }))
+                               };
+                               f()
+                       },
                        5u8 => {
-                               let outputs_len: u64 = Readable::read(reader)?;
-                               let mut outputs = Vec::new();
-                               for _ in 0..outputs_len {
-                                       outputs.push(Readable::read(reader)?);
-                               }
-                               Ok(Some(Event::SpendableOutputs { outputs }))
+                               let f = || {
+                                       let mut outputs = VecReadWrapper(Vec::new());
+                                       read_tlv_fields!(reader, {
+                                               (0, outputs, required),
+                                       });
+                                       Ok(Some(Event::SpendableOutputs { outputs: outputs.0 }))
+                               };
+                               f()
                        },
                        _ => Err(msgs::DecodeError::InvalidValue)
                }
@@ -333,6 +427,15 @@ pub enum MessageSendEvent {
                /// The channel_update which should be sent.
                msg: msgs::ChannelUpdate,
        },
+       /// Used to indicate that a channel_update should be sent to a single peer.
+       /// In contrast to [`Self::BroadcastChannelUpdate`], this is used when the channel is a
+       /// private channel and we shouldn't be informing all of our peers of channel parameters.
+       SendChannelUpdate {
+               /// The node_id of the node which should receive this message
+               node_id: PublicKey,
+               /// The channel_update which should be sent.
+               msg: msgs::ChannelUpdate,
+       },
        /// Broadcast an error downstream to be handled
        HandleError {
                /// The node_id of the node which should receive this message