X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fevents.rs;h=8ddd762e97036bac77fee08c2be7819ec707388e;hb=3a3c931c5a5bc49197c021aaf98bc98b76176de7;hp=2282ea55ab36211576b4726645af7579179001f8;hpb=fda38196993b22e34ba43f0bb9c94ba842174bf1;p=rust-lightning diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index 2282ea55..8ddd762e 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -25,7 +25,7 @@ use routing::gossip::NetworkUpdate; use util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper}; use routing::router::{RouteHop, RouteParameters}; -use bitcoin::Transaction; +use bitcoin::{PackedLockTime, Transaction}; use bitcoin::blockdata::script::Script; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; @@ -152,6 +152,50 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason, (12, OutdatedChannelManager) => {}, ); +/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`]. +#[derive(Clone, Debug, PartialEq)] +pub enum HTLCDestination { + /// We tried forwarding to a channel but failed to do so. An example of such an instance is when + /// there is insufficient capacity in our outbound channel. + NextHopChannel { + /// The `node_id` of the next node. For backwards compatibility, this field is + /// marked as optional, versions prior to 0.0.110 may not always be able to provide + /// counterparty node information. + node_id: Option, + /// The outgoing `channel_id` between us and the next node. + channel_id: [u8; 32], + }, + /// Scenario where we are unsure of the next node to forward the HTLC to. + UnknownNextHop { + /// Short channel id we are requesting to forward an HTLC to. + requested_forward_scid: u64, + }, + /// Failure scenario where an HTLC may have been forwarded to be intended for us, + /// but is invalid for some reason, so we reject it. + /// + /// Some of the reasons may include: + /// * HTLC Timeouts + /// * Expected MPP amount to claim does not equal HTLC total + /// * Claimable amount does not match expected amount + FailedPayment { + /// The payment hash of the payment we attempted to process. + payment_hash: PaymentHash + }, +} + +impl_writeable_tlv_based_enum_upgradable!(HTLCDestination, + (0, NextHopChannel) => { + (0, node_id, required), + (2, channel_id, required), + }, + (2, UnknownNextHop) => { + (0, requested_forward_scid, required), + }, + (4, FailedPayment) => { + (0, payment_hash, required), + } +); + /// 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 @@ -332,7 +376,7 @@ pub enum Event { /// Indicates the payment was rejected for some reason by the recipient. This implies that /// 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, + payment_failed_permanently: bool, /// Any failure information conveyed via the Onion return packet by a node along the failed /// payment route. /// @@ -540,6 +584,24 @@ pub enum Event { /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager channel_type: ChannelTypeFeatures, }, + /// Indicates that the HTLC was accepted, but could not be processed when or after attempting to + /// forward it. + /// + /// Some scenarios where this event may be sent include: + /// * Insufficient capacity in the outbound channel + /// * While waiting to forward the HTLC, the channel it is meant to be forwarded through closes + /// * When an unknown SCID is requested for forwarding a payment. + /// * Claiming an amount for an MPP payment that exceeds the HTLC total + /// * The HTLC has timed out + /// + /// This event, however, does not get generated if an HTLC fails to meet the forwarding + /// requirements (i.e. insufficient fees paid, or a CLTV that is too soon). + HTLCHandlingFailed { + /// The channel over which the HTLC was received. + prev_channel_id: [u8; 32], + /// Destination of the HTLC that failed to be processed. + failed_next_destination: HTLCDestination, + }, } impl Writeable for Event { @@ -581,7 +643,7 @@ impl Writeable for Event { }); }, &Event::PaymentPathFailed { - ref payment_id, ref payment_hash, ref rejected_by_dest, ref network_update, + ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update, ref all_paths_failed, ref path, ref short_channel_id, ref retry, #[cfg(test)] ref error_code, @@ -596,7 +658,7 @@ impl Writeable for Event { write_tlv_fields!(writer, { (0, payment_hash, required), (1, network_update, option), - (2, rejected_by_dest, required), + (2, payment_failed_permanently, required), (3, all_paths_failed, required), (5, path, vec_type), (7, short_channel_id, option), @@ -684,6 +746,13 @@ impl Writeable for Event { (6, short_channel_id, option), }) }, + &Event::HTLCHandlingFailed { ref prev_channel_id, ref failed_next_destination } => { + 25u8.write(writer)?; + write_tlv_fields!(writer, { + (0, prev_channel_id, required), + (2, failed_next_destination, required), + }) + }, // Note that, going forward, all new events must only write data inside of // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write // data via `write_tlv_fields`. @@ -758,7 +827,7 @@ impl MaybeReadable for Event { #[cfg(test)] let error_data = Readable::read(reader)?; let mut payment_hash = PaymentHash([0; 32]); - let mut rejected_by_dest = false; + let mut payment_failed_permanently = false; let mut network_update = None; let mut all_paths_failed = Some(true); let mut path: Option> = Some(vec![]); @@ -768,7 +837,7 @@ impl MaybeReadable for Event { read_tlv_fields!(reader, { (0, payment_hash, required), (1, network_update, ignorable), - (2, rejected_by_dest, required), + (2, payment_failed_permanently, required), (3, all_paths_failed, option), (5, path, vec_type), (7, short_channel_id, option), @@ -778,7 +847,7 @@ impl MaybeReadable for Event { Ok(Some(Event::PaymentPathFailed { payment_id, payment_hash, - rejected_by_dest, + payment_failed_permanently, network_update, all_paths_failed: all_paths_failed.unwrap(), path: path.unwrap(), @@ -838,7 +907,7 @@ impl MaybeReadable for Event { 11u8 => { let f = || { let mut channel_id = [0; 32]; - let mut transaction = Transaction{ version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() }; + let mut transaction = Transaction{ version: 2, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() }; read_tlv_fields!(reader, { (0, channel_id, required), (2, transaction, required), @@ -933,7 +1002,7 @@ impl MaybeReadable for Event { (4, path, vec_type), (6, short_channel_id, option), }); - Ok(Some(Event::ProbeFailed{ + Ok(Some(Event::ProbeFailed { payment_id, payment_hash, path: path.unwrap(), @@ -942,6 +1011,28 @@ impl MaybeReadable for Event { }; f() }, + 25u8 => { + let f = || { + let mut prev_channel_id = [0; 32]; + let mut failed_next_destination_opt = None; + read_tlv_fields!(reader, { + (0, prev_channel_id, required), + (2, failed_next_destination_opt, ignorable), + }); + if let Some(failed_next_destination) = failed_next_destination_opt { + Ok(Some(Event::HTLCHandlingFailed { + prev_channel_id, + failed_next_destination, + })) + } else { + // If we fail to read a `failed_next_destination` assume it's because + // `MaybeReadable::read` returned `Ok(None)`, though it's also possible we + // were simply missing the field. + Ok(None) + } + }; + f() + }, // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt // reads. @@ -1046,25 +1137,32 @@ pub enum MessageSendEvent { /// The message which should be sent. msg: msgs::ChannelReestablish, }, + /// Used to send a channel_announcement and channel_update to a specific peer, likely on + /// initial connection to ensure our peers know about our channels. + SendChannelAnnouncement { + /// The node_id of the node which should receive this message + node_id: PublicKey, + /// The channel_announcement which should be sent. + msg: msgs::ChannelAnnouncement, + /// The followup channel_update which should be sent. + update_msg: msgs::ChannelUpdate, + }, /// Used to indicate that a channel_announcement and channel_update should be broadcast to all /// peers (except the peer with node_id either msg.contents.node_id_1 or msg.contents.node_id_2). /// - /// Note that after doing so, you very likely (unless you did so very recently) want to call - /// ChannelManager::broadcast_node_announcement to trigger a BroadcastNodeAnnouncement event. - /// This ensures that any nodes which see our channel_announcement also have a relevant + /// Note that after doing so, you very likely (unless you did so very recently) want to + /// broadcast a node_announcement (e.g. via [`PeerManager::broadcast_node_announcement`]). This + /// ensures that any nodes which see our channel_announcement also have a relevant /// node_announcement, including relevant feature flags which may be important for routing /// through or to us. + /// + /// [`PeerManager::broadcast_node_announcement`]: crate::ln::peer_handler::PeerManager::broadcast_node_announcement BroadcastChannelAnnouncement { /// The channel_announcement which should be sent. msg: msgs::ChannelAnnouncement, /// The followup channel_update which should be sent. update_msg: msgs::ChannelUpdate, }, - /// Used to indicate that a node_announcement should be broadcast to all peers. - BroadcastNodeAnnouncement { - /// The node_announcement which should be sent. - msg: msgs::NodeAnnouncement, - }, /// Used to indicate that a channel_update should be broadcast to all peers. BroadcastChannelUpdate { /// The channel_update which should be sent. @@ -1126,17 +1224,29 @@ pub trait MessageSendEventsProvider { fn get_and_clear_pending_msg_events(&self) -> Vec; } +/// A trait indicating an object may generate onion messages to send +pub trait OnionMessageProvider { + /// Gets the next pending onion message for the peer with the given node id. + fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option; +} + /// A trait indicating an object may generate events. /// /// Events are processed by passing an [`EventHandler`] to [`process_pending_events`]. /// /// # Requirements /// -/// See [`process_pending_events`] for requirements around event processing. -/// /// When using this trait, [`process_pending_events`] will call [`handle_event`] for each pending -/// event since the last invocation. The handler must either act upon the event immediately -/// or preserve it for later handling. +/// event since the last invocation. +/// +/// In order to ensure no [`Event`]s are lost, implementors of this trait will persist [`Event`]s +/// and replay any unhandled events on startup. An [`Event`] is considered handled when +/// [`process_pending_events`] returns, thus handlers MUST fully handle [`Event`]s and persist any +/// relevant changes to disk *before* returning. +/// +/// Further, because an application may crash between an [`Event`] being handled and the +/// implementor of this trait being re-serialized, [`Event`] handling must be idempotent - in +/// effect, [`Event`]s may be replayed. /// /// Note, handlers may call back into the provider and thus deadlocking must be avoided. Be sure to /// consult the provider's documentation on the implication of processing events and how a handler @@ -1153,9 +1263,7 @@ pub trait MessageSendEventsProvider { pub trait EventsProvider { /// Processes any events generated since the last call using the given event handler. /// - /// Subsequent calls must only process new events. However, handlers must be capable of handling - /// duplicate events across process restarts. This may occur if the provider was recovered from - /// an old state (i.e., it hadn't been successfully persisted after processing pending events). + /// See the trait-level documentation for requirements. fn process_pending_events(&self, handler: H) where H::Target: EventHandler; }