Unwrapping the onion

pull/736/head
Andreas M. Antonopoulos 3 years ago
parent bafcc1c93d
commit b50af33288

@ -52,6 +52,7 @@ Alice wants Bob to accept an HTLC worth 50,200 satoshis to forward to Dina. To d
To add the HTLC, Alice starts the flow we saw in <<HTLC_commitment_message_flow>> by sending the +update_add_htlc+ message to Bob.
[[update_add_htlc]]
==== The +update_add_htlc+ message
Alice sends the `update_add_HTLC` Lightning message to Bob. This message is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc[BOLT #2 - Peer Protocol - update_add_HTLC], and is shown in <<update_add_HTLC_message_fields>> below:

@ -494,3 +494,158 @@ The result can be seen in <<onion_packet_2>> below:
image::images/onion_packet.png[]
=== Sending the onion
In this section we will look at how the onion packet is forwarded and how HTLCs are deployed along the path.
==== The update_add_htlc message
Onion packets are sent as part of the +update_add_htlc+ message. If you recall from <<update_add_htlc>>, in <<channel_operations>>, we saw the contents of the +update_add_htlc+ message were as follows:
----
[channel_id:channel_id]
[u64:id]
[u64:amount_msat]
[sha256:payment_hash]
[u32:cltv_expiry]
[1366*byte:onion_routing_packet]
----
You will recall that this message is sent by one channel partner to ask the other channel partner to add an HTLC. This is how Alice will ask Bob to add an HTLC to pay Dina. Now you understand the purpose of the last field +onion_routing_packet+, which is 1366 bytes long. It's the fully-wrapped onion packet we just constructed!
==== Alice sends the onion to Bob
Alice will send the +update_add_htlc+ message to Bob. Let's look at what this message will contain:
channel_id:: This field will contain the Alice-Bob channel ID, which in our example is +0000031e192ca1+ (see <<alice_dina_path_detail>>).
id:: The ID of this HTLC in this channel, starting at +0+.
amount_msat:: The amount of the HTLC, 50,200,000 milli-satoshis.
payment_hash:: The RIPEMD160(SHA256) payment hash, +9e017f6767971ed7cea17f98528d5f5c0ccb2c71+.
cltv_expiry:: The expiry timelock for the HTLC will be 700,058. Alice adds 20 blocks to the expiry set in Bob's payload according to Bob's negotiated +cltv_expiry_delta+.
onion_routing_packet:: The final onion packet Alice constructed with all the hop payloads!
==== Bob checks the onion
As we saw in <<channel_operations>>, Bob will add the HTLC to the commitment transactions and update the state of the channel with Alice.
Bob will unwrap the onion he received from Alice as follows:
1. Bob takes the session key from the onion packet and derives the Alice-Bob shared secret.
1. Bob generates the +mu+ key from the shared secret and uses it to verify the onion packet HMAC checksum.
Now that Bob has generated the shared key and verified the HMAC, he can start unwrapping the 1300 byte onion payload inside the onion packet. The goal is for Bob to retrieve his own hop payload and then forward the remaining onion to the next hop.
If Bob extracts and removes his hop payload, the remaining onion will not be 1300 bytes, it will be shorter! So the next hop will know that they are not the first hop and will be able to detect how long the path is. To prevent this, Bob needs to add more filler to refill the onion.
==== Bob generates filler
Bob generates filler in a slightly different way than Alice, but following the same general principle.
First, Bob *extends* the onion payload by 1300 bytes and filles them with +0+ values. Now the onion packet is 2600 bytes long, with the first half containing the data Alice sent and the next half containing zeroes. This empty space will become obfuscated and turn into "filler", by the same process that Bob uses to deobfuscate his own hop payload. Let's see how that works.
==== Bob de-obfuscates his hop payload
Next, Bob will generate the +rho+ key from the Alice-Bob shared key. He will use this to generate a 2600 byte stream, using the +ChaCha20+ algorithm.
[TIP]
====
The first 1300 bytes of the byte stream generated by Bob are exactly the same as those generated by Alice using the +rho+ key.
====
Next, Bob applies the 2600 bytes of +rho+ byte stream to the 2600 bytes onion payload with a bitwise XOR operation.
The first 1300 bytes will become de-obfuscated by this XOR operation, because it is the same operation Alice applied and XOR is involutory. So Bob will _reveal_ his hop payload followed by some data that seems scrambled.
At the same time, applying the +rho+ byte stream to the 1300 zeroes that were added to the onion payload will turn them into seemingly random filler data.
==== Bob verifies the hop payload
Now Bob can confirm that his hop payload is correct. It contains an HMAC field. Bob repeats the HMAC verification with the +mu+ key and the hop payload data, finding the same HMAC. Now Bob knows the data is correct, unmodified and sent by Alice, because only the two of them know the shared secret and the +mu+ key derived from it.
==== Bob removes his payload and left shifts the onion
Now Bob can remove his hop payload from the front of the onion and left-shift the remaining data. An amount of data equal to Bob's hop payload from the second-half 1300 bytes of filler will now shift into the onion payload space.
Now Bob can keep the first half 1300 bytes, and discard the extended (filler) 1300 bytes.
Bob now has a 1300 byte onion packet to send to the next hop. It is almost identical to the onion payload that Alice had created for Chan, except that the last 65 or so bytes of filler was put there by Bob and will be different.
No one can tell the difference between filler put there by Alice and filler put there by Bob. Filler is filler! It's all random bytes anyway.
==== Bob constructs the new onion packet
Bob now copies the onion payload into the onion packet
////
TODO
Clarify how the HMAC and session key are computed for this onion packet
////
==== Bob verifies the HTLC details
Bob's hop payload contains the instructions needed to create an HTLC for Chan.
In the hop payload, Bob finds a +short_channel_id+, +amt_to_forward+, and +cltv_expiry+.
First, Bob checks to see if he has a channel with that short ID. He finds that he has such a channel with Chan.
Next, Bob confirms that the outgoing amount (50,100 satoshis) is less than the incoming amount (50,200 satoshis) and therefore Bob's fee expectations are met.
Similarly, Bob checks that the outgoing cltv_expiry is less than the incoming cltv_expiry giving Bob enough time to claim the incoming HTLC if there is a breach.
==== Bob sends the update_add_htlc to Chan
Bob now constructs and HTLC to send to Chan, as follows:
channel_id:: This field will contain the Bob-Chan channel ID, which in our example is +000004040a61f0+ (see <<alice_dina_path_detail>>).
id:: The ID of this HTLC in this channel, starting at +0+.
amount_msat:: The amount of the HTLC, 50,100,000 milli-satoshis.
payment_hash:: The RIPEMD160(SHA256) payment hash, +9e017f6767971ed7cea17f98528d5f5c0ccb2c71+. This is the same as the payment hash from Alice's HTLC.
cltv_expiry:: The expiry timelock for the HTLC will be 700,038.
onion_routing_packet:: The onion packet Bob reconstructed after removing his hop payload.
==== Chan forwards the onion
Chan repeats the exact same process as Bob:
1. Chan receives the +update_add_htlc+ and processes the HTLC request, adding it to commitment transactions.
1. Chan generates the Alice-Chan shared key and the +mu+ subkey
1. Chan verifies the onion packet HMAC, then extracts the 1300 onion payload
1. Chan extends the onion payload by 1300 extra bytes, filling it with zeroes.
1. Chan uses the +rho+ key to produce 2600 bytes.
1. Chan uses the generated byte stream to XOR and de-obfuscate the onion payload. Simultaneously the XOR operation obfuscates the extra 1300 zeroes, turning them into filler
1. Chan verifies his hop payload's HMAC with the +mu+ key
1. Chan removes his hop payload and left-shifts the onion payload by the same amount. Some of the filler generated in the 1300 extended bytes move into the first-half 1300 bytes becoming part of the onion payload.
1. Chan constructs the onion packet for Dina with this onion payload.
1. Chan builds an +update_add_htlc+ message for Dina and inserts the onion packet into it.
1. Chan sends the +update_add_htlc+ to Dina
==== Dina receives the final payload
When Dina receives the +update_add_htlc+ message from Chan, she knows from the +payment_hash+ that this is a payment for her. She knows she is the last hop in the onion.
Dina follows the exact same process as Bob and Chan to verify and unwrap the onion, except she doesn't construct new filler and doesn't forward anything. Instead, Dina responds to Chan with +update_fulfill_htlc+ to redeem the HTLC. The +update_fulfill_htlc+ will flow backwards along the path until it reaches Alice. All the HTLCs are redeemed and channel balances are updated. The payment is complete!
=== Returning errors

Loading…
Cancel
Save