X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fevents.rs;h=abd8f6b105fcdda900518efbd3c59ea2c52c14cf;hb=0dd987fc41240d96a13f2011cb0679eb6abdb3b1;hp=74490eb348b6f78eff96088b4db81b24ce1432ad;hpb=09e167019589dcfc5ee9675ad243b337659eafc7;p=rust-lightning diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index 74490eb3..abd8f6b1 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -14,9 +14,11 @@ //! future, as well as generate and broadcast funding transactions handle payment preimages and a //! few other things. +use chain::keysinterface::SpendableOutputDescriptor; use ln::msgs; +use ln::msgs::DecodeError; use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; -use chain::keysinterface::SpendableOutputDescriptor; +use routing::network_graph::NetworkUpdate; use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper}; use bitcoin::blockdata::script::Script; @@ -67,6 +69,47 @@ pub enum PaymentPurpose { SpontaneousPayment(PaymentPreimage), } +#[derive(Clone, Debug)] +pub enum ClosureDescriptor { + ForceClosed, + UserInitiated, + CounterpartyInitiated, + CooperativeClosure, + UnknownOnchainCommitment, + ProcessingError, + DisconnectedPeer, +} + +impl Writeable for ClosureDescriptor { + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + match self { + ClosureDescriptor::ForceClosed => 0u8.write(writer)?, + ClosureDescriptor::UserInitiated => 1u8.write(writer)?, + ClosureDescriptor::CounterpartyInitiated => 2u8.write(writer)?, + ClosureDescriptor::CooperativeClosure => 3u8.write(writer)?, + ClosureDescriptor::UnknownOnchainCommitment => 4u8.write(writer)?, + ClosureDescriptor::ProcessingError => 5u8.write(writer)?, + ClosureDescriptor::DisconnectedPeer => 6u8.write(writer)?, + } + Ok(()) + } +} + +impl Readable for ClosureDescriptor { + fn read(reader: &mut R) -> Result { + Ok(match ::read(reader)? { + 0 => ClosureDescriptor::ForceClosed, + 1 => ClosureDescriptor::UserInitiated, + 2 => ClosureDescriptor::CounterpartyInitiated, + 3 => ClosureDescriptor::CooperativeClosure, + 4 => ClosureDescriptor::UnknownOnchainCommitment, + 5 => ClosureDescriptor::ProcessingError, + 6 => ClosureDescriptor::DisconnectedPeer, + _ => return Err(DecodeError::InvalidValue), + }) + } +} + /// 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 @@ -111,8 +154,11 @@ pub enum Event { /// 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 + /// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target /// and we got back the payment preimage for it). + /// + /// Note for MPP payments: in rare cases, this event may be preceded by a `PaymentFailed` event. + /// In this situation, you SHOULD treat this payment as having succeeded. PaymentSent { /// The preimage to the hash given to ChannelManager::send_payment. /// Note that this serves as a payment receipt, if you wish to have such a thing, you must @@ -128,6 +174,19 @@ pub enum Event { /// the payment has failed, not just the route in question. If this is not set, you may /// retry the payment via a different route. rejected_by_dest: bool, + /// Any failure information conveyed via the Onion return packet by a node along the failed + /// payment route. + /// + /// Should be applied to the [`NetworkGraph`] so that routing decisions can take into + /// account the update. [`NetGraphMsgHandler`] is capable of doing this. + /// + /// [`NetworkGraph`]: crate::routing::network_graph::NetworkGraph + /// [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler + network_update: Option, + /// For both single-path and multi-path payments, this is set if all paths of the payment have + /// failed. This will be set to false if (1) this is an MPP payment and (2) other parts of the + /// larger MPP payment were still in flight when this event was generated. + all_paths_failed: bool, #[cfg(test)] error_code: Option, #[cfg(test)] @@ -151,6 +210,35 @@ pub enum Event { /// The outputs which you should store as spendable by you. outputs: Vec, }, + /// This event is generated when a payment has been successfully forwarded through us and a + /// forwarding fee earned. + PaymentForwarded { + /// The fee, in milli-satoshis, which was earned as a result of the payment. + /// + /// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC + /// was pending, the amount the next hop claimed will have been rounded down to the nearest + /// whole satoshi. Thus, the fee calculated here may be higher than expected as we still + /// claimed the full value in millisatoshis from the source. In this case, + /// `claim_from_onchain_tx` will be set. + /// + /// If the channel which sent us the payment has been force-closed, we will claim the funds + /// via an on-chain transaction. In that case we do not yet know the on-chain transaction + /// fees which we will spend and will instead set this to `None`. It is possible duplicate + /// `PaymentForwarded` events are generated for the same payment iff `fee_earned_msat` is + /// `None`. + fee_earned_msat: Option, + /// If this is `true`, the forwarded HTLC was claimed by our counterparty via an on-chain + /// transaction. + claim_from_onchain_tx: bool, + }, + /// Used to indicate that a channel was closed at the given timestamp. + ChannelClosed { + /// The channel_id which has been barren from further off-chain updates but + /// funding output might still be not resolved yet. + channel_id: [u8; 32], + /// A machine-readable error message + err: ClosureDescriptor + } } impl Writeable for Event { @@ -190,7 +278,7 @@ impl Writeable for Event { (0, payment_preimage, required), }); }, - &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, + &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed, #[cfg(test)] ref error_code, #[cfg(test)] @@ -203,7 +291,9 @@ impl Writeable for Event { error_data.write(writer)?; write_tlv_fields!(writer, { (0, payment_hash, required), + (1, network_update, option), (2, rejected_by_dest, required), + (3, all_paths_failed, required), }); }, &Event::PendingHTLCsForwardable { time_forwardable: _ } => { @@ -218,6 +308,19 @@ impl Writeable for Event { (0, VecWriteWrapper(outputs), required), }); }, + &Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx } => { + 7u8.write(writer)?; + write_tlv_fields!(writer, { + (0, fee_earned_msat, option), + (2, claim_from_onchain_tx, required), + }); + }, + &Event::ChannelClosed { ref channel_id, ref err } => { + 6u8.write(writer)?; + channel_id.write(writer)?; + err.write(writer)?; + write_tlv_fields!(writer, {}); + }, } Ok(()) } @@ -279,13 +382,19 @@ impl MaybeReadable for Event { let error_data = Readable::read(reader)?; let mut payment_hash = PaymentHash([0; 32]); let mut rejected_by_dest = false; + let mut network_update = None; + let mut all_paths_failed = Some(true); read_tlv_fields!(reader, { (0, payment_hash, required), + (1, network_update, ignorable), (2, rejected_by_dest, required), + (3, all_paths_failed, option), }); Ok(Some(Event::PaymentFailed { payment_hash, rejected_by_dest, + network_update, + all_paths_failed: all_paths_failed.unwrap(), #[cfg(test)] error_code, #[cfg(test)] @@ -313,6 +422,29 @@ impl MaybeReadable for Event { }; f() }, + 7u8 => { + let f = || { + let mut fee_earned_msat = None; + let mut claim_from_onchain_tx = false; + read_tlv_fields!(reader, { + (0, fee_earned_msat, option), + (2, claim_from_onchain_tx, required), + }); + Ok(Some(Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx })) + }; + f() + }, + // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. + x if x % 2 == 1 => Ok(None), + 6u8 => { + let f = || { + let channel_id = Readable::read(reader)?; + let err = Readable::read(reader)?; + read_tlv_fields!(reader, {}); + Ok(Some(Event::ChannelClosed { channel_id, err})) + }; + f() + }, _ => Err(msgs::DecodeError::InvalidValue) } } @@ -443,12 +575,6 @@ pub enum MessageSendEvent { /// The action which should be taken. action: msgs::ErrorAction }, - /// When a payment fails we may receive updates back from the hop where it failed. In such - /// cases this event is generated so that we can inform the network graph of this information. - PaymentFailureNetworkUpdate { - /// The channel/node update which should be sent to NetGraphMsgHandler - update: msgs::HTLCFailChannelUpdate, - }, /// Query a peer for channels with funding transaction UTXOs in a block range. SendChannelRangeQuery { /// The node_id of this message recipient @@ -519,11 +645,11 @@ pub trait EventHandler { /// Handles the given [`Event`]. /// /// See [`EventsProvider`] for details that must be considered when implementing this method. - fn handle_event(&self, event: Event); + fn handle_event(&self, event: &Event); } -impl EventHandler for F where F: Fn(Event) { - fn handle_event(&self, event: Event) { +impl EventHandler for F where F: Fn(&Event) { + fn handle_event(&self, event: &Event) { self(event) } }