+ let error_data = Readable::read(reader)?;
+ 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);
+ let mut path: Option<Vec<RouteHop>> = Some(vec![]);
+ let mut short_channel_id = None;
+ let mut retry = None;
+ let mut payment_id = None;
+ 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),
+ (7, short_channel_id, option),
+ (9, retry, option),
+ (11, payment_id, option),
+ });
+ Ok(Some(Event::PaymentPathFailed {
+ payment_id,
+ payment_hash,
+ rejected_by_dest,
+ network_update,
+ all_paths_failed: all_paths_failed.unwrap(),
+ path: path.unwrap(),
+ short_channel_id,
+ retry,
+ #[cfg(test)]
+ error_code,
+ #[cfg(test)]
+ error_data,
+ }))
+ };
+ f()
+ },
+ 4u8 => Ok(None),
+ 5u8 => {
+ let f = || {
+ let mut outputs = VecReadWrapper(Vec::new());
+ read_tlv_fields!(reader, {
+ (0, outputs, required),
+ });
+ Ok(Some(Event::SpendableOutputs { outputs: outputs.0 }))
+ };
+ f()
+ },
+ 7u8 => {
+ let f = || {
+ let mut fee_earned_msat = None;
+ let mut prev_channel_id = None;
+ let mut claim_from_onchain_tx = false;
+ let mut next_channel_id = None;
+ read_tlv_fields!(reader, {
+ (0, fee_earned_msat, option),
+ (1, prev_channel_id, option),
+ (2, claim_from_onchain_tx, required),
+ (3, next_channel_id, option),
+ });
+ Ok(Some(Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id }))
+ };
+ f()
+ },
+ 9u8 => {
+ let f = || {
+ let mut channel_id = [0; 32];
+ let mut reason = None;
+ let mut user_channel_id_opt = None;
+ read_tlv_fields!(reader, {
+ (0, channel_id, required),
+ (1, user_channel_id_opt, option),
+ (2, reason, ignorable),
+ });
+ if reason.is_none() { return Ok(None); }
+ let user_channel_id = if let Some(id) = user_channel_id_opt { id } else { 0 };
+ Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: reason.unwrap() }))
+ };
+ f()
+ },
+ 11u8 => {
+ let f = || {
+ let mut channel_id = [0; 32];
+ 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),
+ });
+ Ok(Some(Event::DiscardFunding { channel_id, transaction } ))
+ };
+ f()
+ },
+ 13u8 => {
+ let f = || {
+ let mut payment_id = PaymentId([0; 32]);
+ let mut payment_hash = None;
+ let mut path: Option<Vec<RouteHop>> = Some(vec![]);
+ read_tlv_fields!(reader, {
+ (0, payment_id, required),
+ (2, payment_hash, option),
+ (4, path, vec_type),
+ });
+ Ok(Some(Event::PaymentPathSuccessful {
+ payment_id,
+ payment_hash,
+ path: path.unwrap(),
+ }))
+ };
+ f()
+ },
+ 15u8 => {
+ let f = || {
+ let mut payment_hash = PaymentHash([0; 32]);
+ let mut payment_id = PaymentId([0; 32]);
+ read_tlv_fields!(reader, {
+ (0, payment_id, required),
+ (2, payment_hash, required),
+ });
+ Ok(Some(Event::PaymentFailed {
+ payment_id,
+ payment_hash,
+ }))
+ };
+ f()
+ },
+ 17u8 => {
+ // Value 17 is used for `Event::OpenChannelRequest`.
+ Ok(None)
+ },
+ 19u8 => {
+ let f = || {
+ let mut payment_hash = PaymentHash([0; 32]);
+ let mut purpose = None;
+ let mut amount_msat = 0;
+ read_tlv_fields!(reader, {
+ (0, payment_hash, required),
+ (2, purpose, ignorable),
+ (4, amount_msat, required),
+ });
+ if purpose.is_none() { return Ok(None); }
+ Ok(Some(Event::PaymentClaimed {
+ payment_hash,
+ purpose: purpose.unwrap(),
+ amount_msat,
+ }))
+ };
+ f()
+ },
+ 21u8 => {
+ let f = || {
+ let mut payment_id = PaymentId([0; 32]);
+ let mut payment_hash = PaymentHash([0; 32]);
+ let mut path: Option<Vec<RouteHop>> = Some(vec![]);
+ read_tlv_fields!(reader, {
+ (0, payment_id, required),
+ (2, payment_hash, required),
+ (4, path, vec_type),
+ });
+ Ok(Some(Event::ProbeSuccessful {
+ payment_id,
+ payment_hash,
+ path: path.unwrap(),
+ }))
+ };
+ f()
+ },
+ 23u8 => {
+ let f = || {
+ let mut payment_id = PaymentId([0; 32]);
+ let mut payment_hash = PaymentHash([0; 32]);
+ let mut path: Option<Vec<RouteHop>> = Some(vec![]);
+ let mut short_channel_id = None;
+ read_tlv_fields!(reader, {
+ (0, payment_id, required),
+ (2, payment_hash, required),
+ (4, path, vec_type),
+ (6, short_channel_id, option),
+ });
+ Ok(Some(Event::ProbeFailed{
+ payment_id,
+ payment_hash,
+ path: path.unwrap(),
+ short_channel_id,
+ }))
+ };
+ 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.
+ 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)