use io;
use prelude::*;
+use core::cmp;
use core::time::Duration;
use core::ops::Deref;
/// 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
/// [`NetworkGraph`]: crate::routing::network_graph::NetworkGraph
/// [`NetGraphMsgHandler`]: crate::routing::network_graph::NetGraphMsgHandler
network_update: Option<NetworkUpdate>,
+ /// 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<u16>,
#[cfg(test)]
/// 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 human-readable error message
+ err: String
+ }
}
impl Writeable for Event {
(0, payment_preimage, required),
});
},
- &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update,
+ &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed,
#[cfg(test)]
ref error_code,
#[cfg(test)]
(0, payment_hash, required),
(1, network_update, option),
(2, rejected_by_dest, required),
+ (3, all_paths_failed, required),
});
},
&Event::PendingHTLCsForwardable { time_forwardable: _ } => {
(2, claim_from_onchain_tx, required),
});
},
+ &Event::ChannelClosed { ref channel_id, ref err } => {
+ 6u8.write(writer)?;
+ channel_id.write(writer)?;
+ (err.len() as u16).write(writer)?;
+ writer.write_all(err.as_bytes())?;
+ write_tlv_fields!(writer, {});
+ },
}
Ok(())
}
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)]
},
// 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 = {
+ let mut size: usize = <u16 as Readable>::read(reader)? as usize;
+ let mut data = vec![];
+ let data_len = reader.read_to_end(&mut data)?;
+ size = cmp::min(data_len, size);
+ match String::from_utf8(data[..size as usize].to_vec()) {
+ Ok(s) => s,
+ Err(_) => return Err(msgs::DecodeError::InvalidValue),
+ }
+ };
+ read_tlv_fields!(reader, {});
+ Ok(Some(Event::ChannelClosed { channel_id, err: err }))
+ };
+ f()
+ },
_ => Err(msgs::DecodeError::InvalidValue)
}
}