Skip to content

Commit 8db9dc0

Browse files
Support constructing and encoding onion payloads for blinded payments
1 parent 16f0fa1 commit 8db9dc0

File tree

2 files changed

+71
-17
lines changed

2 files changed

+71
-17
lines changed

lightning/src/ln/msgs.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,7 @@ pub trait OnionMessageHandler : OnionMessageProvider {
14191419
}
14201420

14211421
mod fuzzy_internal_msgs {
1422+
use bitcoin::secp256k1::PublicKey;
14221423
use crate::prelude::*;
14231424
use crate::ln::{PaymentPreimage, PaymentSecret};
14241425

@@ -1464,6 +1465,17 @@ mod fuzzy_internal_msgs {
14641465
amt_msat: u64,
14651466
outgoing_cltv_value: u32,
14661467
},
1468+
BlindedForward {
1469+
encrypted_tlvs: Vec<u8>,
1470+
intro_node_blinding_point: Option<PublicKey>,
1471+
},
1472+
BlindedReceive {
1473+
amt_msat: u64,
1474+
total_msat: u64,
1475+
outgoing_cltv_value: u32,
1476+
encrypted_tlvs: Vec<u8>,
1477+
intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
1478+
}
14671479
}
14681480

14691481
pub struct DecodedOnionErrorPacket {
@@ -2000,6 +2012,24 @@ impl Writeable for OutboundOnionPayload {
20002012
(16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option)
20012013
}, custom_tlvs.iter());
20022014
},
2015+
Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point } => {
2016+
_encode_varint_length_prefixed_tlv!(w, {
2017+
(10, *encrypted_tlvs, required_vec),
2018+
(12, intro_node_blinding_point, option)
2019+
});
2020+
},
2021+
Self::BlindedReceive {
2022+
amt_msat, total_msat, outgoing_cltv_value, encrypted_tlvs,
2023+
intro_node_blinding_point,
2024+
} => {
2025+
_encode_varint_length_prefixed_tlv!(w, {
2026+
(2, HighZeroBytesDroppedBigSize(*amt_msat), required),
2027+
(4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
2028+
(10, *encrypted_tlvs, required_vec),
2029+
(12, intro_node_blinding_point, option),
2030+
(18, HighZeroBytesDroppedBigSize(*total_msat), required)
2031+
});
2032+
},
20032033
}
20042034
Ok(())
20052035
}

lightning/src/ln/onion_utils.rs

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::ln::channelmanager::{HTLCSource, RecipientOnionFields};
1212
use crate::ln::msgs;
1313
use crate::ln::wire::Encode;
1414
use crate::routing::gossip::NetworkUpdate;
15-
use crate::routing::router::{Path, RouteHop};
15+
use crate::routing::router::{BlindedTail, Path, RouteHop};
1616
use crate::util::chacha20::{ChaCha20, ChaChaReader};
1717
use crate::util::errors::{self, APIError};
1818
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, LengthCalculatingWriter};
@@ -177,27 +177,51 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
177177
// the intended recipient).
178178
let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat };
179179
let cltv = if cur_cltv == starting_htlc_offset { hop.cltv_expiry_delta + starting_htlc_offset } else { cur_cltv };
180-
res.insert(0, if idx == 0 {
181-
msgs::OutboundOnionPayload::Receive {
182-
payment_data: if let Some(secret) = recipient_onion.payment_secret.take() {
183-
Some(msgs::FinalOnionHopData {
184-
payment_secret: secret,
185-
total_msat,
186-
})
187-
} else { None },
188-
payment_metadata: recipient_onion.payment_metadata.take(),
189-
keysend_preimage: *keysend_preimage,
190-
custom_tlvs: recipient_onion.custom_tlvs.clone(),
191-
amt_msat: value_msat,
192-
outgoing_cltv_value: cltv,
180+
if idx == 0 {
181+
if let Some(BlindedTail {
182+
blinding_point, hops, final_value_msat, excess_final_cltv_expiry_delta, ..
183+
}) = &path.blinded_tail {
184+
let mut blinding_point = Some(*blinding_point);
185+
for (i, blinded_hop) in hops.iter().enumerate() {
186+
if i == hops.len() - 1 {
187+
cur_value_msat += final_value_msat;
188+
cur_cltv += excess_final_cltv_expiry_delta;
189+
res.push(msgs::OutboundOnionPayload::BlindedReceive {
190+
amt_msat: *final_value_msat,
191+
total_msat,
192+
outgoing_cltv_value: cltv,
193+
encrypted_tlvs: blinded_hop.encrypted_payload.clone(),
194+
intro_node_blinding_point: blinding_point.take(),
195+
});
196+
} else {
197+
res.push(msgs::OutboundOnionPayload::BlindedForward {
198+
encrypted_tlvs: blinded_hop.encrypted_payload.clone(),
199+
intro_node_blinding_point: blinding_point.take(),
200+
});
201+
}
202+
}
203+
} else {
204+
res.push(msgs::OutboundOnionPayload::Receive {
205+
payment_data: if let Some(secret) = recipient_onion.payment_secret.take() {
206+
Some(msgs::FinalOnionHopData {
207+
payment_secret: secret,
208+
total_msat,
209+
})
210+
} else { None },
211+
payment_metadata: recipient_onion.payment_metadata.take(),
212+
keysend_preimage: *keysend_preimage,
213+
custom_tlvs: recipient_onion.custom_tlvs.clone(),
214+
amt_msat: value_msat,
215+
outgoing_cltv_value: cltv,
216+
});
193217
}
194218
} else {
195-
msgs::OutboundOnionPayload::Forward {
219+
res.insert(0, msgs::OutboundOnionPayload::Forward {
196220
short_channel_id: last_short_channel_id,
197221
amt_to_forward: value_msat,
198222
outgoing_cltv_value: cltv,
199-
}
200-
});
223+
});
224+
}
201225
cur_value_msat += hop.fee_msat;
202226
if cur_value_msat >= 21000000 * 100000000 * 1000 {
203227
return Err(APIError::InvalidRoute{err: "Channel fees overflowed?".to_owned()});

0 commit comments

Comments
 (0)