Skip to content

Commit 07a5739

Browse files
Sending onion messages -- internal api changes
This commit covers the internal refactors needed for sending onion messages and docs updates
1 parent 0a9d88a commit 07a5739

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

lightning/src/ln/onion_message.rs

+93-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,79 @@
1+
/// The payload of an onion message.
2+
struct Payload {
3+
/// Onion message payloads contain an encrypted TLV stream, containing both "control" TLVs and
4+
/// sometimes user-provided custom "data" TLVs. See [`EncryptedTlvs`] for more information.
5+
encrypted_tlvs: EncryptedTlvs,
6+
// Coming soon:
7+
// message: Message
8+
9+
// Coming soon: custom TLVs
10+
11+
// Coming soon:
12+
// reply_path: BlindedRoute,
13+
}
14+
15+
impl Writeable for Payload {
16+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
17+
// calls:
18+
// * ChaCha20Poly1305RFC::encrypt_in_place
19+
}
20+
}
21+
22+
// Coming soon:
23+
// enum Message {
24+
// InvoiceRequest(InvoiceRequest),
25+
// Invoice(Invoice),
26+
// InvoiceError(InvoiceError),
27+
28+
/// Onion messages contain an encrypted TLV stream. This can be supplied by someone else, in the
29+
/// case that we're sending to a blinded route, or created by us if we're constructing payloads for
30+
/// unblinded hops in the onion message's path.
31+
enum EncryptedTlvs {
32+
/// If we're sending to a blinded route, the node that constructed the blinded route has provided
33+
/// our onion message's `EncryptedTlvs`, already encrypted and encoded into bytes.
34+
Blinded(Vec<u8>),
35+
/// If we're receiving an onion message or constructing an onion message to send through any
36+
/// unblinded nodes, we'll need to construct the onion message's `EncryptedTlvs` in their
37+
/// unblinded state to avoid encoding them into an intermediate `Vec`.
38+
// Below will later have an additional Vec<CustomTlv>
39+
Unblinded(ControlTlvs, SharedSecret),
40+
}
41+
42+
/// Onion messages have "control" TLVs and "data" TLVs. Control TLVs are used to control the
43+
/// direction and routing of an onion message from hop to hop, whereas data TLVs contain the onion
44+
/// message content itself.
45+
enum ControlTlvs {
46+
/// Control TLVs for the final recipient of an onion message.
47+
Receive {
48+
/// If `path_id` is `Some`, it is used to identify the blinded route that this onion message is
49+
/// sending to. This is useful for receivers to check that said blinded route is being used in
50+
/// the right context.
51+
path_id: Option<[u8; 32]>
52+
},
53+
/// Control TLVs for an intermediate forwarder of an onion message.
54+
Forward {
55+
/// The node id of the next hop in the onion message's path.
56+
next_node_id: PublicKey,
57+
/// Senders of onion messages have the option of specifying an overriding [`blinding_point`]
58+
/// for forwarding nodes along the path. If this field is absent, forwarding nodes will
59+
/// calculate the next hop's blinding point by multiplying the blinding point that they
60+
/// received by a blinding factor.
61+
///
62+
/// [`blinding_point`]: crate::ln::msgs::OnionMessage::blinding_point
63+
next_blinding_override: Option<PublicKey>,
64+
}
65+
}
66+
167
/// Used to construct the blinded hops portion of a blinded route. These hops cannot be identified
268
/// by outside observers and thus can be used to hide the identity of the recipient.
369
pub struct BlindedNode {
470
/// The blinded node id of this hop in a blinded route.
571
pub blinded_node_id: PublicKey,
672
/// The encrypted payload intended for this hop in a blinded route.
73+
// If we're sending to this blinded route, this payload will later be encoded into the
74+
// [`EncryptedTlvs`] for the hop when constructing the onion packet for sending.
75+
//
76+
// [`EncryptedTlvs`]: EncryptedTlvs
777
pub encrypted_payload: Vec<u8>,
878
}
979

@@ -74,14 +144,36 @@ impl<Signer: Sign, K: Deref> OnionMessager<Signer, K>
74144

75145
/// Send an empty onion message to `recipient`, routing it through `intermediate_nodes`.
76146
// NOTE: sending custom TLVs and reply paths aren't included atm
77-
pub fn send_onion_message(&self, recipient: Destination, intermediate_nodes: Vec<PublicKey>) -> Result<(), APIError> {}
147+
pub fn send_onion_message(&self, recipient: Destination, intermediate_nodes: Vec<PublicKey>) -> Result<(), APIError> {
148+
// calls:
149+
// * construct_path_keys
150+
// * build_payloads
151+
// * onion_utils::construct_onion_message_packet
152+
}
78153
}
79154

