Use Infallible for the unconstructable default custom message type
[rust-lightning] / lightning / src / ln / channelmanager.rs
index 56dcb057ddf10af8106f24904f05f849840c7c21..a4684bfe6cc2960438bfdc9e2e575ed2b7aa2f79 100644 (file)
@@ -54,7 +54,7 @@ use chain::keysinterface::{Sign, KeysInterface, KeysManager, InMemorySigner};
 use util::config::UserConfig;
 use util::events::{EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
 use util::{byte_utils, events};
-use util::ser::{Readable, ReadableArgs, MaybeReadable, Writeable, Writer};
+use util::ser::{BigSize, FixedLengthReader, Readable, ReadableArgs, MaybeReadable, Writeable, Writer};
 use util::chacha20::{ChaCha20, ChaChaReader};
 use util::logger::{Logger, Level};
 use util::errors::APIError;
@@ -489,7 +489,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
        /// The session_priv bytes of outbound payments which are pending resolution.
        /// The authoritative state of these HTLCs resides either within Channels or ChannelMonitors
        /// (if the channel has been force-closed), however we track them here to prevent duplicative
-       /// PaymentSent/PaymentFailed events. Specifically, in the case of a duplicative
+       /// PaymentSent/PaymentPathFailed events. Specifically, in the case of a duplicative
        /// update_fulfill_htlc message after a reconnect, we may "claim" a payment twice.
        /// Additionally, because ChannelMonitors are often not re-serialized after connecting block(s)
        /// which may generate a claim event, we may receive similar duplicate claim/fail MonitorEvents
@@ -2875,18 +2875,19 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        self.fail_htlc_backwards_internal(channel_state,
                                                htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data});
                                },
-                               HTLCSource::OutboundRoute { session_priv, mpp_id, .. } => {
+                               HTLCSource::OutboundRoute { session_priv, mpp_id, path, .. } => {
                                        let mut session_priv_bytes = [0; 32];
                                        session_priv_bytes.copy_from_slice(&session_priv[..]);
                                        let mut outbounds = self.pending_outbound_payments.lock().unwrap();
                                        if let hash_map::Entry::Occupied(mut sessions) = outbounds.entry(mpp_id) {
                                                if sessions.get_mut().remove(&session_priv_bytes) {
                                                        self.pending_events.lock().unwrap().push(
-                                                               events::Event::PaymentFailed {
+                                                               events::Event::PaymentPathFailed {
                                                                        payment_hash,
                                                                        rejected_by_dest: false,
                                                                        network_update: None,
                                                                        all_paths_failed: sessions.get().len() == 0,
+                                                                       path: path.clone(),
                                                                        #[cfg(test)]
                                                                        error_code: None,
                                                                        #[cfg(test)]
@@ -2951,11 +2952,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                // process_onion_failure we should close that channel as it implies our
                                                // next-hop is needlessly blaming us!
                                                self.pending_events.lock().unwrap().push(
-                                                       events::Event::PaymentFailed {
+                                                       events::Event::PaymentPathFailed {
                                                                payment_hash: payment_hash.clone(),
                                                                rejected_by_dest: !payment_retryable,
                                                                network_update,
                                                                all_paths_failed,
+                                                               path: path.clone(),
 #[cfg(test)]
                                                                error_code: onion_error_code,
 #[cfg(test)]
@@ -2977,11 +2979,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                // TODO: For non-temporary failures, we really should be closing the
                                                // channel here as we apparently can't relay through them anyway.
                                                self.pending_events.lock().unwrap().push(
-                                                       events::Event::PaymentFailed {
+                                                       events::Event::PaymentPathFailed {
                                                                payment_hash: payment_hash.clone(),
                                                                rejected_by_dest: path.len() == 1,
                                                                network_update: None,
                                                                all_paths_failed,
+                                                               path: path.clone(),
 #[cfg(test)]
                                                                error_code: Some(*failure_code),
 #[cfg(test)]
@@ -4930,10 +4933,74 @@ impl_writeable_tlv_based!(PendingHTLCInfo, {
        (8, outgoing_cltv_value, required)
 });
 
-impl_writeable_tlv_based_enum!(HTLCFailureMsg, ;
-       (0, Relay),
-       (1, Malformed),
-);
+
+impl Writeable for HTLCFailureMsg {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+               match self {
+                       HTLCFailureMsg::Relay(msgs::UpdateFailHTLC { channel_id, htlc_id, reason }) => {
+                               0u8.write(writer)?;
+                               channel_id.write(writer)?;
+                               htlc_id.write(writer)?;
+                               reason.write(writer)?;
+                       },
+                       HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
+                               channel_id, htlc_id, sha256_of_onion, failure_code
+                       }) => {
+                               1u8.write(writer)?;
+                               channel_id.write(writer)?;
+                               htlc_id.write(writer)?;
+                               sha256_of_onion.write(writer)?;
+                               failure_code.write(writer)?;
+                       },
+               }
+               Ok(())
+       }
+}
+
+impl Readable for HTLCFailureMsg {
+       fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               let id: u8 = Readable::read(reader)?;
+               match id {
+                       0 => {
+                               Ok(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
+                                       channel_id: Readable::read(reader)?,
+                                       htlc_id: Readable::read(reader)?,
+                                       reason: Readable::read(reader)?,
+                               }))
+                       },
+                       1 => {
+                               Ok(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
+                                       channel_id: Readable::read(reader)?,
+                                       htlc_id: Readable::read(reader)?,
+                                       sha256_of_onion: Readable::read(reader)?,
+                                       failure_code: Readable::read(reader)?,
+                               }))
+                       },
+                       // In versions prior to 0.0.101, HTLCFailureMsg objects were written with type 0 or 1 but
+                       // weren't length-prefixed and thus didn't support reading the TLV stream suffix of the network
+                       // messages contained in the variants.
+                       // In version 0.0.101, support for reading the variants with these types was added, and
+                       // we should migrate to writing these variants when UpdateFailHTLC or
+                       // UpdateFailMalformedHTLC get TLV fields.
+                       2 => {
+                               let length: BigSize = Readable::read(reader)?;
+                               let mut s = FixedLengthReader::new(reader, length.0);
+                               let res = Readable::read(&mut s)?;
+                               s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
+                               Ok(HTLCFailureMsg::Relay(res))
+                       },
+                       3 => {
+                               let length: BigSize = Readable::read(reader)?;
+                               let mut s = FixedLengthReader::new(reader, length.0);
+                               let res = Readable::read(&mut s)?;
+                               s.eat_remaining()?; // Return ShortRead if there's actually not enough bytes
+                               Ok(HTLCFailureMsg::Malformed(res))
+                       },
+                       _ => Err(DecodeError::UnknownRequiredFeature),
+               }
+       }
+}
+
 impl_writeable_tlv_based_enum!(PendingHTLCStatus, ;
        (0, Forward),
        (1, Fail),