Pass PaymentContext through HTLC processing
[rust-lightning] / lightning / src / ln / msgs.rs
index f0db28949ed7e4aeaf422c4b78de828c04da317c..d688a38babc409eefd4d957203585f4e309c7cc4 100644 (file)
@@ -38,9 +38,9 @@ use crate::ln::onion_utils;
 use crate::onion_message;
 use crate::sign::{NodeSigner, Recipient};
 
+#[allow(unused_imports)]
 use crate::prelude::*;
-#[cfg(feature = "std")]
-use core::convert::TryFrom;
+
 use core::fmt;
 use core::fmt::Debug;
 use core::ops::Deref;
@@ -91,6 +91,16 @@ pub enum DecodeError {
        Io(io::ErrorKind),
        /// The message included zlib-compressed values, which we don't support.
        UnsupportedCompression,
+       /// Value is validly encoded but is dangerous to use.
+       ///
+       /// This is used for things like [`ChannelManager`] deserialization where we want to ensure
+       /// that we don't use a [`ChannelManager`] which is in out of sync with the [`ChannelMonitor`].
+       /// This indicates that there is a critical implementation flaw in the storage implementation
+       /// and it's unsafe to continue.
+       ///
+       /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+       /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
+       DangerousValue,
 }
 
 /// An [`init`] message to be sent to or received from a peer.
@@ -396,6 +406,10 @@ pub struct ChannelReady {
        pub short_channel_id_alias: Option<u64>,
 }
 