80155
impl OnionMessageHandler for OnionMessager {
81156
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &msgs::OnionMessage) {
82157
}
83158
}
84159

160+
/// Construct keys for sending an onion message along the given `path`.
161+
///
162+
/// Returns: `(encrypted_tlvs_keys, onion_packet_keys, blinded_node_ids)`
163+
/// where the encrypted tlvs keys are used to encrypt the `EncryptedTlvs` of the onion message, the
164+
/// onion packet keys are used to encrypt the onion packet, and the blinded node ids are used to set
165+
/// the [`blinded_node_id`]s if we're constructing a [`BlindedRoute`].
166+
///
167+
/// [`blinded_node_id`]: BlindedNode::blinded_node_id
168+
/// [`BlindedRoute`]: BlindedRoute
169+
fn construct_path_keys<T: secp256k1::Signing + secp256k1::Verification>(
170+
secp_ctx: &Secp256k1<T>, unblinded_hops: Vec<PublicKey>, blinded_hops: Vec<PublicKey>,
171+
session_priv: &SecretKey)
172+
-> Result<(Vec<SharedSecret>, Vec<onion_utils::OnionKeys>, Vec<PublicKey>), secp256k1::Error> {}
173+
174+
/// Build an onion message's payloads for encoding in the onion packet.
175+
fn build_payloads(blinding_secret: SecretKey, intermediate_nodes: Vec<PublicKey>, destination: Destination, encrypted_data_keys: Vec<SharedSecret>) -> Vec<Payload> {}
176+
85177
/// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
86178
/// [`SimpleArcPeerManager`]. See their docs for more details.
87179
pub type SimpleArcOnionMessager = OnionMessager<Arc<KeysManager>>;

lightning/src/ln/onion_utils.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ pub(super) fn construct_onion_packet(payloads: Vec<msgs::OnionHopData>, onion_ke
208208
construct_onion_packet_with_init_noise(payloads, onion_keys, packet_data, associated_data)
209209
}
210210

211+
/// Constructs the onion routing packet for onion messages.
212+
// NOTE: this could prob be DRY'd with `construct_onion_packet`, but it'd lead to a large-ish diff,
213+
// and it's a small method.
214+
pub(super) fn construct_onion_message_packet(payloads: Vec<onion_message::Payload>, onion_packet_keys: Vec<OnionKeys>, prng_seed: [u8; 32]) -> msgs::OnionPacket {
215+
// calls:
216+
// * construct_onion_packet_with_init_noise
217+
}
218+
211219
#[cfg(test)]
212220
// Used in testing to write bogus OnionHopDatas, which is otherwise not representable in
213221
// msgs::OnionHopData.
@@ -221,7 +229,8 @@ pub(super) fn construct_onion_packet_bogus_hopdata<HD: Writeable>(payloads: Vec<
221229
}
222230

223231
/// panics if route_size_insane(paylods)
224-
fn construct_onion_packet_with_init_noise<HD: Writeable>(mut payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, mut packet_data: [u8; ONION_DATA_LEN], associated_data: &PaymentHash) -> msgs::OnionPacket {
232+
fn construct_onion_packet_with_init_noise<HD: Writeable>(mut payloads: Vec<HD>, onion_keys: Vec<OnionKeys>, mut packet_data: [u8; ONION_DATA_LEN], associated_data: Option<&PaymentHash>) -> msgs::OnionPacket {
233+
// calls `onion_messages::Payload::write`
225234
let filler = {
226235
const ONION_HOP_DATA_LEN: usize = 65; // We may decrease this eventually after TLV is common
227236
let mut res = Vec::with_capacity(ONION_HOP_DATA_LEN * (payloads.len() - 1));

lightning/src/util/chacha20poly1305rfc.rs

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ mod real_chachapoly {
7070
self.mac.raw_result(out_tag);
7171
}
7272

73+
pub fn encrypt_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {}
74+
75+
fn encrypt_inner(&mut self, input_output: &mut [u8], output: Option<&mut [u8]>, out_tag: &mut [u8]) {}
76+
7377
pub fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
7478
assert!(input.len() == output.len());
7579
assert!(self.finished == false);

0 commit comments

Comments
 (0)