X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fmsgs.rs;h=d39f1a6084274762331b456d28494b725999d69e;hb=cf2c27800a1b30e72d4f7397c931cf6624594233;hp=41120ce036f0897b104e8b34da5540c41d7a18d3;hpb=06b05df75533bbbe1400bb3efca7e97cff78146f;p=rust-lightning diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 41120ce0..d39f1a60 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -53,7 +53,7 @@ use crate::io::{self, Cursor, Read}; use crate::io_extras::read_to_end; use crate::events::{EventsProvider, MessageSendEventsProvider}; -use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter; +use crate::crypto::streams::ChaChaPolyReadAdapter; use crate::util::logger; use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize}; use crate::util::base32; @@ -695,7 +695,7 @@ pub struct OnionMessage { /// 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. @@ -1650,6 +1650,10 @@ pub trait OnionMessageHandler: EventsProvider { /// drop and refuse to forward onion messages to this peer. fn peer_disconnected(&self, their_node_id: &PublicKey); + /// Performs actions that should happen roughly every ten seconds after startup. Allows handlers + /// to drop any buffered onion messages intended for prospective peers. + fn timer_tick_occurred(&self); + // Handler information: /// Gets the node feature flags which this handler itself supports. All available handlers are /// queried similarly and their feature flags are OR'd together to form the [`NodeFeatures`] @@ -1664,22 +1668,31 @@ pub trait OnionMessageHandler: EventsProvider { 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)] - 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 { @@ -1693,23 +1706,23 @@ mod fuzzy_internal_msgs { payment_metadata: Option>, keysend_preimage: Option, custom_tlvs: Vec<(u64, Vec)>, - amt_msat: u64, - outgoing_cltv_value: u32, + sender_intended_htlc_amt_msat: u64, + cltv_expiry_height: u32, }, BlindedForward { short_channel_id: u64, payment_relay: PaymentRelay, payment_constraints: PaymentConstraints, features: BlindedHopFeatures, - intro_node_blinding_point: PublicKey, + intro_node_blinding_point: Option, }, 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: PublicKey, + intro_node_blinding_point: Option, } } @@ -1725,17 +1738,17 @@ mod fuzzy_internal_msgs { payment_metadata: Option>, keysend_preimage: Option, custom_tlvs: Vec<(u64, Vec)>, - amt_msat: u64, - outgoing_cltv_value: u32, + sender_intended_htlc_amt_msat: u64, + cltv_expiry_height: u32, }, BlindedForward { encrypted_tlvs: Vec, intro_node_blinding_point: Option, }, BlindedReceive { - amt_msat: u64, + sender_intended_htlc_amt_msat: u64, total_msat: u64, - outgoing_cltv_value: u32, + cltv_expiry_height: u32, encrypted_tlvs: Vec, intro_node_blinding_point: Option, // Set if the introduction node of the blinded path is the final node } @@ -2232,7 +2245,8 @@ impl Readable for OnionMessage { 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 = ::read(&mut packet_reader)?; + let onion_routing_packet: onion_message::packet::Packet = + ::read(&mut packet_reader)?; Ok(Self { blinding_point, onion_routing_packet, @@ -2276,8 +2290,8 @@ impl Writeable for OutboundOnionPayload { }); }, 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 @@ -2286,8 +2300,8 @@ impl Writeable for OutboundOnionPayload { let mut custom_tlvs: Vec<&(u64, Vec)> = 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()); @@ -2299,12 +2313,12 @@ impl Writeable for OutboundOnionPayload { }); }, 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) @@ -2315,8 +2329,10 @@ impl Writeable for OutboundOnionPayload { } } -impl ReadableArgs<&NS> for InboundOnionPayload where NS::Target: NodeSigner { - fn read(r: &mut R, node_signer: &NS) -> Result { +impl ReadableArgs<(Option, &NS)> for InboundOnionPayload where NS::Target: NodeSigner { + fn read(r: &mut R, args: (Option, &NS)) -> Result { + let (update_add_blinding_point, node_signer) = args; + let mut amt = None; let mut cltv_value = None; let mut short_id: Option = None; @@ -2350,9 +2366,14 @@ impl ReadableArgs<&NS> for InboundOnionPayload where NS::Target: Node }); if amt.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) } + if intro_node_blinding_point.is_some() && update_add_blinding_point.is_some() { + return Err(DecodeError::InvalidValue) + } - if let Some(blinding_point) = intro_node_blinding_point { - if short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() { + if let Some(blinding_point) = intro_node_blinding_point.or(update_add_blinding_point) { + if short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() || + keysend_preimage.is_some() + { return Err(DecodeError::InvalidValue) } let enc_tlvs = encrypted_tlvs_opt.ok_or(DecodeError::InvalidValue)?.0; @@ -2373,7 +2394,7 @@ impl ReadableArgs<&NS> for InboundOnionPayload where NS::Target: Node payment_relay, payment_constraints, features, - intro_node_blinding_point: blinding_point, + intro_node_blinding_point, }) }, ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs { @@ -2381,12 +2402,12 @@ impl ReadableArgs<&NS> for InboundOnionPayload where NS::Target: Node })} => { 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: blinding_point, + intro_node_blinding_point, }) }, } @@ -2412,8 +2433,8 @@ impl ReadableArgs<&NS> for InboundOnionPayload where NS::Target: Node 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, }) } @@ -3983,7 +4004,7 @@ mod tests { assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap(); + let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &&node_signer)).unwrap(); if let msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = inbound_msg { @@ -3999,8 +4020,8 @@ mod tests { 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(); @@ -4008,12 +4029,12 @@ mod tests { assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap(); + 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!(); } } @@ -4027,8 +4048,8 @@ mod tests { }), 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(); @@ -4036,20 +4057,20 @@ mod tests { assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap(); + let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &&node_signer)).unwrap(); if let msgs::InboundOnionPayload::Receive { payment_data: Some(FinalOnionHopData { 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!(); } } @@ -4067,12 +4088,12 @@ mod tests { 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); - assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).is_err()); + assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..]), (None, &&node_signer)).is_err()); let good_type_range_tlvs = vec![ ((1 << 16) - 3, vec![42]), ((1 << 16) - 1, vec![42; 32]), @@ -4081,7 +4102,7 @@ mod tests { *custom_tlvs = good_type_range_tlvs.clone(); } let encoded_value = msg.encode(); - let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).unwrap(); + let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), (None, &&node_signer)).unwrap(); match inbound_msg { msgs::InboundOnionPayload::Receive { custom_tlvs, .. } => assert!(custom_tlvs.is_empty()), _ => panic!(), @@ -4099,25 +4120,25 @@ mod tests { 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 = >::from_hex("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap(); assert_eq!(encoded_value, target_value); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - let inbound_msg: msgs::InboundOnionPayload = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap(); + let inbound_msg: msgs::InboundOnionPayload = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &&node_signer)).unwrap(); if let msgs::InboundOnionPayload::Receive { payment_data: None, 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!(); } } @@ -4271,8 +4292,8 @@ mod tests { let mut rd = Cursor::new(&big_payload[..]); let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); - > - ::read(&mut rd, &&node_signer).unwrap(); + , &&test_utils::TestKeysInterface)>> + ::read(&mut rd, (None, &&node_signer)).unwrap(); } // see above test, needs to be a separate method for use of the serialization macros. fn encode_big_payload() -> Result, io::Error> {