+/// A randomly chosen number that is used to identify inputs within an interactive transaction
+/// construction.
+pub type SerialId = u64;
+
 /// An stfu (quiescence) message to be sent by or received from the stfu initiator.
 // TODO(splicing): Add spec link for `stfu`; still in draft, using from https://github.com/lightning/bolts/pull/863
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -459,7 +473,7 @@ pub struct TxAddInput {
        pub channel_id: ChannelId,
        /// A randomly chosen unique identifier for this input, which is even for initiators and odd for
        /// non-initiators.
-       pub serial_id: u64,
+       pub serial_id: SerialId,
        /// Serialized transaction that contains the output this input spends to verify that it is non
        /// malleable.
        pub prevtx: TransactionU16LenLimited,
@@ -478,7 +492,7 @@ pub struct TxAddOutput {
        pub channel_id: ChannelId,
        /// A randomly chosen unique identifier for this output, which is even for initiators and odd for
        /// non-initiators.
-       pub serial_id: u64,
+       pub serial_id: SerialId,
        /// The satoshi value of the output
        pub sats: u64,
        /// The scriptPubKey for the output
@@ -493,7 +507,7 @@ pub struct TxRemoveInput {
        /// The channel ID
        pub channel_id: ChannelId,
        /// The serial ID of the input to be removed
-       pub serial_id: u64,
+       pub serial_id: SerialId,
 }
 
 /// A tx_remove_output message for removing an output during interactive transaction construction.
@@ -504,7 +518,7 @@ pub struct TxRemoveOutput {
        /// The channel ID
        pub channel_id: ChannelId,
        /// The serial ID of the output to be removed
-       pub serial_id: u64,
+       pub serial_id: SerialId,
 }
 
 /// A tx_complete message signalling the conclusion of a peer's transaction contributions during
@@ -843,6 +857,16 @@ impl SocketAddress {
        /// This maximum length is reached by a hostname address descriptor:
        /// a hostname with a maximum length of 255, its 1-byte length and a 2-byte port.
        pub(crate) const MAX_LEN: u16 = 258;
+
+       pub(crate) fn is_tor(&self) -> bool {
+               match self {
+                       &SocketAddress::TcpIpV4 {..} => false,
+                       &SocketAddress::TcpIpV6 {..} => false,
+                       &SocketAddress::OnionV2(_) => true,
+                       &SocketAddress::OnionV3 {..} => true,
+                       &SocketAddress::Hostname {..} => false,
+               }
+       }
 }
 
 impl Writeable for SocketAddress {
@@ -1126,8 +1150,16 @@ pub struct UnsignedNodeAnnouncement {
        pub alias: NodeAlias,
        /// List of addresses on which this node is reachable
        pub addresses: Vec<SocketAddress>,
-       pub(crate) excess_address_data: Vec<u8>,
-       pub(crate) excess_data: Vec<u8>,
+       /// Excess address data which was signed as a part of the message which we do not (yet) understand how
+       /// to decode.
+       ///
+       /// This is stored to ensure forward-compatibility as new address types are added to the lightning gossip protocol.
+       pub excess_address_data: Vec<u8>,
+       /// Excess data which was signed as a part of the message which we do not (yet) understand how
+       /// to decode.
+       ///
+       /// This is stored to ensure forward-compatibility as new fields are added to the lightning gossip protocol.
+       pub excess_data: Vec<u8>,
 }
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 /// A [`node_announcement`] message to be sent to or received from a peer.
@@ -1640,11 +1672,13 @@ pub struct FinalOnionHopData {
 
 mod fuzzy_internal_msgs {
        use bitcoin::secp256k1::PublicKey;
-       use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay};
-       use crate::prelude::*;
+       use crate::blinded_path::payment::{PaymentConstraints, PaymentContext, PaymentRelay};
        use crate::ln::{PaymentPreimage, PaymentSecret};
        use crate::ln::features::BlindedHopFeatures;
-       use super::FinalOnionHopData;
+       use super::{FinalOnionHopData, TrampolineOnionPacket};
+
+       #[allow(unused_imports)]
+       use crate::prelude::*;
 
        // These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
        // them from untrusted input):
@@ -1677,7 +1711,10 @@ mod fuzzy_internal_msgs {
                        cltv_expiry_height: u32,
                        payment_secret: PaymentSecret,
                        payment_constraints: PaymentConstraints,
+                       payment_context: PaymentContext,
                        intro_node_blinding_point: Option<PublicKey>,
+                       keysend_preimage: Option<PaymentPreimage>,
+                       custom_tlvs: Vec<(u64, Vec<u8>)>,
                }
        }
 
@@ -1688,6 +1725,13 @@ mod fuzzy_internal_msgs {
                        amt_to_forward: u64,
                        outgoing_cltv_value: u32,
                },
+               #[allow(unused)]
+               TrampolineEntrypoint {
+                       amt_to_forward: u64,
+                       outgoing_cltv_value: u32,
+                       multipath_trampoline_data: Option<FinalOnionHopData>,
+                       trampoline_packet: TrampolineOnionPacket,
+               },
                Receive {
                        payment_data: Option<FinalOnionHopData>,
                        payment_metadata: Option<Vec<u8>>,
@@ -1706,6 +1750,19 @@ mod fuzzy_internal_msgs {
                        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
+                       keysend_preimage: Option<PaymentPreimage>,
+                       custom_tlvs: Vec<(u64, Vec<u8>)>,
+               }
+       }
+
+       pub(crate) enum OutboundTrampolinePayload {
+               #[allow(unused)]
+               Forward {
+                       /// The value, in msat, of the payment after this hop's fee is deducted.
+                       amt_to_forward: u64,
+                       outgoing_cltv_value: u32,
+                       /// The node id to which the trampoline node must find a route
+                       outgoing_node_id: PublicKey,
                }
        }
 
@@ -1755,6 +1812,52 @@ impl fmt::Debug for OnionPacket {
        }
 }
 
+/// BOLT 4 onion packet including hop data for the next peer.
+#[derive(Clone, Hash, PartialEq, Eq)]
+pub struct TrampolineOnionPacket {
+       /// Bolt 04 version number
+       pub version: u8,
+       /// A random sepc256k1 point, used to build the ECDH shared secret to decrypt hop_data
+       pub public_key: PublicKey,
+       /// Encrypted payload for the next hop
+       //
+       // Unlike the onion packets used for payments, Trampoline onion packets have to be shorter than
+       // 1300 bytes. The expected default is 650 bytes.
+       // TODO: if 650 ends up being the most common size, optimize this to be:
+       // enum { SixFifty([u8; 650]), VarLen(Vec<u8>) }
+       pub hop_data: Vec<u8>,
+       /// HMAC to verify the integrity of hop_data
+       pub hmac: [u8; 32],
+}
+
+impl onion_utils::Packet for TrampolineOnionPacket {
+       type Data = Vec<u8>;
+       fn new(public_key: PublicKey, hop_data: Vec<u8>, hmac: [u8; 32]) -> Self {
+               Self {
+                       version: 0,
+                       public_key,
+                       hop_data,
+                       hmac,
+               }
+       }
+}
+
+impl Writeable for TrampolineOnionPacket {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               self.version.write(w)?;
+               self.public_key.write(w)?;
+               w.write_all(&self.hop_data)?;
+               self.hmac.write(w)?;
+               Ok(())
+       }
+}
+
+impl Debug for TrampolineOnionPacket {
+       fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+               f.write_fmt(format_args!("TrampolineOnionPacket version {} with hmac {:?}", self.version, &self.hmac[..]))
+       }
+}
+
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 pub(crate) struct OnionErrorPacket {
        // This really should be a constant size slice, but the spec lets these things be up to 128KB?
@@ -1772,6 +1875,7 @@ impl fmt::Display for DecodeError {
                        DecodeError::BadLengthDescriptor => f.write_str("A length descriptor in the packet didn't describe the later data correctly"),
                        DecodeError::Io(ref e) => fmt::Debug::fmt(e, f),
                        DecodeError::UnsupportedCompression => f.write_str("We don't support receiving messages with zlib-compressed fields"),
+                       DecodeError::DangerousValue => f.write_str("Value would be dangerous to continue execution with"),
                }
        }
 }
