/// Used in decrypting the onion packet's payload.
pub blinding_point: PublicKey,
/// The full onion packet including hop data, pubkey, and hmac
- pub onion_routing_packet: onion_message::Packet,
+ pub onion_routing_packet: onion_message::packet::Packet,
}
/// An [`update_fulfill_htlc`] message to be sent to or received from a peer.
fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
}
+#[derive(Clone)]
+#[cfg_attr(test, derive(Debug, PartialEq))]
+/// Information communicated in the onion to the recipient for multi-part tracking and proof that
+/// the payment is associated with an invoice.
+pub struct FinalOnionHopData {
+ /// When sending a multi-part payment, this secret is used to identify a payment across HTLCs.
+ /// Because it is generated by the recipient and included in the invoice, it also provides
+ /// proof to the recipient that the payment was sent by someone with the generated invoice.
+ pub payment_secret: PaymentSecret,
+ /// The intended total amount that this payment is for.
+ ///
+ /// Message serialization may panic if this value is more than 21 million Bitcoin.
+ pub total_msat: u64,
+}
+
mod fuzzy_internal_msgs {
use bitcoin::secp256k1::PublicKey;
use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay};
use crate::prelude::*;
use crate::ln::{PaymentPreimage, PaymentSecret};
use crate::ln::features::BlindedHopFeatures;
+ use super::FinalOnionHopData;
// These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
// them from untrusted input):
- #[derive(Clone)]
- #[cfg_attr(test, derive(Debug, PartialEq))]
- pub struct FinalOnionHopData {
- pub payment_secret: PaymentSecret,
- /// The total value, in msat, of the payment as received by the ultimate recipient.
- /// Message serialization may panic if this value is more than 21 million Bitcoin.
- pub total_msat: u64,
- }
pub enum InboundOnionPayload {
Forward {
payment_metadata: Option<Vec<u8>>,
keysend_preimage: Option<PaymentPreimage>,
custom_tlvs: Vec<(u64, Vec<u8>)>,
- amt_msat: u64,
- outgoing_cltv_value: u32,
+ sender_intended_htlc_amt_msat: u64,
+ cltv_expiry_height: u32,
},
BlindedForward {
short_channel_id: u64,
intro_node_blinding_point: PublicKey,
},
BlindedReceive {
- amt_msat: u64,
+ sender_intended_htlc_amt_msat: u64,
total_msat: u64,
- outgoing_cltv_value: u32,
+ cltv_expiry_height: u32,
payment_secret: PaymentSecret,
payment_constraints: PaymentConstraints,
intro_node_blinding_point: Option<PublicKey>,
payment_metadata: Option<Vec<u8>>,
keysend_preimage: Option<PaymentPreimage>,
custom_tlvs: Vec<(u64, Vec<u8>)>,
- amt_msat: u64,
- outgoing_cltv_value: u32,
+ sender_intended_htlc_amt_msat: u64,
+ cltv_expiry_height: u32,
},
BlindedForward {
encrypted_tlvs: Vec<u8>,
intro_node_blinding_point: Option<PublicKey>,
},
BlindedReceive {
- amt_msat: u64,
+ sender_intended_htlc_amt_msat: u64,
total_msat: u64,
- outgoing_cltv_value: u32,
+ cltv_expiry_height: u32,
encrypted_tlvs: Vec<u8>,
intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
}
let blinding_point: PublicKey = Readable::read(r)?;
let len: u16 = Readable::read(r)?;
let mut packet_reader = FixedLengthReader::new(r, len as u64);
- let onion_routing_packet: onion_message::Packet = <onion_message::Packet as LengthReadable>::read(&mut packet_reader)?;
+ let onion_routing_packet: onion_message::packet::Packet =
+ <onion_message::packet::Packet as LengthReadable>::read(&mut packet_reader)?;
Ok(Self {
blinding_point,
onion_routing_packet,
});
},
Self::Receive {
- ref payment_data, ref payment_metadata, ref keysend_preimage, amt_msat,
- outgoing_cltv_value, ref custom_tlvs,
+ ref payment_data, ref payment_metadata, ref keysend_preimage, sender_intended_htlc_amt_msat,
+ cltv_expiry_height, ref custom_tlvs,
} => {
// We need to update [`ln::outbound_payment::RecipientOnionFields::with_custom_tlvs`]
// to reject any reserved types in the experimental range if new ones are ever
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(keysend_tlv.iter()).collect();
custom_tlvs.sort_unstable_by_key(|(typ, _)| *typ);
_encode_varint_length_prefixed_tlv!(w, {
- (2, HighZeroBytesDroppedBigSize(*amt_msat), required),
- (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+ (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
+ (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
(8, payment_data, option),
(16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option)
}, custom_tlvs.iter());
});
},
Self::BlindedReceive {
- amt_msat, total_msat, outgoing_cltv_value, encrypted_tlvs,
+ sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs,
intro_node_blinding_point,
} => {
_encode_varint_length_prefixed_tlv!(w, {
- (2, HighZeroBytesDroppedBigSize(*amt_msat), required),
- (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+ (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
+ (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
(10, *encrypted_tlvs, required_vec),
(12, intro_node_blinding_point, option),
(18, HighZeroBytesDroppedBigSize(*total_msat), required)
})} => {
if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
Ok(Self::BlindedReceive {
- amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+ sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
total_msat: total_msat.ok_or(DecodeError::InvalidValue)?,
- outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
+ cltv_expiry_height: cltv_value.ok_or(DecodeError::InvalidValue)?,
payment_secret,
payment_constraints,
intro_node_blinding_point,
payment_data,
payment_metadata: payment_metadata.map(|w| w.0),
keysend_preimage,
- amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
- outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
+ sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+ cltv_expiry_height: cltv_value.ok_or(DecodeError::InvalidValue)?,
custom_tlvs,
})
}
payment_data: None,
payment_metadata: None,
keysend_preimage: None,
- amt_msat: 0x0badf00d01020304,
- outgoing_cltv_value: 0xffffffff,
+ sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+ cltv_expiry_height: 0xffffffff,
custom_tlvs: vec![],
};
let encoded_value = outbound_msg.encode();
let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &&node_signer)).unwrap();
if let msgs::InboundOnionPayload::Receive {
- payment_data: None, amt_msat, outgoing_cltv_value, ..
+ payment_data: None, sender_intended_htlc_amt_msat, cltv_expiry_height, ..
} = inbound_msg {
- assert_eq!(amt_msat, 0x0badf00d01020304);
- assert_eq!(outgoing_cltv_value, 0xffffffff);
+ assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304);
+ assert_eq!(cltv_expiry_height, 0xffffffff);
} else { panic!(); }
}
}),
payment_metadata: None,
keysend_preimage: None,
- amt_msat: 0x0badf00d01020304,
- outgoing_cltv_value: 0xffffffff,
+ sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+ cltv_expiry_height: 0xffffffff,
custom_tlvs: vec![],
};
let encoded_value = outbound_msg.encode();
payment_secret,
total_msat: 0x1badca1f
}),
- amt_msat, outgoing_cltv_value,
+ sender_intended_htlc_amt_msat, cltv_expiry_height,
payment_metadata: None,
keysend_preimage: None,
custom_tlvs,
} = inbound_msg {
assert_eq!(payment_secret, expected_payment_secret);
- assert_eq!(amt_msat, 0x0badf00d01020304);
- assert_eq!(outgoing_cltv_value, 0xffffffff);
+ assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304);
+ assert_eq!(cltv_expiry_height, 0xffffffff);
assert_eq!(custom_tlvs, vec![]);
} else { panic!(); }
}
payment_metadata: None,
keysend_preimage: None,
custom_tlvs: bad_type_range_tlvs,
- amt_msat: 0x0badf00d01020304,
- outgoing_cltv_value: 0xffffffff,
+ sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+ cltv_expiry_height: 0xffffffff,
};
let encoded_value = msg.encode();
let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
payment_metadata: None,
keysend_preimage: None,
custom_tlvs: expected_custom_tlvs.clone(),
- amt_msat: 0x0badf00d01020304,
- outgoing_cltv_value: 0xffffffff,
+ sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+ cltv_expiry_height: 0xffffffff,
};
let encoded_value = msg.encode();
let target_value = <Vec<u8>>::from_hex("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap();
payment_metadata: None,
keysend_preimage: None,
custom_tlvs,
- amt_msat,
- outgoing_cltv_value,
+ sender_intended_htlc_amt_msat,
+ cltv_expiry_height: outgoing_cltv_value,
..
} = inbound_msg {
assert_eq!(custom_tlvs, expected_custom_tlvs);
- assert_eq!(amt_msat, 0x0badf00d01020304);
+ assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304);
assert_eq!(outgoing_cltv_value, 0xffffffff);
} else { panic!(); }
}