use ln::msgs::DecodeError;
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use routing::network_graph::NetworkUpdate;
-use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
+use util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
+use routing::router::RouteHop;
use bitcoin::blockdata::script::Script;
-
+use bitcoin::hashes::Hash;
+use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::key::PublicKey;
use io;
use prelude::*;
use core::time::Duration;
use core::ops::Deref;
+use bitcoin::Transaction;
/// Some information provided on receipt of payment depends on whether the payment received is a
/// spontaneous payment or a "conventional" lightning payment that's paying an invoice.
user_channel_id: u64,
},
/// Indicates we've received money! Just gotta dig out that payment preimage and feed it to
- /// ChannelManager::claim_funds to get it....
- /// Note that if the preimage is not known or the amount paid is incorrect, you should call
- /// ChannelManager::fail_htlc_backwards to free up resources for this HTLC and avoid
+ /// [`ChannelManager::claim_funds`] to get it....
+ /// Note that if the preimage is not known, you should call
+ /// [`ChannelManager::fail_htlc_backwards`] to free up resources for this HTLC and avoid
/// network congestion.
- /// The amount paid should be considered 'incorrect' when it is less than or more than twice
- /// the amount expected.
- /// If you fail to call either ChannelManager::claim_funds or
- /// ChannelManager::fail_htlc_backwards within the HTLC's timeout, the HTLC will be
+ /// If you fail to call either [`ChannelManager::claim_funds`] or
+ /// [`ChannelManager::fail_htlc_backwards`] within the HTLC's timeout, the HTLC will be
/// automatically failed.
+ ///
+ /// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
+ /// [`ChannelManager::fail_htlc_backwards`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards
PaymentReceived {
/// The hash for which the preimage should be handed to the ChannelManager.
payment_hash: PaymentHash,
- /// The value, in thousandths of a satoshi, that this payment is for. Note that you must
- /// compare this to the expected value before accepting the payment (as otherwise you are
- /// providing proof-of-payment for less than the value you expected!).
+ /// The value, in thousandths of a satoshi, that this payment is for.
amt: u64,
/// Information for claiming this received payment, based on whether the purpose of the
/// payment is to pay an invoice or to send a spontaneous payment.
/// 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.
+ /// Note for MPP payments: in rare cases, this event may be preceded by a `PaymentPathFailed`
+ /// 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
/// store it somehow!
payment_preimage: PaymentPreimage,
+ /// The hash which was given to [`ChannelManager::send_payment`].
+ ///
+ /// [`ChannelManager::send_payment`]: crate::ln::channelmanager::ChannelManager::send_payment
+ payment_hash: PaymentHash,
},
/// Indicates an outbound payment we made failed. Probably some intermediary node dropped
/// something. You may wish to retry with a different route.
- PaymentFailed {
+ PaymentPathFailed {
/// The hash which was given to ChannelManager::send_payment.
payment_hash: PaymentHash,
/// Indicates the payment was rejected for some reason by the recipient. This implies that
/// 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,
+ /// The payment path that failed.
+ path: Vec<RouteHop>,
#[cfg(test)]
error_code: Option<u16>,
#[cfg(test)]
channel_id: [u8; 32],
/// The reason the channel was closed.
reason: ClosureReason
+ },
+ /// Used to indicate to the user that they can abandon the funding transaction and recycle the
+ /// inputs for another purpose.
+ DiscardFunding {
+ /// The channel_id of the channel which has been closed.
+ channel_id: [u8; 32],
+ /// The full transaction received from the user
+ transaction: Transaction
}
}
(8, payment_preimage, option),
});
},
- &Event::PaymentSent { ref payment_preimage } => {
+ &Event::PaymentSent { ref payment_preimage, ref payment_hash} => {
2u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_preimage, required),
+ (1, payment_hash, required),
});
},
- &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, ref network_update, ref all_paths_failed,
+ &Event::PaymentPathFailed { ref payment_hash, ref rejected_by_dest, ref network_update,
+ ref all_paths_failed, ref path,
#[cfg(test)]
ref error_code,
#[cfg(test)]
(1, network_update, option),
(2, rejected_by_dest, required),
(3, all_paths_failed, required),
+ (5, path, vec_type),
});
},
&Event::PendingHTLCsForwardable { time_forwardable: _ } => {
4u8.write(writer)?;
- write_tlv_fields!(writer, {});
- // We don't write the time_fordwardable out at all, as we presume when the user
- // deserializes us at least that much time has elapsed.
+ // Note that we now ignore these on the read end as we'll re-generate them in
+ // ChannelManager, we write them here only for backwards compatibility.
},
&Event::SpendableOutputs { ref outputs } => {
5u8.write(writer)?;
(2, reason, required)
});
},
+ &Event::DiscardFunding { ref channel_id, ref transaction } => {
+ 11u8.write(writer)?;
+ write_tlv_fields!(writer, {
+ (0, channel_id, required),
+ (2, transaction, 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`.
}
Ok(())
}
impl MaybeReadable for Event {
fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
match Readable::read(reader)? {
+ // Note that we do not write a length-prefixed TLV for FundingGenerationReady events,
+ // unlike all other events, thus we return immediately here.
0u8 => Ok(None),
1u8 => {
let f = || {
2u8 => {
let f = || {
let mut payment_preimage = PaymentPreimage([0; 32]);
+ let mut payment_hash = None;
read_tlv_fields!(reader, {
(0, payment_preimage, required),
+ (1, payment_hash, option),
});
+ if payment_hash.is_none() {
+ payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()));
+ }
Ok(Some(Event::PaymentSent {
payment_preimage,
+ payment_hash: payment_hash.unwrap(),
}))
};
f()
let mut rejected_by_dest = false;
let mut network_update = None;
let mut all_paths_failed = Some(true);
+ let mut path: Option<Vec<RouteHop>> = Some(vec![]);
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, network_update, ignorable),
(2, rejected_by_dest, required),
(3, all_paths_failed, option),
+ (5, path, vec_type),
});
- Ok(Some(Event::PaymentFailed {
+ Ok(Some(Event::PaymentPathFailed {
payment_hash,
rejected_by_dest,
network_update,
all_paths_failed: all_paths_failed.unwrap(),
+ path: path.unwrap(),
#[cfg(test)]
error_code,
#[cfg(test)]
};
f()
},
- 4u8 => {
- let f = || {
- read_tlv_fields!(reader, {});
- Ok(Some(Event::PendingHTLCsForwardable {
- time_forwardable: Duration::from_secs(0)
- }))
- };
- f()
- },
+ 4u8 => Ok(None),
5u8 => {
let f = || {
let mut outputs = VecReadWrapper(Vec::new());
if reason.is_none() { return Ok(None); }
Ok(Some(Event::ChannelClosed { channel_id, reason: reason.unwrap() }))
},
+ 11u8 => {
+ let mut channel_id = [0; 32];
+ let mut transaction = Transaction{ version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() };
+ read_tlv_fields!(reader, {
+ (0, channel_id, required),
+ (2, transaction, required),
+ });
+ Ok(Some(Event::DiscardFunding { channel_id, transaction } ))
+ },
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
- x if x % 2 == 1 => Ok(None),
+ // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
+ // reads.
+ x if x % 2 == 1 => {
+ // If the event is of unknown type, assume it was written with `write_tlv_fields`,
+ // which prefixes the whole thing with a length BigSize. Because the event is
+ // odd-type unknown, we should treat it as `Ok(None)` even if it has some TLV
+ // fields that are even. Thus, we avoid using `read_tlv_fields` and simply read
+ // exactly the number of bytes specified, ignoring them entirely.
+ let tlv_len: BigSize = Readable::read(reader)?;
+ FixedLengthReader::new(reader, tlv_len.0)
+ .eat_remaining().map_err(|_| msgs::DecodeError::ShortRead)?;
+ Ok(None)
+ },
_ => Err(msgs::DecodeError::InvalidValue)
}
}