@@ -2468,6 +2572,17 @@ impl Writeable for OutboundOnionPayload {
                                        (6, short_channel_id, required)
                                });
                        },
+                       Self::TrampolineEntrypoint {
+                               amt_to_forward, outgoing_cltv_value, ref multipath_trampoline_data,
+                               ref trampoline_packet
+                       } => {
+                               _encode_varint_length_prefixed_tlv!(w, {
+                                       (2, HighZeroBytesDroppedBigSize(*amt_to_forward), required),
+                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+                                       (8, multipath_trampoline_data, option),
+                                       (20, trampoline_packet, required)
+                               });
+                       },
                        Self::Receive {
                                ref payment_data, ref payment_metadata, ref keysend_preimage, sender_intended_htlc_amt_msat,
                                cltv_expiry_height, ref custom_tlvs,
@@ -2493,21 +2608,43 @@ impl Writeable for OutboundOnionPayload {
                        },
                        Self::BlindedReceive {
                                sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs,
-                               intro_node_blinding_point,
+                               intro_node_blinding_point, keysend_preimage, 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
+                               // standardized.
+                               let keysend_tlv = keysend_preimage.map(|preimage| (5482373484, preimage.encode()));
+                               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(*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)
-                               });
+                               }, custom_tlvs.iter());
                        },
                }
                Ok(())
        }
 }
 
