Parameterize InboundPayload reads with NodeSigner
authorValentine Wallace <vwallace@protonmail.com>
Sun, 10 Sep 2023 05:10:03 +0000 (01:10 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Tue, 12 Sep 2023 22:11:59 +0000 (18:11 -0400)
This will be used in the next commit to deserialize encrypted TLVs for
receiving to 1-hop blinded paths.

fuzz/src/onion_hop_data.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_utils.rs

index 54b283ab0f1628974fa3545978699453f65330bb..cc80ccf932088423aa37e1a637c0b85e22322602 100644 (file)
 // To modify it, modify msg_target_template.txt and run gen_target.sh instead.
 
 use crate::utils::test_logger;
+use lightning::util::test_utils;
 
 #[inline]
 pub fn onion_hop_data_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       use lightning::util::ser::Readable;
+       use lightning::util::ser::ReadableArgs;
        let mut r = ::std::io::Cursor::new(data);
-       let _ =  <lightning::ln::msgs::InboundOnionPayload as Readable>::read(&mut r);
+       let node_signer = test_utils::TestNodeSigner::new(test_utils::privkey(42));
+       let _ =  <lightning::ln::msgs::InboundOnionPayload as ReadableArgs<&&test_utils::TestNodeSigner>>::read(&mut r, &&node_signer);
 }
 
 #[no_mangle]
 pub extern "C" fn onion_hop_data_run(data: *const u8, datalen: usize) {
-       use lightning::util::ser::Readable;
+       use lightning::util::ser::ReadableArgs;
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
        let mut r = ::std::io::Cursor::new(data);
-       let _ =  <lightning::ln::msgs::InboundOnionPayload as Readable>::read(&mut r);
+       let node_signer = test_utils::TestNodeSigner::new(test_utils::privkey(42));
+       let _ =  <lightning::ln::msgs::InboundOnionPayload as ReadableArgs<&&test_utils::TestNodeSigner>>::read(&mut r, &&node_signer);
 }
index 6ea51660008fbad931c76d7cef7254039fed16a5..0238c96960f6303ac91d8cb4fb5d2d46da832110 100644 (file)
@@ -2915,7 +2915,10 @@ where
                        }
                }
 
