BDR: Linearizing secp256k1 deps
[rust-lightning] / lightning / src / ln / msgs.rs
index 294dbb965e781aebdfa90bcb00ca4e2fff081755..6c1d3cd928700a13550327c87d47b6fe1d634577 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::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::blockdata::script::Script;
 
 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)]
@@ -612,11 +614,15 @@ 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: [u8; 32],
+               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,
        }
 
@@ -634,6 +640,8 @@ mod fuzzy_internal_msgs {
 
        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
@@ -679,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),
+               }
        }
 }
 
@@ -975,22 +978,26 @@ impl_writeable!(UpdateAddHTLC, 32+8+8+32+4+1366, {
 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.write(w)?;
+               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 payment_secret = Readable::read(r)?;
+               let secret: [u8; 32] = Readable::read(r)?;
                let amt: HighZeroBytesDroppedVarInt<u64> = Readable::read(r)?;
-               Ok(Self { payment_secret, total_msat: amt.0 })
+               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)?;
@@ -1007,6 +1014,7 @@ impl Writeable for OnionHopData {
                                });
                        },
                        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)),
@@ -1053,6 +1061,11 @@ impl Readable for OnionHopData {
                                        short_channel_id,
                                }
                        } else {
+                               if let &Some(ref data) = &payment_data {
+                                       if data.total_msat > MAX_VALUE_MSAT {
+                                               return Err(DecodeError::InvalidValue);
+                                       }
+                               }
                                OnionHopDataFormat::FinalNode {
                                        payment_data
                                }
@@ -1068,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,
@@ -1341,18 +1357,18 @@ mod tests {
        use hex;
        use ln::msgs;
        use ln::msgs::{ChannelFeatures, FinalOnionHopData, InitFeatures, NodeFeatures, OptionalField, OnionErrorPacket, OnionHopDataFormat};
-       use ln::channelmanager::{PaymentPreimage, PaymentHash};
+       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::sha256d::Hash as Sha256dHash;
+       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 secp256k1::key::{PublicKey,SecretKey};
-       use secp256k1::{Secp256k1, Message};
+       use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+       use bitcoin::secp256k1::{Secp256k1, Message};
 
        use std::io::Cursor;
 
@@ -2050,7 +2066,7 @@ mod tests {
 
        #[test]
        fn encoding_final_onion_hop_data_with_secret() {
-               let expected_payment_secret = [0x42u8; 32];
+               let expected_payment_secret = PaymentSecret([0x42u8; 32]);
                let mut msg = msgs::OnionHopData {
                        format: OnionHopDataFormat::FinalNode {
                                payment_data: Some(FinalOnionHopData {