+impl Writeable for OutboundTrampolinePayload {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               match self {
+                       Self::Forward { amt_to_forward, outgoing_cltv_value, outgoing_node_id } => {
+                               _encode_varint_length_prefixed_tlv!(w, {
+                                       (2, HighZeroBytesDroppedBigSize(*amt_to_forward), required),
+                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+                                       (14, outgoing_node_id, required)
+                               });
+                       }
+               }
+               Ok(())
+       }
+}
+
+
 impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload where NS::Target: NodeSigner {
        fn read<R: Read>(r: &mut R, args: (Option<PublicKey>, &NS)) -> Result<Self, DecodeError> {
                let (update_add_blinding_point, node_signer) = args;
@@ -2550,9 +2687,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                }
 
                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()
-                       {
+                       if short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() {
                                return Err(DecodeError::InvalidValue)
                        }
                        let enc_tlvs = encrypted_tlvs_opt.ok_or(DecodeError::InvalidValue)?.0;
@@ -2565,7 +2700,9 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Forward(ForwardTlvs {
                                        short_channel_id, payment_relay, payment_constraints, features
                                })} => {
-                                       if amt.is_some() || cltv_value.is_some() || total_msat.is_some() {
+                                       if amt.is_some() || cltv_value.is_some() || total_msat.is_some() ||
+                                               keysend_preimage.is_some()
+                                       {
                                                return Err(DecodeError::InvalidValue)
                                        }
                                        Ok(Self::BlindedForward {
@@ -2577,7 +2714,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                        })
                                },
                                ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs {
-                                       payment_secret, payment_constraints
+                                       payment_secret, payment_constraints, payment_context
                                })} => {
                                        if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
                                        Ok(Self::BlindedReceive {
@@ -2586,7 +2723,10 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                                cltv_expiry_height: cltv_value.ok_or(DecodeError::InvalidValue)?,
                                                payment_secret,
                                                payment_constraints,
+                                               payment_context,
                                                intro_node_blinding_point,
+                                               keysend_preimage,
+                                               custom_tlvs,
                                        })
                                },
                        }
@@ -3027,16 +3167,15 @@ impl_writeable_msg!(GossipTimestampFilter, {
 
 #[cfg(test)]
 mod tests {
-       use std::convert::TryFrom;
        use bitcoin::{Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut};
        use hex::DisplayHex;
        use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
        use crate::ln::ChannelId;
        use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
-       use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, CommonOpenChannelFields, CommonAcceptChannelFields};
+       use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, CommonOpenChannelFields, CommonAcceptChannelFields, TrampolineOnionPacket};
        use crate::ln::msgs::SocketAddress;
        use crate::routing::gossip::{NodeAlias, NodeId};
-       use crate::util::ser::{Writeable, Readable, ReadableArgs, Hostname, TransactionU16LenLimited};
+       use crate::util::ser::{BigSize, Hostname, Readable, ReadableArgs, TransactionU16LenLimited, Writeable};
        use crate::util::test_utils;
 
        use bitcoin::hashes::hex::FromHex;
@@ -4328,6 +4467,64 @@ mod tests {
                } else { panic!(); }
        }
 
