Rename payment_basepoint/key to simply payment_point/key.
[rust-lightning] / lightning / src / ln / msgs.rs
index e5903f7d603e947ebc5eb9440a1fb9adf3531cba..43005ad1d65370095f70e28823fc53ef2b95386f 100644 (file)
 //! raw socket events into your non-internet-facing system and then send routing events back to
 //! track the network on the less-secure system.
 
-use secp256k1::key::PublicKey;
-use secp256k1::Signature;
-use secp256k1;
-use bitcoin_hashes::sha256d::Hash as Sha256dHash;
+use bitcoin::secp256k1::key::PublicKey;
+use bitcoin::secp256k1::Signature;
+use bitcoin::secp256k1;
 use bitcoin::blockdata::script::Script;
+use bitcoin::hash_types::{Txid, BlockHash};
 
 use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 
-use std::error::Error;
 use std::{cmp, fmt};
 use std::io::Read;
 use std::result::Result;
@@ -31,7 +30,10 @@ use std::result::Result;
 use util::events;
 use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt};
 
-use ln::channelmanager::{PaymentPreimage, PaymentHash};
+use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret};
+
+/// 21 million * 10^8 * 1000
+pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000;
 
 /// An error in decoding a message or struct.
 #[derive(Debug)]
@@ -82,7 +84,7 @@ pub struct Pong {
 /// An open_channel message to be sent or received from a peer
 #[derive(Clone)]
 pub struct OpenChannel {
-       pub(crate) chain_hash: Sha256dHash,
+       pub(crate) chain_hash: BlockHash,
        pub(crate) temporary_channel_id: [u8; 32],
        pub(crate) funding_satoshis: u64,
        pub(crate) push_msat: u64,
@@ -95,7 +97,7 @@ pub struct OpenChannel {
        pub(crate) max_accepted_htlcs: u16,
        pub(crate) funding_pubkey: PublicKey,
        pub(crate) revocation_basepoint: PublicKey,
-       pub(crate) payment_basepoint: PublicKey,
+       pub(crate) payment_point: PublicKey,
        pub(crate) delayed_payment_basepoint: PublicKey,
        pub(crate) htlc_basepoint: PublicKey,
        pub(crate) first_per_commitment_point: PublicKey,
@@ -116,7 +118,7 @@ pub struct AcceptChannel {
        pub(crate) max_accepted_htlcs: u16,
        pub(crate) funding_pubkey: PublicKey,
        pub(crate) revocation_basepoint: PublicKey,
-       pub(crate) payment_basepoint: PublicKey,
+       pub(crate) payment_point: PublicKey,
        pub(crate) delayed_payment_basepoint: PublicKey,
        pub(crate) htlc_basepoint: PublicKey,
        pub(crate) first_per_commitment_point: PublicKey,
@@ -127,7 +129,7 @@ pub struct AcceptChannel {
 #[derive(Clone)]
 pub struct FundingCreated {
        pub(crate) temporary_channel_id: [u8; 32],
-       pub(crate) funding_txid: Sha256dHash,
+       pub(crate) funding_txid: Txid,
        pub(crate) funding_output_index: u16,
        pub(crate) signature: Signature,
 }
@@ -401,7 +403,7 @@ pub struct NodeAnnouncement {
 #[derive(PartialEq, Clone, Debug)]
 pub struct UnsignedChannelAnnouncement {
        pub(crate) features: ChannelFeatures,
-       pub(crate) chain_hash: Sha256dHash,
+       pub(crate) chain_hash: BlockHash,
        pub(crate) short_channel_id: u64,
        /// One of the two node_ids which are endpoints of this channel
        pub        node_id_1: PublicKey,
@@ -423,7 +425,7 @@ pub struct ChannelAnnouncement {
 
 #[derive(PartialEq, Clone, Debug)]
 pub(crate) struct UnsignedChannelUpdate {
-       pub(crate) chain_hash: Sha256dHash,
+       pub(crate) chain_hash: BlockHash,
        pub(crate) short_channel_id: u64,
        pub(crate) timestamp: u32,
        pub(crate) flags: u16,
@@ -600,10 +602,11 @@ pub trait RoutingMessageHandler : Send + Sync {
        fn handle_htlc_fail_channel_update(&self, update: &HTLCFailChannelUpdate);
        /// Gets a subset of the channel announcements and updates required to dump our routing table
        /// to a remote node, starting at the short_channel_id indicated by starting_point and
-       /// including batch_amount entries.
-       fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(ChannelAnnouncement, ChannelUpdate, ChannelUpdate)>;
+       /// including the batch_amount entries immediately higher in numerical value than starting_point.
+       fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)>;
        /// Gets a subset of the node announcements required to dump our routing table to a remote node,
-       /// starting at the node *after* the provided publickey and including batch_amount entries.
+       /// starting at the node *after* the provided publickey and including batch_amount entries
+       /// immediately higher (as defined by <PublicKey as Ord>::cmp) than starting_point.
        /// If None is provided for starting_point, we start at the first node.
        fn get_next_node_announcements(&self, starting_point: Option<&PublicKey>, batch_amount: u8) -> Vec<NodeAnnouncement>;
        /// Returns whether a full sync should be requested from a peer.
@@ -611,8 +614,17 @@ pub trait RoutingMessageHandler : Send + Sync {
 }
 
 mod fuzzy_internal_msgs {
+       use ln::channelmanager::PaymentSecret;
+
        // These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
        // them from untrusted input):
+       #[derive(Clone)]
+       pub(crate) struct FinalOnionHopData {
+               pub(crate) 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(crate) total_msat: u64,
+       }
 
        pub(crate) enum OnionHopDataFormat {
                Legacy { // aka Realm-0
@@ -621,11 +633,15 @@ mod fuzzy_internal_msgs {
                NonFinalNode {
                        short_channel_id: u64,
                },
-               FinalNode,
+               FinalNode {
+                       payment_data: Option<FinalOnionHopData>,
+               },
        }
 
        pub struct OnionHopData {
                pub(crate) format: OnionHopDataFormat,
+               /// The value, in msat, of the payment after this hop's fee is deducted.
+               /// Message serialization may panic if this value is more than 21 million Bitcoin.
                pub(crate) amt_to_forward: u64,
                pub(crate) outgoing_cltv_value: u32,
                // 12 bytes of 0-padding for Legacy format
@@ -671,21 +687,16 @@ pub(crate) struct OnionErrorPacket {
        pub(crate) data: Vec<u8>,
 }
 
-impl Error for DecodeError {
-       fn description(&self) -> &str {
-               match *self {
-                       DecodeError::UnknownVersion => "Unknown realm byte in Onion packet",
-                       DecodeError::UnknownRequiredFeature => "Unknown required feature preventing decode",
-                       DecodeError::InvalidValue => "Nonsense bytes didn't map to the type they were interpreted as",
-                       DecodeError::ShortRead => "Packet extended beyond the provided bytes",
-                       DecodeError::BadLengthDescriptor => "A length descriptor in the packet didn't describe the later data correctly",
-                       DecodeError::Io(ref e) => e.description(),
-               }
-       }
-}
 impl fmt::Display for DecodeError {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-               f.write_str(self.description())
+               match *self {
+                       DecodeError::UnknownVersion => f.write_str("Unknown realm byte in Onion packet"),
+                       DecodeError::UnknownRequiredFeature => f.write_str("Unknown required feature preventing decode"),
+                       DecodeError::InvalidValue => f.write_str("Nonsense bytes didn't map to the type they were interpreted as"),
+                       DecodeError::ShortRead => f.write_str("Packet extended beyond the provided bytes"),
+                       DecodeError::BadLengthDescriptor => f.write_str("A length descriptor in the packet didn't describe the later data correctly"),
+                       DecodeError::Io(ref e) => e.fmt(f),
+               }
        }
 }
 
@@ -746,7 +757,7 @@ impl_writeable_len_match!(AcceptChannel, {
        max_accepted_htlcs,
        funding_pubkey,
        revocation_basepoint,
-       payment_basepoint,
+       payment_point,
        delayed_payment_basepoint,
        htlc_basepoint,
        first_per_commitment_point,
@@ -873,7 +884,7 @@ impl_writeable_len_match!(OpenChannel, {
        max_accepted_htlcs,
        funding_pubkey,
        revocation_basepoint,
-       payment_basepoint,
+       payment_point,
        delayed_payment_basepoint,
        htlc_basepoint,
        first_per_commitment_point,
@@ -964,9 +975,29 @@ impl_writeable!(UpdateAddHTLC, 32+8+8+32+4+1366, {
        onion_routing_packet
 });
 
+impl Writeable for FinalOnionHopData {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               w.size_hint(32 + 8 - (self.total_msat.leading_zeros()/8) as usize);
+               self.payment_secret.0.write(w)?;
+               HighZeroBytesDroppedVarInt(self.total_msat).write(w)
+       }
+}
+
+impl Readable for FinalOnionHopData {
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let secret: [u8; 32] = Readable::read(r)?;
+               let amt: HighZeroBytesDroppedVarInt<u64> = Readable::read(r)?;
+               Ok(Self { payment_secret: PaymentSecret(secret), total_msat: amt.0 })
+       }
+}
+
 impl Writeable for OnionHopData {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
                w.size_hint(33);
+               // Note that this should never be reachable if Rust-Lightning generated the message, as we
+               // check values are sane long before we get here, though its possible in the future
+               // user-generated messages may hit this.
+               if self.amt_to_forward > MAX_VALUE_MSAT { panic!("We should never be sending infinite/overflow onion payments"); }
                match self.format {
                        OnionHopDataFormat::Legacy { short_channel_id } => {
                                0u8.write(w)?;
@@ -982,7 +1013,15 @@ impl Writeable for OnionHopData {
                                        (6, short_channel_id)
                                });
                        },
-                       OnionHopDataFormat::FinalNode => {
+                       OnionHopDataFormat::FinalNode { payment_data: Some(ref final_data) } => {
+                               if final_data.total_msat > MAX_VALUE_MSAT { panic!("We should never be sending infinite/overflow onion payments"); }
+                               encode_varint_length_prefixed_tlv!(w, {
+                                       (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)),
+                                       (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value)),
+                                       (8, final_data)
+                               });
+                       },
+                       OnionHopDataFormat::FinalNode { payment_data: None } => {
                                encode_varint_length_prefixed_tlv!(w, {
                                        (2, HighZeroBytesDroppedVarInt(self.amt_to_forward)),
                                        (4, HighZeroBytesDroppedVarInt(self.outgoing_cltv_value))
@@ -1007,19 +1046,29 @@ impl Readable for OnionHopData {
                        let mut amt = HighZeroBytesDroppedVarInt(0u64);
                        let mut cltv_value = HighZeroBytesDroppedVarInt(0u32);
                        let mut short_id: Option<u64> = None;
+                       let mut payment_data: Option<FinalOnionHopData> = None;
                        decode_tlv!(&mut rd, {
                                (2, amt),
                                (4, cltv_value)
                        }, {
-                               (6, short_id)
+                               (6, short_id),
+                               (8, payment_data)
                        });
                        rd.eat_remaining().map_err(|_| DecodeError::ShortRead)?;
                        let format = if let Some(short_channel_id) = short_id {
+                               if payment_data.is_some() { return Err(DecodeError::InvalidValue); }
                                OnionHopDataFormat::NonFinalNode {
                                        short_channel_id,
                                }
                        } else {
-                               OnionHopDataFormat::FinalNode
+                               if let &Some(ref data) = &payment_data {
+                                       if data.total_msat > MAX_VALUE_MSAT {
+                                               return Err(DecodeError::InvalidValue);
+                                       }
+                               }
+                               OnionHopDataFormat::FinalNode {
+                                       payment_data
+                               }
                        };
                        (format, amt.0, cltv_value.0)
                } else {
@@ -1032,6 +1081,9 @@ impl Readable for OnionHopData {
                        (format, amt, cltv_value)
                };
 
+               if amt > MAX_VALUE_MSAT {
+                       return Err(DecodeError::InvalidValue);
+               }
                Ok(OnionHopData {
                        format,
                        amt_to_forward: amt,
@@ -1304,19 +1356,19 @@ impl_writeable_len_match!(NodeAnnouncement, {
 mod tests {
        use hex;
        use ln::msgs;
-       use ln::msgs::{ChannelFeatures, InitFeatures, NodeFeatures, OptionalField, OnionErrorPacket, OnionHopDataFormat};
-       use ln::channelmanager::{PaymentPreimage, PaymentHash};
+       use ln::msgs::{ChannelFeatures, FinalOnionHopData, InitFeatures, NodeFeatures, OptionalField, OnionErrorPacket, OnionHopDataFormat};
+       use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret};
        use util::ser::{Writeable, Readable};
 
-       use bitcoin_hashes::sha256d::Hash as Sha256dHash;
-       use bitcoin_hashes::hex::FromHex;
+       use bitcoin::hashes::hex::FromHex;
        use bitcoin::util::address::Address;
        use bitcoin::network::constants::Network;
        use bitcoin::blockdata::script::Builder;
        use bitcoin::blockdata::opcodes;
+       use bitcoin::hash_types::{Txid, BlockHash};
 
-       use secp256k1::key::{PublicKey,SecretKey};
-       use secp256k1::{Secp256k1, Message};
+       use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+       use bitcoin::secp256k1::{Secp256k1, Message};
 
        use std::io::Cursor;
 
@@ -1403,13 +1455,13 @@ mod tests {
                let sig_2 = get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101"));
                let sig_3 = get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101"));
                let sig_4 = get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101"));
-               let mut features = ChannelFeatures::supported();
+               let mut features = ChannelFeatures::known();
                if unknown_features_bits {
                        features = ChannelFeatures::from_le_bytes(vec![0xFF, 0xFF]);
                }
                let unsigned_channel_announcement = msgs::UnsignedChannelAnnouncement {
                        features,
-                       chain_hash: if !non_bitcoin_chain_hash { Sha256dHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap() } else { Sha256dHash::from_hex("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943").unwrap() },
+                       chain_hash: if !non_bitcoin_chain_hash { BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap() } else { BlockHash::from_hex("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943").unwrap() },
                        short_channel_id: 2316138423780173,
                        node_id_1: pubkey_1,
                        node_id_2: pubkey_2,
@@ -1559,7 +1611,7 @@ mod tests {
                let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
                let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
                let unsigned_channel_update = msgs::UnsignedChannelUpdate {
-                       chain_hash: if !non_bitcoin_chain_hash { Sha256dHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap() } else { Sha256dHash::from_hex("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943").unwrap() },
+                       chain_hash: if !non_bitcoin_chain_hash { BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap() } else { BlockHash::from_hex("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943").unwrap() },
                        short_channel_id: 2316138423780173,
                        timestamp: 20190119,
                        flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 } | if htlc_maximum_msat { 1 << 8 } else { 0 },
@@ -1621,7 +1673,7 @@ mod tests {
                let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx);
                let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
                let open_channel = msgs::OpenChannel {
-                       chain_hash: if !non_bitcoin_chain_hash { Sha256dHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap() } else { Sha256dHash::from_hex("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943").unwrap() },
+                       chain_hash: if !non_bitcoin_chain_hash { BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap() } else { BlockHash::from_hex("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943").unwrap() },
                        temporary_channel_id: [2; 32],
                        funding_satoshis: 1311768467284833366,
                        push_msat: 2536655962884945560,
@@ -1634,7 +1686,7 @@ mod tests {
                        max_accepted_htlcs: 49340,
                        funding_pubkey: pubkey_1,
                        revocation_basepoint: pubkey_2,
-                       payment_basepoint: pubkey_3,
+                       payment_point: pubkey_3,
                        delayed_payment_basepoint: pubkey_4,
                        htlc_basepoint: pubkey_5,
                        first_per_commitment_point: pubkey_6,
@@ -1688,7 +1740,7 @@ mod tests {
                        max_accepted_htlcs: 49340,
                        funding_pubkey: pubkey_1,
                        revocation_basepoint: pubkey_2,
-                       payment_basepoint: pubkey_3,
+                       payment_point: pubkey_3,
                        delayed_payment_basepoint: pubkey_4,
                        htlc_basepoint: pubkey_5,
                        first_per_commitment_point: pubkey_6,
@@ -1715,7 +1767,7 @@ mod tests {
                let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
                let funding_created = msgs::FundingCreated {
                        temporary_channel_id: [2; 32],
-                       funding_txid: Sha256dHash::from_hex("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(),
+                       funding_txid: Txid::from_hex("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(),
                        funding_output_index: 255,
                        signature: sig_1,
                };
@@ -1997,7 +2049,9 @@ mod tests {
        #[test]
        fn encoding_final_onion_hop_data() {
                let mut msg = msgs::OnionHopData {
-                       format: OnionHopDataFormat::FinalNode,
+                       format: OnionHopDataFormat::FinalNode {
+                               payment_data: None,
+                       },
                        amt_to_forward: 0x0badf00d01020304,
                        outgoing_cltv_value: 0xffffffff,
                };
@@ -2005,7 +2059,36 @@ mod tests {
                let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
                assert_eq!(encoded_value, target_value);
                msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
-               if let OnionHopDataFormat::FinalNode = msg.format { } else { panic!(); }
+               if let OnionHopDataFormat::FinalNode { payment_data: None } = msg.format { } else { panic!(); }
+               assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
+               assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
+       }
+
+       #[test]
+       fn encoding_final_onion_hop_data_with_secret() {
+               let expected_payment_secret = PaymentSecret([0x42u8; 32]);
+               let mut msg = msgs::OnionHopData {
+                       format: OnionHopDataFormat::FinalNode {
+                               payment_data: Some(FinalOnionHopData {
+                                       payment_secret: expected_payment_secret,
+                                       total_msat: 0x1badca1f
+                               }),
+                       },
+                       amt_to_forward: 0x0badf00d01020304,
+                       outgoing_cltv_value: 0xffffffff,
+               };
+               let encoded_value = msg.encode();
+               let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
+               assert_eq!(encoded_value, target_value);
+               msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+               if let OnionHopDataFormat::FinalNode {
+                       payment_data: Some(FinalOnionHopData {
+                               payment_secret,
+                               total_msat: 0x1badca1f
+                       })
+               } = msg.format {
+                       assert_eq!(payment_secret, expected_payment_secret);
+               } else { panic!(); }
                assert_eq!(msg.amt_to_forward, 0x0badf00d01020304);
                assert_eq!(msg.outgoing_cltv_value, 0xffffffff);
        }