X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fevents.rs;h=83e861889bc356bff2cd2305cfd92077e13b6ded;hb=17c0fc82a4efe980fd3e135548d47d407517fe63;hp=e86eae3c813a8af7a3684480171df913ea0883bd;hpb=8c6cb9953a3b00ce3da25fbdfd8ada0ec48fc63f;p=rust-lightning diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index e86eae3c..83e86188 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -15,6 +15,7 @@ //! few other things. use chain::keysinterface::SpendableOutputDescriptor; +use ln::chan_utils::HTLCOutputInCommitment; use ln::channelmanager::PaymentId; use ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; use ln::features::ChannelTypeFeatures; @@ -25,7 +26,7 @@ use routing::gossip::NetworkUpdate; use util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper}; use routing::router::{RouteHop, RouteParameters}; -use bitcoin::{PackedLockTime, Transaction}; +use bitcoin::{PackedLockTime, Transaction, OutPoint}; use bitcoin::blockdata::script::Script; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; @@ -74,7 +75,7 @@ impl_writeable_tlv_based_enum!(PaymentPurpose, (2, SpontaneousPayment) ); -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] /// The reason the channel was closed. See individual variants more details. pub enum ClosureReason { /// Closure generated from receiving a peer error message. @@ -111,11 +112,19 @@ pub enum ClosureReason { /// The peer disconnected prior to funding completing. In this case the spec mandates that we /// forget the channel entirely - we can attempt again if the peer reconnects. /// + /// This includes cases where we restarted prior to funding completion, including prior to the + /// initial [`ChannelMonitor`] persistence completing. + /// /// In LDK versions prior to 0.0.107 this could also occur if we were unable to connect to the /// peer because of mutual incompatibility between us and our channel counterparty. + /// + /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor DisconnectedPeer, - /// Closure generated from `ChannelManager::read` if the ChannelMonitor is newer than - /// the ChannelManager deserialized. + /// Closure generated from `ChannelManager::read` if the [`ChannelMonitor`] is newer than + /// the [`ChannelManager`] deserialized. + /// + /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager OutdatedChannelManager } @@ -153,7 +162,7 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason, ); /// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`]. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] 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. @@ -196,6 +205,84 @@ impl_writeable_tlv_based_enum_upgradable!(HTLCDestination, } ); +/// A descriptor used to sign for a commitment transaction's anchor output. +#[derive(Clone, Debug)] +pub struct AnchorDescriptor { + /// A unique identifier used along with `channel_value_satoshis` to re-derive the + /// [`InMemorySigner`] required to sign `input`. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + pub channel_keys_id: [u8; 32], + /// The value in satoshis of the channel we're attempting to spend the anchor output of. This is + /// used along with `channel_keys_id` to re-derive the [`InMemorySigner`] required to sign + /// `input`. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + pub channel_value_satoshis: u64, + /// The transaction input's outpoint corresponding to the commitment transaction's anchor + /// output. + pub outpoint: OutPoint, +} + +/// Represents the different types of transactions, originating from LDK, to be bumped. +#[derive(Clone, Debug)] +pub enum BumpTransactionEvent { + /// Indicates that a channel featuring anchor outputs is to be closed by broadcasting the local + /// commitment transaction. Since commitment transactions have a static feerate pre-agreed upon, + /// they may need additional fees to be attached through a child transaction using the popular + /// [Child-Pays-For-Parent](https://bitcoinops.org/en/topics/cpfp) fee bumping technique. This + /// child transaction must include the anchor input described within `anchor_descriptor` along + /// with additional inputs to meet the target feerate. Failure to meet the target feerate + /// decreases the confirmation odds of the transaction package (which includes the commitment + /// and child anchor transactions), possibly resulting in a loss of funds. Once the transaction + /// is constructed, it must be fully signed for and broadcasted by the consumer of the event + /// along with the `commitment_tx` enclosed. Note that the `commitment_tx` must always be + /// broadcast first, as the child anchor transaction depends on it. + /// + /// The consumer should be able to sign for any of the additional inputs included within the + /// child anchor transaction. To sign its anchor input, an [`InMemorySigner`] should be + /// re-derived through [`KeysManager::derive_channel_keys`] with the help of + /// [`AnchorDescriptor::channel_keys_id`] and [`AnchorDescriptor::channel_value_satoshis`]. + /// + /// It is possible to receive more than one instance of this event if a valid child anchor + /// transaction is never broadcast or is but not with a sufficient fee to be mined. Care should + /// be taken by the consumer of the event to ensure any future iterations of the child anchor + /// transaction adhere to the [Replace-By-Fee + /// rules](https://github.com/bitcoin/bitcoin/blob/master/doc/policy/mempool-replacements.md) + /// for fee bumps to be accepted into the mempool, and eventually the chain. As the frequency of + /// these events is not user-controlled, users may ignore/drop the event if they are no longer + /// able to commit external confirmed funds to the child anchor transaction. + /// + /// The set of `pending_htlcs` on the commitment transaction to be broadcast can be inspected to + /// determine whether a significant portion of the channel's funds are allocated to HTLCs, + /// enabling users to make their own decisions regarding the importance of the commitment + /// transaction's confirmation. Note that this is not required, but simply exists as an option + /// for users to override LDK's behavior. On commitments with no HTLCs (indicated by those with + /// an empty `pending_htlcs`), confirmation of the commitment transaction can be considered to + /// be not urgent. + /// + /// [`InMemorySigner`]: crate::chain::keysinterface::InMemorySigner + /// [`KeysManager::derive_channel_keys`]: crate::chain::keysinterface::KeysManager::derive_channel_keys + ChannelClose { + /// The target feerate that the transaction package, which consists of the commitment + /// transaction and the to-be-crafted child anchor transaction, must meet. + package_target_feerate_sat_per_1000_weight: u32, + /// The channel's commitment transaction to bump the fee of. This transaction should be + /// broadcast along with the anchor transaction constructed as a result of consuming this + /// event. + commitment_tx: Transaction, + /// The absolute fee in satoshis of the commitment transaction. This can be used along the + /// with weight of the commitment transaction to determine its feerate. + commitment_tx_fee_satoshis: u64, + /// The descriptor to sign the anchor input of the anchor transaction constructed as a + /// result of consuming this event. + anchor_descriptor: AnchorDescriptor, + /// The set of pending HTLCs on the commitment transaction that need to be resolved once the + /// commitment transaction confirms. + pending_htlcs: Vec, + }, +} + /// 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 @@ -376,7 +463,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. /// @@ -602,6 +689,13 @@ pub enum Event { /// Destination of the HTLC that failed to be processed. failed_next_destination: HTLCDestination, }, + #[cfg(anchors)] + /// Indicates that a transaction originating from LDK needs to have its fee bumped. This event + /// requires confirmed external funds to be readily available to spend. + /// + /// LDK does not currently generate this event. It is limited to the scope of channels with + /// anchor outputs, which will be introduced in a future release. + BumpTransaction(BumpTransactionEvent), } impl Writeable for Event { @@ -643,7 +737,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, @@ -658,7 +752,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), @@ -753,6 +847,15 @@ impl Writeable for Event { (2, failed_next_destination, required), }) }, + #[cfg(anchors)] + &Event::BumpTransaction(ref event)=> { + 27u8.write(writer)?; + match event { + // We never write the ChannelClose events as they'll be replayed upon restarting + // anyway if the commitment transaction remains unconfirmed. + BumpTransactionEvent::ChannelClose { .. } => {} + } + } // 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`. @@ -827,7 +930,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![]); @@ -837,7 +940,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), @@ -847,7 +950,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(), @@ -1002,7 +1105,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(), @@ -1011,6 +1114,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. @@ -1115,25 +1240,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. @@ -1207,11 +1339,17 @@ pub trait OnionMessageProvider { /// /// # 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 @@ -1228,9 +1366,7 @@ pub trait OnionMessageProvider { 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; }