+       #[test]
+       fn encoding_final_onion_hop_data_with_trampoline_packet() {
+               let secp_ctx = Secp256k1::new();
+               let (_private_key, public_key) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
+
+               let compressed_public_key = public_key.serialize();
+               assert_eq!(compressed_public_key.len(), 33);
+
+               let trampoline_packet = TrampolineOnionPacket {
+                       version: 0,
+                       public_key,
+                       hop_data: vec![1; 650], // this should be the standard encoded length
+                       hmac: [2; 32],
+               };
+               let encoded_trampoline_packet = trampoline_packet.encode();
+               assert_eq!(encoded_trampoline_packet.len(), 716);
+
+               let msg = msgs::OutboundOnionPayload::TrampolineEntrypoint {
+                       multipath_trampoline_data: None,
+                       amt_to_forward: 0x0badf00d01020304,
+                       outgoing_cltv_value: 0xffffffff,
+                       trampoline_packet,
+               };
+               let encoded_payload = msg.encode();
+
+               let trampoline_type_bytes = &encoded_payload[19..=19];
+               let mut trampoline_type_cursor = Cursor::new(trampoline_type_bytes);
+               let trampoline_type_big_size: BigSize = Readable::read(&mut trampoline_type_cursor).unwrap();
+               assert_eq!(trampoline_type_big_size.0, 20);
+
+               let trampoline_length_bytes = &encoded_payload[20..=22];
+               let mut trampoline_length_cursor = Cursor::new(trampoline_length_bytes);
+               let trampoline_length_big_size: BigSize = Readable::read(&mut trampoline_length_cursor).unwrap();
+               assert_eq!(trampoline_length_big_size.0, encoded_trampoline_packet.len() as u64);
+       }
+
+       #[test]
+       fn encoding_final_onion_hop_data_with_eclair_trampoline_packet() {
+               let public_key = PublicKey::from_slice(&<Vec<u8>>::from_hex("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()).unwrap();
+               let hop_data = <Vec<u8>>::from_hex("cff34152f3a36e52ca94e74927203a560392b9cc7ce3c45809c6be52166c24a595716880f95f178bf5b30ca63141f74db6e92795c6130877cfdac3d4bd3087ee73c65d627ddd709112a848cc99e303f3706509aa43ba7c8a88cba175fccf9a8f5016ef06d3b935dbb15196d7ce16dc1a7157845566901d7b2197e52cab4ce487014b14816e5805f9fcacb4f8f88b8ff176f1b94f6ce6b00bc43221130c17d20ef629db7c5f7eafaa166578c720619561dd14b3277db557ec7dcdb793771aef0f2f667cfdbeae3ac8d331c5994779dffb31e5fc0dbdedc0c592ca6d21c18e47fe3528d6975c19517d7e2ea8c5391cf17d0fe30c80913ed887234ccb48808f7ef9425bcd815c3b586210979e3bb286ef2851bf9ce04e28c40a203df98fd648d2f1936fd2f1def0e77eecb277229b4b682322371c0a1dbfcd723a991993df8cc1f2696b84b055b40a1792a29f710295a18fbd351b0f3ff34cd13941131b8278ba79303c89117120eea691738a9954908195143b039dbeed98f26a92585f3d15cf742c953799d3272e0545e9b744be9d3b4c").unwrap();
+               let hmac_vector = <Vec<u8>>::from_hex("bb079bfc4b35190eee9f59a1d7b41ba2f773179f322dafb4b1af900c289ebd6c").unwrap();
+               let mut hmac = [0; 32];
+               hmac.copy_from_slice(&hmac_vector);
+
+               let compressed_public_key = public_key.serialize();
+               assert_eq!(compressed_public_key.len(), 33);
+
+               let trampoline_packet = TrampolineOnionPacket {
+                       version: 0,
+                       public_key,
+                       hop_data,
+                       hmac,
+               };
+               let encoded_trampoline_packet = trampoline_packet.encode();
+               let expected_eclair_trampoline_packet = <Vec<u8>>::from_hex("0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619cff34152f3a36e52ca94e74927203a560392b9cc7ce3c45809c6be52166c24a595716880f95f178bf5b30ca63141f74db6e92795c6130877cfdac3d4bd3087ee73c65d627ddd709112a848cc99e303f3706509aa43ba7c8a88cba175fccf9a8f5016ef06d3b935dbb15196d7ce16dc1a7157845566901d7b2197e52cab4ce487014b14816e5805f9fcacb4f8f88b8ff176f1b94f6ce6b00bc43221130c17d20ef629db7c5f7eafaa166578c720619561dd14b3277db557ec7dcdb793771aef0f2f667cfdbeae3ac8d331c5994779dffb31e5fc0dbdedc0c592ca6d21c18e47fe3528d6975c19517d7e2ea8c5391cf17d0fe30c80913ed887234ccb48808f7ef9425bcd815c3b586210979e3bb286ef2851bf9ce04e28c40a203df98fd648d2f1936fd2f1def0e77eecb277229b4b682322371c0a1dbfcd723a991993df8cc1f2696b84b055b40a1792a29f710295a18fbd351b0f3ff34cd13941131b8278ba79303c89117120eea691738a9954908195143b039dbeed98f26a92585f3d15cf742c953799d3272e0545e9b744be9d3b4cbb079bfc4b35190eee9f59a1d7b41ba2f773179f322dafb4b1af900c289ebd6c").unwrap();
+               assert_eq!(encoded_trampoline_packet, expected_eclair_trampoline_packet);
+       }
+
        #[test]
        fn query_channel_range_end_blocknum() {
                let tests: Vec<(u32, u32, u32)> = vec![