Skip to content

Commit

Permalink
Implement receiving and forwarding onion messages
Browse files Browse the repository at this point in the history
This required adapting `onion_utils::decode_next_hop` to work for both payments
and onion messages.

Currently we just print out the path_id of any onion messages we receive. In
the future, these received onion messages will be redirected to their
respective handlers: i.e. an invoice_request will go to an InvoiceHandler,
custom onion messages will go to a custom handler, etc.
  • Loading branch information
valentinewallace committed Jun 4, 2022
1 parent 4eb86d3 commit d2653d6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
4 changes: 2 additions & 2 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2139,7 +2139,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
}
}

let next_hop = match onion_utils::decode_next_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) {
Ok(res) => res,
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
return_malformed_err!(err_msg, err_code);
Expand Down Expand Up @@ -2955,7 +2955,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
let phantom_secret_res = self.keys_manager.get_node_secret(Recipient::PhantomNode);
if phantom_secret_res.is_ok() && fake_scid::is_valid_phantom(&self.fake_scid_rand_bytes, short_chan_id) {
let phantom_shared_secret = SharedSecret::new(&onion_packet.public_key.unwrap(), &phantom_secret_res.unwrap()).secret_bytes();
let next_hop = match onion_utils::decode_next_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) {
Ok(res) => res,
Err(onion_utils::OnionDecodeErr::Malformed { err_msg, err_code }) => {
let sha256_of_onion = Sha256::hash(&onion_packet.hop_data).into_inner();
Expand Down
7 changes: 7 additions & 0 deletions lightning/src/ln/onion_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ impl Writeable for (Payload, SharedSecret) {
}
}

/// Reads of `Payload`s are parameterized by the `rho` of a `SharedSecret`, which is used to decrypt
/// the onion message payload's `encrypted_data` field.
impl ReadableArgs<SharedSecret> for Payload {
fn read<R: Read>(mut r: &mut R, encrypted_tlvs_ss: SharedSecret) -> Result<Self, DecodeError> {
}
}

/// Onion messages contain an encrypted TLV stream. This can be supplied by someone else, in the
/// case that we're sending to a blinded route, or created by us if we're constructing payloads for
/// unblinded hops in the onion message's path.
Expand Down
40 changes: 38 additions & 2 deletions lightning/src/ln/onion_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,37 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
} else { unreachable!(); }
}

/// Data decrypted from the onion payload.
/// Used in the decoding of inbound payments' and onion messages' routing packets. This enum allows
/// us to use `decode_next_hop` to return the payloads and next hop packet bytes of both payments
/// and onion messages.
enum Payload {
/// This payload was for an incoming payment.
Payment(msgs::OnionHopData),
/// This payload was for an incoming onion message.
Message(onion_message::Payload),
}

enum NextPacketBytes {
Payment([u8; 20*65]),
Message(Vec<u8>),
}

/// Data decrypted from an onion message's onion payload.
pub(crate) enum MessageHop {
/// This onion payload was for us, not for forwarding to a next-hop.
Receive(onion_message::Payload),
/// This onion payload needs to be forwarded to a next-hop.
Forward {
/// Onion payload data used in forwarding the onion message.
next_hop_data: onion_message::Payload,
/// HMAC of the next hop's onion packet.
next_hop_hmac: [u8; 32],
/// Bytes of the onion packet we're forwarding.
new_packet_bytes: Vec<u8>,
},
}

/// Data decrypted from a payment's onion payload.
pub(crate) enum Hop {
/// This onion payload was for us, not for forwarding to a next-hop. Contains information for
/// verifying the incoming payment.
Expand Down Expand Up @@ -603,7 +633,13 @@ pub(crate) enum OnionDecodeErr {
},
}

pub(crate) fn decode_next_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: PaymentHash) -> Result<Hop, OnionDecodeErr> {
pub(crate) fn decode_next_message_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], encrypted_tlvs_ss: SharedSecret) -> Result<MessageHop, 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> {
}

fn decode_next_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], payment_hash: Option<PaymentHash>, encrypted_tlv_ss: Option<SharedSecret>) -> Result<(Payload, Option<([u8; 32], NextPacketBytes)>), OnionDecodeErr> {
let (rho, mu) = gen_rho_mu_from_shared_secret(&shared_secret);
let mut hmac = HmacEngine::<Sha256>::new(&mu);
hmac.input(hop_data);
Expand Down

0 comments on commit d2653d6

Please sign in to comment.