-               let next_hop = match onion_utils::decode_next_payment_hop(shared_secret, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac, msg.payment_hash) {
+               let next_hop = match onion_utils::decode_next_payment_hop(
+                       shared_secret, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac,
+                       msg.payment_hash, &self.node_signer
+               ) {
                        Ok(res) => res,
                        Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
                                return_malformed_err!(err_msg, err_code);
@@ -3924,7 +3927,10 @@ where
                                                                                        let phantom_pubkey_res = self.node_signer.get_node_id(Recipient::PhantomNode);
                                                                                        if phantom_pubkey_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id, &self.genesis_hash) {
                                                                                                let phantom_shared_secret = self.node_signer.ecdh(Recipient::PhantomNode, &onion_packet.public_key.unwrap(), None).unwrap().secret_bytes();
-                                                                                               let next_hop = match onion_utils::decode_next_payment_hop(phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac, payment_hash) {
+                                                                                               let next_hop = match onion_utils::decode_next_payment_hop(
+                                                                                                       phantom_shared_secret, &onion_packet.hop_data, onion_packet.hmac,
+                                                                                                       payment_hash, &self.node_signer
+                                                                                               ) {
                                                                                                        Ok(res) => res,
                                                                                                        Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
                                                                                                                let sha256_of_onion = Sha256::hash(&onion_packet.hop_data).into_inner();
index 8bb264fe9c6332a9950bda2045a27faf35ab553c..810270ca4e6ae7d890ed843c72c19cb1b67b0be8 100644 (file)
@@ -35,11 +35,13 @@ use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
 use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
 use crate::ln::onion_utils;
 use crate::onion_message;
+use crate::sign::NodeSigner;
 
 use crate::prelude::*;
 use core::convert::TryFrom;
 use core::fmt;
 use core::fmt::Debug;
+use core::ops::Deref;
 use core::str::FromStr;
 use crate::io::{self, Read};
 use crate::io_extras::read_to_end;
@@ -2132,8 +2134,8 @@ impl Writeable for OutboundOnionPayload {
        }
 }
 
-impl Readable for InboundOnionPayload {
-       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+impl<NS: Deref> ReadableArgs<&NS> for InboundOnionPayload where NS::Target: NodeSigner {
+       fn read<R: Read>(r: &mut R, node_signer: &NS) -> Result<Self, DecodeError> {
                let mut amt = HighZeroBytesDroppedBigSize(0u64);
                let mut cltv_value = HighZeroBytesDroppedBigSize(0u32);
                let mut short_id: Option<u64> = None;
@@ -2187,14 +2189,6 @@ impl Readable for InboundOnionPayload {
        }
 }
 
-// ReadableArgs because we need onion_utils::decode_next_hop to accommodate payment packets and
-// onion message packets.
-impl ReadableArgs<()> for InboundOnionPayload {
-       fn read<R: Read>(r: &mut R, _arg: ()) -> Result<Self, DecodeError> {
-               <Self as Readable>::read(r)
-       }
-}
-
 impl Writeable for Ping {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
                self.ponglen.write(w)?;
@@ -2612,7 +2606,8 @@ mod tests {
        use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket};
        use crate::ln::msgs::SocketAddress;
        use crate::routing::gossip::{NodeAlias, NodeId};
-       use crate::util::ser::{Writeable, Readable, Hostname, TransactionU16LenLimited};
+       use crate::util::ser::{Writeable, Readable, ReadableArgs, Hostname, TransactionU16LenLimited};
+       use crate::util::test_utils;
 
        use bitcoin::hashes::hex::FromHex;
        use bitcoin::util::address::Address;
@@ -3704,8 +3699,11 @@ mod tests {
                let target_value = hex::decode("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap();
                assert_eq!(encoded_value, target_value);
 
-               let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
-               if let msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = inbound_msg {
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
+               if let msgs::InboundOnionPayload::Forward {
+                       short_channel_id, amt_to_forward, outgoing_cltv_value
+               } = inbound_msg {
                        assert_eq!(short_channel_id, 0xdeadbeef1bad1dea);
                        assert_eq!(amt_to_forward, 0x0badf00d01020304);
                        assert_eq!(outgoing_cltv_value, 0xffffffff);
@@ -3726,8 +3724,11 @@ mod tests {
                let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
                assert_eq!(encoded_value, target_value);
 
-               let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
-               if let msgs::InboundOnionPayload::Receive { payment_data: None, amt_msat, outgoing_cltv_value, .. } = inbound_msg {
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
+               if let msgs::InboundOnionPayload::Receive {
+                       payment_data: None, amt_msat, outgoing_cltv_value, ..
+               } = inbound_msg {
                        assert_eq!(amt_msat, 0x0badf00d01020304);
                        assert_eq!(outgoing_cltv_value, 0xffffffff);
                } else { panic!(); }
@@ -3751,7 +3752,8 @@ mod tests {
                let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
                assert_eq!(encoded_value, target_value);
 
-               let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
                if let msgs::InboundOnionPayload::Receive {
                        payment_data: Some(FinalOnionHopData {
                                payment_secret,
@@ -3786,7 +3788,8 @@ mod tests {
                        outgoing_cltv_value: 0xffffffff,
                };
                let encoded_value = msg.encode();
-               assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..])).is_err());
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).is_err());
                let good_type_range_tlvs = vec![
                        ((1 << 16) - 3, vec![42]),
                        ((1 << 16) - 1, vec![42; 32]),
@@ -3795,7 +3798,7 @@ mod tests {
                        *custom_tlvs = good_type_range_tlvs.clone();
                }
                let encoded_value = msg.encode();
-               let inbound_msg = Readable::read(&mut Cursor::new(&encoded_value[..])).unwrap();
+               let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).unwrap();
                match inbound_msg {
                        msgs::InboundOnionPayload::Receive { custom_tlvs, .. } => assert!(custom_tlvs.is_empty()),
                        _ => panic!(),
@@ -3819,7 +3822,8 @@ mod tests {
                let encoded_value = msg.encode();
                let target_value = hex::decode("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap();
                assert_eq!(encoded_value, target_value);
-               let inbound_msg: msgs::InboundOnionPayload = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+               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();
                if let msgs::InboundOnionPayload::Receive {
                        payment_data: None,
                        payment_metadata: None,
@@ -3982,7 +3986,10 @@ mod tests {
                // payload length to be encoded over multiple bytes rather than a single u8.
                let big_payload = encode_big_payload().unwrap();
                let mut rd = Cursor::new(&big_payload[..]);
-               <msgs::InboundOnionPayload as Readable>::read(&mut rd).unwrap();
+
+               let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+               <msgs::InboundOnionPayload as ReadableArgs<&&test_utils::TestKeysInterface>>
+                       ::read(&mut rd, &&node_signer).unwrap();
        }
        // see above test, needs to be a separate method for use of the serialization macros.
        fn encode_big_payload() -> Result<Vec<u8>, io::Error> {
index 8782323ea77333d0ce1e46a17c17aebea2580051..666221b2dd47fbe400b506d7602435905f9a2010 100644 (file)
@@ -13,6 +13,7 @@ use crate::ln::msgs;
 use crate::ln::wire::Encode;
 use crate::routing::gossip::NetworkUpdate;
 use crate::routing::router::{BlindedTail, Path, RouteHop};
+use crate::sign::NodeSigner;
 use crate::util::chacha20::{ChaCha20, ChaChaReader};
 use crate::util::errors::{self, APIError};
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, LengthCalculatingWriter};
@@ -885,8 +886,11 @@ pub(crate) enum OnionDecodeErr {
        },
 }
 
-pub(crate) fn decode_next_payment_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash) -> Result<Hop, OnionDecodeErr> {
-       match decode_next_hop(shared_secret, hop_data, hmac_bytes, Some(payment_hash), ()) {
+pub(crate) fn decode_next_payment_hop<NS: Deref>(
+       shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash,
+       node_signer: &NS,
+) -> Result<Hop, OnionDecodeErr> where NS::Target: NodeSigner {
+       match decode_next_hop(shared_secret, hop_data, hmac_bytes, Some(payment_hash), node_signer) {
                Ok((next_hop_data, None)) => Ok(Hop::Receive(next_hop_data)),
                Ok((next_hop_data, Some((next_hop_hmac, FixedSizeOnionPacket(new_packet_bytes))))) => {
                        Ok(Hop::Forward {