From 154841b23410a53d72040859929902d4e6878c3f Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Sun, 10 Sep 2023 01:10:03 -0400 Subject: [PATCH] Parameterize InboundPayload reads with NodeSigner 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 | 11 ++++--- lightning/src/ln/channelmanager.rs | 10 +++++-- lightning/src/ln/msgs.rs | 47 +++++++++++++++++------------- lightning/src/ln/onion_utils.rs | 8 +++-- 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/fuzz/src/onion_hop_data.rs b/fuzz/src/onion_hop_data.rs index 54b283ab..cc80ccf9 100644 --- a/fuzz/src/onion_hop_data.rs +++ b/fuzz/src/onion_hop_data.rs @@ -11,18 +11,21 @@ // 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(data: &[u8], _out: Out) { - use lightning::util::ser::Readable; + use lightning::util::ser::ReadableArgs; let mut r = ::std::io::Cursor::new(data); - let _ = ::read(&mut r); + let node_signer = test_utils::TestNodeSigner::new(test_utils::privkey(42)); + let _ = >::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 _ = ::read(&mut r); + let node_signer = test_utils::TestNodeSigner::new(test_utils::privkey(42)); + let _ = >::read(&mut r, &&node_signer); } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 6ea51660..0238c969 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -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(); diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 8bb264fe..810270ca 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -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: &mut R) -> Result { +impl ReadableArgs<&NS> for InboundOnionPayload where NS::Target: NodeSigner { + fn read(r: &mut R, node_signer: &NS) -> Result { let mut amt = HighZeroBytesDroppedBigSize(0u64); let mut cltv_value = HighZeroBytesDroppedBigSize(0u32); let mut short_id: Option = 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: &mut R, _arg: ()) -> Result { - ::read(r) - } -} - impl Writeable for Ping { fn write(&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[..]); - ::read(&mut rd).unwrap(); + + let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet); + > + ::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, io::Error> { diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 8782323e..666221b2 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -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 { - match decode_next_hop(shared_secret, hop_data, hmac_bytes, Some(payment_hash), ()) { +pub(crate) fn decode_next_payment_hop( + shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash, + node_signer: &NS, +) -> Result 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 { -- 2.30.2