Skip to content

Commit 7aebad9

Browse files
Replace OnionHopData with OutboundPayload for outbound onions
Follows on from the previous commit, see its message
1 parent 0f79b90 commit 7aebad9

File tree

4 files changed

+81
-92
lines changed

4 files changed

+81
-92
lines changed

lightning/src/ln/functional_tests.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -8039,7 +8039,9 @@ fn test_onion_value_mpp_set_calculation() {
80398039
RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap();
80408040
// Edit amt_to_forward to simulate the sender having set
80418041
// the final amount and the routing node taking less fee
8042-
onion_payloads[1].amt_to_forward = 99_000;
8042+
if let msgs::OutboundPayload::Receive { ref mut amt_msat, .. } = onion_payloads[1] {
8043+
*amt_msat = 99_000;
8044+
} else { panic!() }
80438045
let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap();
80448046
payment_event.msgs[0].onion_routing_packet = new_onion_packet;
80458047
}

lightning/src/ln/msgs.rs

+41-51
Original file line numberDiff line numberDiff line change
@@ -1441,25 +1441,21 @@ mod fuzzy_internal_msgs {
14411441
},
14421442
}
14431443

1444-
pub(crate) enum OnionHopDataFormat {
1445-
NonFinalNode {
1444+
pub(crate) enum OutboundPayload {
1445+
Forward {
14461446
short_channel_id: u64,
1447+
amt_to_forward: u64,
1448+
outgoing_cltv_value: u32,
14471449
},
1448-
FinalNode {
1450+
Receive {
14491451
payment_data: Option<FinalOnionHopData>,
14501452
payment_metadata: Option<Vec<u8>>,
14511453
keysend_preimage: Option<PaymentPreimage>,
1454+
amt_msat: u64,
1455+
outgoing_cltv_value: u32,
14521456
},
14531457
}
14541458

1455-
pub struct OnionHopData {
1456-
pub(crate) format: OnionHopDataFormat,
1457-
/// The value, in msat, of the payment after this hop's fee is deducted.
1458-
/// Message serialization may panic if this value is more than 21 million Bitcoin.
1459-
pub(crate) amt_to_forward: u64,
1460-
pub(crate) outgoing_cltv_value: u32,
1461-
}
1462-
14631459
pub struct DecodedOnionErrorPacket {
14641460
pub(crate) hmac: [u8; 32],
14651461
pub(crate) failuremsg: Vec<u8>,
@@ -1966,20 +1962,22 @@ impl Readable for FinalOnionHopData {
19661962
}
19671963
}
19681964

1969-
impl Writeable for OnionHopData {
1965+
impl Writeable for OutboundPayload {
19701966
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
1971-
match self.format {
1972-
OnionHopDataFormat::NonFinalNode { short_channel_id } => {
1967+
match self {
1968+
Self::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } => {
19731969
_encode_varint_length_prefixed_tlv!(w, {
1974-
(2, HighZeroBytesDroppedBigSize(self.amt_to_forward), required),
1975-
(4, HighZeroBytesDroppedBigSize(self.outgoing_cltv_value), required),
1970+
(2, HighZeroBytesDroppedBigSize(*amt_to_forward), required),
1971+
(4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
19761972
(6, short_channel_id, required)
19771973
});
19781974
},
1979-
OnionHopDataFormat::FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
1975+
Self::Receive {
1976+
ref payment_data, ref payment_metadata, ref keysend_preimage, amt_msat, outgoing_cltv_value
1977+
} => {
19801978
_encode_varint_length_prefixed_tlv!(w, {
1981-
(2, HighZeroBytesDroppedBigSize(self.amt_to_forward), required),
1982-
(4, HighZeroBytesDroppedBigSize(self.outgoing_cltv_value), required),
1979+
(2, HighZeroBytesDroppedBigSize(*amt_msat), required),
1980+
(4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
19831981
(8, payment_data, option),
19841982
(16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option),
19851983
(5482373484, keysend_preimage, option)
@@ -2454,7 +2452,7 @@ mod tests {
24542452
use hex;
24552453
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
24562454
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
2457-
use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, OnionHopDataFormat};
2455+
use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket};
24582456
use crate::routing::gossip::{NodeAlias, NodeId};
24592457
use crate::util::ser::{Writeable, Readable, Hostname, TransactionU16LenLimited};
24602458

@@ -3537,14 +3535,12 @@ mod tests {
35373535

35383536
#[test]
35393537
fn encoding_nonfinal_onion_hop_data() {
3540-
let msg = msgs::OnionHopData {
3541-
format: OnionHopDataFormat::NonFinalNode {
3542-
short_channel_id: 0xdeadbeef1bad1dea,
3543-
},
3538+
let outbound_msg = msgs::OutboundPayload::Forward {
3539+
short_channel_id: 0xdeadbeef1bad1dea,
35443540
amt_to_forward: 0x0badf00d01020304,
35453541
outgoing_cltv_value: 0xffffffff,
35463542
};
3547-
let encoded_value = msg.encode();
3543+
let encoded_value = outbound_msg.encode();
35483544
let target_value = hex::decode("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap();
35493545
assert_eq!(encoded_value, target_value);
35503546

@@ -3558,16 +3554,14 @@ mod tests {
35583554

35593555
#[test]
35603556
fn encoding_final_onion_hop_data() {
3561-
let msg = msgs::OnionHopData {
3562-
format: OnionHopDataFormat::FinalNode {
3563-
payment_data: None,
3564-
payment_metadata: None,
3565-
keysend_preimage: None,
3566-
},
3567-
amt_to_forward: 0x0badf00d01020304,
3557+
let outbound_msg = msgs::OutboundPayload::Receive {
3558+
payment_data: None,
3559+
payment_metadata: None,
3560+
keysend_preimage: None,
3561+
amt_msat: 0x0badf00d01020304,
35683562
outgoing_cltv_value: 0xffffffff,
35693563
};
3570-
let encoded_value = msg.encode();
3564+
let encoded_value = outbound_msg.encode();
35713565
let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
35723566
assert_eq!(encoded_value, target_value);
35733567

@@ -3581,19 +3575,17 @@ mod tests {
35813575
#[test]
35823576
fn encoding_final_onion_hop_data_with_secret() {
35833577
let expected_payment_secret = PaymentSecret([0x42u8; 32]);
3584-
let msg = msgs::OnionHopData {
3585-
format: OnionHopDataFormat::FinalNode {
3586-
payment_data: Some(FinalOnionHopData {
3587-
payment_secret: expected_payment_secret,
3588-
total_msat: 0x1badca1f
3589-
}),
3590-
payment_metadata: None,
3591-
keysend_preimage: None,
3592-
},
3593-
amt_to_forward: 0x0badf00d01020304,
3578+
let outbound_msg = msgs::OutboundPayload::Receive {
3579+
payment_data: Some(FinalOnionHopData {
3580+
payment_secret: expected_payment_secret,
3581+
total_msat: 0x1badca1f
3582+
}),
3583+
payment_metadata: None,
3584+
keysend_preimage: None,
3585+
amt_msat: 0x0badf00d01020304,
35943586
outgoing_cltv_value: 0xffffffff,
35953587
};
3596-
let encoded_value = msg.encode();
3588+
let encoded_value = outbound_msg.encode();
35973589
let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
35983590
assert_eq!(encoded_value, target_value);
35993591

@@ -3765,20 +3757,18 @@ mod tests {
37653757
// see above test, needs to be a separate method for use of the serialization macros.
37663758
fn encode_big_payload() -> Result<Vec<u8>, io::Error> {
37673759
use crate::util::ser::HighZeroBytesDroppedBigSize;
3768-
let payload = msgs::OnionHopData {
3769-
format: OnionHopDataFormat::NonFinalNode {
3770-
short_channel_id: 0xdeadbeef1bad1dea,
3771-
},
3760+
let payload = msgs::OutboundPayload::Forward {
3761+
short_channel_id: 0xdeadbeef1bad1dea,
37723762
amt_to_forward: 1000,
37733763
outgoing_cltv_value: 0xffffffff,
37743764
};
37753765
let mut encoded_payload = Vec::new();
37763766
let test_bytes = vec![42u8; 1000];
3777-
if let OnionHopDataFormat::NonFinalNode { short_channel_id } = payload.format {
3767+
if let msgs::OutboundPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = payload {
37783768
_encode_varint_length_prefixed_tlv!(&mut encoded_payload, {
37793769
(1, test_bytes, required_vec),
3780-
(2, HighZeroBytesDroppedBigSize(payload.amt_to_forward), required),
3781-
(4, HighZeroBytesDroppedBigSize(payload.outgoing_cltv_value), required),
3770+
(2, HighZeroBytesDroppedBigSize(amt_to_forward), required),
3771+
(4, HighZeroBytesDroppedBigSize(outgoing_cltv_value), required),
37823772
(6, short_channel_id, required)
37833773
});
37843774
}

lightning/src/ln/onion_route_tests.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ struct BogusOnionHopData {
252252
data: Vec<u8>
253253
}
254254
impl BogusOnionHopData {
255-
fn new(orig: msgs::OnionHopData) -> Self {
255+
fn new(orig: msgs::OutboundPayload) -> Self {
256256
Self { data: orig.encode() }
257257
}
258258
}
@@ -875,15 +875,15 @@ fn test_always_create_tlv_format_onion_payloads() {
875875
let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(
876876
&route.paths[0], 40000, RecipientOnionFields::spontaneous_empty(), cur_height, &None).unwrap();
877877

878-
match onion_payloads[0].format {
879-
msgs::OnionHopDataFormat::NonFinalNode {..} => {},
878+
match onion_payloads[0] {
879+
msgs::OutboundPayload::Forward {..} => {},
880880
_ => { panic!(
881881
"Should have generated a `msgs::OnionHopDataFormat::NonFinalNode` payload for `hops[0]`,
882882
despite that the features signals no support for variable length onions"
883883
)}
884884
}
885-
match onion_payloads[1].format {
886-
msgs::OnionHopDataFormat::FinalNode {..} => {},
885+
match onion_payloads[1] {
886+
msgs::OutboundPayload::Receive {..} => {},
887887
_ => {panic!(
888888
"Should have generated a `msgs::OnionHopDataFormat::FinalNode` payload for `hops[1]`,
889889
despite that the features signals no support for variable length onions"

lightning/src/ln/onion_utils.rs

+32-35
Original file line numberDiff line numberDiff line change
@@ -149,37 +149,37 @@ pub(super) fn construct_onion_keys<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T
149149
}
150150

151151
/// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
152-
pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields, starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(Vec<msgs::OnionHopData>, u64, u32), APIError> {
152+
pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_onion: RecipientOnionFields, starting_htlc_offset: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(Vec<msgs::OutboundPayload>, u64, u32), APIError> {
153153
let mut cur_value_msat = 0u64;
154154
let mut cur_cltv = starting_htlc_offset;
155155
let mut last_short_channel_id = 0;
156-
let mut res: Vec<msgs::OnionHopData> = Vec::with_capacity(path.hops.len());
156+
let mut res: Vec<msgs::OutboundPayload> = Vec::with_capacity(path.hops.len());
157157

158158
for (idx, hop) in path.hops.iter().rev().enumerate() {
159159
// First hop gets special values so that it can check, on receipt, that everything is
160160
// exactly as it should be (and the next hop isn't trying to probe to find out if we're
161161
// the intended recipient).
162162
let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat };
163163
let cltv = if cur_cltv == starting_htlc_offset { hop.cltv_expiry_delta + starting_htlc_offset } else { cur_cltv };
164-
res.insert(0, msgs::OnionHopData {
165-
format: if idx == 0 {
166-
msgs::OnionHopDataFormat::FinalNode {
167-
payment_data: if let Some(secret) = recipient_onion.payment_secret.take() {
168-
Some(msgs::FinalOnionHopData {
169-
payment_secret: secret,
170-
total_msat,
171-
})
172-
} else { None },
173-
payment_metadata: recipient_onion.payment_metadata.take(),
174-
keysend_preimage: *keysend_preimage,
175-
}
176-
} else {
177-
msgs::OnionHopDataFormat::NonFinalNode {
178-
short_channel_id: last_short_channel_id,
179-
}
180-
},
181-
amt_to_forward: value_msat,
182-
outgoing_cltv_value: cltv,
164+
res.insert(0, if idx == 0 {
165+
msgs::OutboundPayload::Receive {
166+
payment_data: if let Some(secret) = recipient_onion.payment_secret.take() {
167+
Some(msgs::FinalOnionHopData {
168+
payment_secret: secret,
169+
total_msat,
170+
})
171+
} else { None },
172+
payment_metadata: recipient_onion.payment_metadata.take(),
173+
keysend_preimage: *keysend_preimage,
174+
amt_msat: value_msat,
175+
outgoing_cltv_value: cltv,
176+
}
177+
} else {
178+
msgs::OutboundPayload::Forward {
179+
short_channel_id: last_short_channel_id,
180+
amt_to_forward: value_msat,
181+
outgoing_cltv_value: cltv,
182+
}
183183
});
184184
cur_value_msat += hop.fee_msat;
185185
if cur_value_msat >= 21000000 * 100000000 * 1000 {
@@ -208,7 +208,10 @@ fn shift_slice_right(arr: &mut [u8], amt: usize) {
208208
}
209209
}
210210

211-
pub(super) fn construct_onion_packet(payloads: Vec<msgs::OnionHopData>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32], associated_data: &PaymentHash) -> Result<msgs::OnionPacket, ()> {
211+
pub(super) fn construct_onion_packet(
212+
payloads: Vec<msgs::OutboundPayload>, onion_keys: Vec<OnionKeys>, prng_seed: [u8; 32],
213+
associated_data: &PaymentHash
214+
) -> Result<msgs::OnionPacket, ()> {
212215
let mut packet_data = [0; ONION_DATA_LEN];
213216

214217
let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
@@ -988,10 +991,8 @@ mod tests {
988991
// with raw hex instead of our in-memory enums, as the payloads contains custom types, and
989992
// we have no way of representing that with our enums.
990993
let payloads = vec!(
991-
RawOnionHopData::new(msgs::OnionHopData {
992-
format: msgs::OnionHopDataFormat::NonFinalNode {
993-
short_channel_id: 1,
994-
},
994+
RawOnionHopData::new(msgs::OutboundPayload::Forward {
995+
short_channel_id: 1,
995996
amt_to_forward: 15000,
996997
outgoing_cltv_value: 1500,
997998
}),
@@ -1013,17 +1014,13 @@ mod tests {
10131014
RawOnionHopData {
10141015
data: hex::decode("52020236b00402057806080000000000000002fd02013c0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f").unwrap(),
10151016
},
1016-
RawOnionHopData::new(msgs::OnionHopData {
1017-
format: msgs::OnionHopDataFormat::NonFinalNode {
1018-
short_channel_id: 3,
1019-
},
1017+
RawOnionHopData::new(msgs::OutboundPayload::Forward {
1018+
short_channel_id: 3,
10201019
amt_to_forward: 12500,
10211020
outgoing_cltv_value: 1250,
10221021
}),
1023-
RawOnionHopData::new(msgs::OnionHopData {
1024-
format: msgs::OnionHopDataFormat::NonFinalNode {
1025-
short_channel_id: 4,
1026-
},
1022+
RawOnionHopData::new(msgs::OutboundPayload::Forward {
1023+
short_channel_id: 4,
10271024
amt_to_forward: 10000,
10281025
outgoing_cltv_value: 1000,
10291026
}),
@@ -1101,7 +1098,7 @@ mod tests {
11011098
data: Vec<u8>
11021099
}
11031100
impl RawOnionHopData {
1104-
fn new(orig: msgs::OnionHopData) -> Self {
1101+
fn new(orig: msgs::OutboundPayload) -> Self {
11051102
Self { data: orig.encode() }
11061103
}
11071104
}

0 commit comments

Comments
 (0)