Edited 10_onion_routing.asciidoc with Atlas code editor

pull/910/head
kristen@oreilly.com 3 years ago
parent b9850d6956
commit f8db7d34d0

@ -396,9 +396,9 @@ Note that the very first hop uses the original session key generated because thi
[[wrapping_the_onion]]
=== Wrapping the Onion Layers
((("onion routing","wrapping the onion layers", id="ix_10_onion_routing-asciidoc11", range="startofrange")))The process of wrapping the onion is detailed in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-construction[BOLT #4-Onion Routing-Packet Construction].
((("onion routing","wrapping the onion layers", id="ix_10_onion_routing-asciidoc11", range="startofrange")))The process of wrapping the onion is detailed in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-construction[BOLT #4: Onion Routing, Packet Construction].
In this section we will describe this process at a high and somewhat simplified level-omitting certain details.
In this section we will describe this process at a high and somewhat simplified level, omitting certain details.
[[fixed_length_onions]]
@ -408,7 +408,7 @@ In this section we will describe this process at a high and somewhat simplified
If you have a set of directions, even if encrypted, can't you tell how far you are from the beginning or end simply by looking at _where_ in the list of directions you are?
The trick used in onion routing is to always make the path (the list of directions), the same length for every node. This is achieved by keeping the onion packet the same length at every step.
The trick used in onion routing is to always make the path (the list of directions) the same length for every node. This is achieved by keeping the onion packet the same length at every step.
At each hop, the hop payload appears at the beginning of the onion payload, followed by _what seem to be_ 19 more hop payloads. Every hop sees itself as the first of 20 hops.
@ -419,12 +419,12 @@ The onion payload is 1,300 bytes. Each hop payload is 65 bytes or less (padded t
As each layer is "peeled off," more filler data (essentially junk) is added at the end of the onion payload so the next hop gets an onion of the same size and is once again the "first hop" in the onion.
The onion size is 1,366 bytes structured as shown in <<onion_packet>>.
The onion size is 1,366 bytes, structured as shown in <<onion_packet>>.
* 1 byte: A version byte
* 33 bytes: A compressed public session key (<<session_key>>) from which the per-hop shared secret (<<shared_secret>>) can be generated without revealing Alice's identity
* 1,300 bytes: The actual _onion payload_ containing the instructions for each hop
* 32 bytes: An HMAC integrity checksum
1 byte:: A version byte
33 bytes:: A compressed public session key (<<session_key>>) from which the per-hop shared secret (<<shared_secret>>) can be generated without revealing Alice's identity
1,300 bytes:: The actual _onion payload_ containing the instructions for each hop
32 bytes:: An HMAC integrity checksum
[[onion_packet]]
.The onion packet
@ -436,9 +436,9 @@ In practice, this little trick allows us to keep the onion packet as compact as
==== Wrapping the Onion (Outlined)
((("onion routing","outline of wrapping process")))Here is the process of wrapping the onion, outlined in the following. Come back to this list as we explore each step with our real-world example.
((("onion routing","outline of wrapping process")))Here is the process of wrapping the onion, outlined next. Come back to this list as we explore each step with our real-world example.
For each hop the sender (Alice) repeats the same process:
For each hop, the sender (Alice) repeats the same process:
1. Alice generates the per-hop shared secret and the ++rho++, ++mu++, and ++pad++ keys.
@ -448,11 +448,11 @@ For each hop the sender (Alice) repeats the same process:
4. Alice calculates the length of the hop payload + HMAC + space to store the length itself.
5. Alice _right shifts_ the onion payload by the calculated space needed to fit the hop payload. The rightmost "filler" data is discarded, making enough space on the left for the payload.
5. Alice _right-shifts_ the onion payload by the calculated space needed to fit the hop payload. The rightmost "filler" data is discarded, making enough space on the left for the payload.
6. Alice inserts the length + hop payload + HMAC at the front of the payload field in the space made from shifting the filler.
7. Alice uses the ++rho++ key to generate a 1,300-byte one-time-pad.
7. Alice uses the ++rho++ key to generate a 1,300-byte one-time pad.
8. Alice obfuscates the entire onion payload by XORing with the bytes generated from ++rho++.
@ -478,15 +478,15 @@ The inner HMAC is then revealed during the inverse of the "shift and encrypt" ro
((("onion routing","wrapping hop payloads", id="ix_10_onion_routing-asciidoc12", range="startofrange")))As a reminder, the onion is wrapped by starting at the end of the path from Dina, the final node or recipient. Then the path is built in reverse all the way back to the sender, Alice.
Alice starts with an empty 1,300-byte field, the fixed-length _onion payload_. Then, Alice fills the onion payload with a pseudorandom byte stream "filler," that is generated from the ++pad++ key.
Alice starts with an empty 1,300-byte field, the fixed-length _onion payload_. Then, Alice fills the onion payload with a pseudorandom byte stream "filler" that is generated from the ++pad++ key.
This is shown in <<onion_payload_filler>>.
[NOTE]
====
Random byte stream generation uses the ChaCha20 algorithm, as a cryptographic secure pseudorandom number generator (CSPRNG). Such an algorithm will generate a deterministic, long, nonrepeating stream of seemingly random bytes from an initial seed. The details are specified in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#pseudo-random-byte-stream[BOLT #4-Onion Routing-Pseudo Random Byte Stream].
Random byte stream generation uses the ChaCha20 algorithm, as a cryptographic secure pseudorandom number generator (CSPRNG). Such an algorithm will generate a deterministic, long, nonrepeating stream of seemingly random bytes from an initial seed. The details are specified in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#pseudo-random-byte-stream[BOLT #4: Onion Routing, Pseudo Random Byte Stream].
====
This is shown in <<onion_payload_filler>>.
[[onion_payload_filler]]
.Filling the onion payload with a random byte stream
image::images/mtln_1016.png[]
@ -503,17 +503,17 @@ Next row down we see the result: the 1,300 byte onion payload contains Dina's ho
Next, Alice obfuscates the entire onion payload so that _only Dina_ can read it.
To do this, Alice generates a byte stream using the ++rho++ key (which Dina also knows). Alice uses a bitwise exclusive-or (XOR) between the bits of the onion payload and the byte stream created from ++rho++. The result appears like a random (or encrypted) byte stream of 1,300 bytes length. This step is shown in <<onion_obfuscate_dina>>.
To do this, Alice generates a byte stream using the ++rho++ key (which Dina also knows). Alice uses a bitwise exclusive or (XOR) between the bits of the onion payload and the byte stream created from ++rho++. The result appears like a random (or encrypted) byte stream of 1,300 bytes length. This step is shown in <<onion_obfuscate_dina>>.
[[onion_obfuscate_dina]]
.Obfuscating the onion payload
image::images/mtln_1018.png[]
One of the properties of XOR is that if you do it twice you get back to the original data. As we will see in <<bobDeobfuscates>>, if Dina applies the same XOR operation with the byte stream generated from ++rho++, it will reveal the original onion payload.
One of the properties of XOR is that if you do it twice, you get back to the original data. As we will see in <<bobDeobfuscates>>, if Dina applies the same XOR operation with the byte stream generated from ++rho++, it will reveal the original onion payload.
[TIP]
====
XOR is an _involutory_ function which means that if it is applied twice it undoes itself. Specifically XOR(XOR(_a_, _b_), _b_) = _a_. This property is used extensively in symmetric-key cryptography.
XOR is an _involutory_ function, which means that if it is applied twice, it undoes itself. Specifically XOR(XOR(_a_, _b_), _b_) = _a_. This property is used extensively in symmetric-key cryptography.
====
Because only Alice and Dina have the ++rho++ key (derived from Alice and Dina's shared secret), only they can do this. Effectively, this encrypts the onion payload for Dina's eyes only.
@ -528,9 +528,9 @@ image::images/mtln_1019.png[]
((("onion routing","replay protection/detection")))The HMAC acts as a secure checksum and helps Dina verify the integrity of the hop payload. The 32-byte HMAC is appended to Dina's hop payload.
((("encrypt-then-mac")))Note that we compute the HMAC over the _encrypted_ data rather then over the plain-text data.
This is known as _encrypt-then-mac_ and is the recommended way to use a MAC, as it provides both plain-text _and_ cihpertext integrity.
This is known as _encrypt-then-mac_ and is the recommended way to use a MAC, as it provides both plain-text _and_ ciphertext integrity.
((("AD (associated data)")))((("associated data (AD)")))Modern authenticated encryption also allows for the use of an optional set of plaintext bytes to also be authenticated known as _associated data._
((("AD (associated data)")))((("associated data (AD)")))Modern authenticated encryption also allows for the use of an optional set of plaintext bytes to also be authenticated, known as _associated data._
In practice, this is usually something like a plain-text packet header or other auxiliary information.
By including this associated data in the payload to be authenticated (MAC'ed), the verifier of the MAC ensures that this associated data hasn't been tampered with (e.g., swapping out the plain-text header on an encrypted packet).
@ -545,7 +545,7 @@ Remember that the payment hash of an HTLC can only ever safely be used (for a co
If a payment hash is used again and traverses a node that has already seen the payment secret for that hash, then they can simply pull the funds and collect the entire payment amount without forwarding!
We can use this fact to strengthen the replay protection by requiring that the _payment hash_ is included in our HMAC computation as the associated data.
With this added step, attempting to replay an onion packet also requires the sender to commit to using the _same_ payment hash.
As a result, on top of the normal replay protection, an attacker also stands to lose the entire amount of the HTLC replayed as well.
As a result, on top of the normal replay protection, an attacker also stands to lose the entire amount of the HTLC replayed.
One consideration with the ever-increasing set of session keys stored for replay protection is: are nodes able to reclaim this space?
In the context of the Lightning Network, the answer is: yes!
@ -573,9 +573,9 @@ Alice adds an inner HMAC checksum to Chan's payload and inserts it at the "front
Remember that there are effectively _two_ HMACs used in the scheme: the outer HMAC and the inner HMAC.
In this case, Chan's _inner_ HMAC is actually Dina's _outer_ HMAC.
Now Chan's payload is in the front of the onion. When Chan sees this he has no idea how many payloads came before or after. It looks like the first of 20 hops always!
Now Chan's payload is in the front of the onion. When Chan sees this, he has no idea how many payloads came before or after. It looks like the first of 20 hops always!
Next, Alice obfuscates the entire payload by XOR with the byte stream generated from the Alice-Chan ++rho++ key. Only Alice and Chan have this ++rho++ key and only they can produce the byte stream to obfuscate and deobfuscate the onion.
Next, Alice obfuscates the entire payload by XOR with the byte stream generated from the Alice-Chan ++rho++ key. Only Alice and Chan have this ++rho++ key, and only they can produce the byte stream to obfuscate and de-obfuscate the onion.
Finally, as we did in the earlier step, we compute Chan's outer HMAC, which is what she'll use to verify the integrity of the encrypted onion packet.
==== Wrapping Bob's Hop Payload
@ -605,11 +605,9 @@ Calculate the outer HMAC and stick it on the end of Bob's hop payload.(((range="
Alice calculates an HMAC for the onion payload to cryptographically secure it with a checksum that Bob can verify.
Alice adds a 33-byte public session key that will be used by each hop to generate a shared-secret and the ++rho++, ++mu++, and ++pad++ keys.
Finally Alice puts the onion version number (+0+ currently) in the front.
Alice adds a 33-byte public session key that will be used by each hop to generate a shared secret and the ++rho++, ++mu++, and ++pad++ keys.
This allows for future upgrades of the onion packet format.
Finally Alice puts the onion version number (+0+ currently) in the front. This allows for future upgrades of the onion packet format.
The result can be seen in <<onion_packet_2>>. (((range="endofrange", startref="ix_10_onion_routing-asciidoc11")))
@ -623,7 +621,7 @@ image::images/mtln_1015.png[]
==== The update_add_htlc Message
((("onion routing","update_add_htlc message")))((("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_operation>>, we saw the contents of the +update_add_htlc+ message were as follows:
((("onion routing","update_add_htlc message")))((("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_operation>>, we saw the contents of the +update_add_htlc+ message are as follows:
----
[channel_id:channel_id]
@ -634,23 +632,23 @@ image::images/mtln_1015.png[]
[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 1,366 bytes long. It's the fully wrapped onion packet we just constructed!
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 1,366 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>>).
+channel_id+:: This field contains 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+.
+id+:: The ID of this HTLC in this channel, starting at +0+.
amount_msat:: The amount of the HTLC, 50,200,000 millisatoshis.
+amount_msat+:: The amount of the HTLC: 50,200,000 millisatoshis.
payment_hash:: The RIPEMD160(SHA-256) payment hash, +9e017f6767971ed7cea17f98528d5f5c0ccb2c71+.
+payment_hash+:: The RIPEMD160(SHA-256) 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+.
+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!
+onion_routing_packet+:: The final onion packet Alice constructed with all the hop payloads!
==== Bob Checks the Onion
@ -676,7 +674,7 @@ First, Bob _extends_ the onion payload by 1,300 bytes and fills them with +0+ va
.Bob extends the onion payload by 1,300 (zero-filled) bytes
image::images/mtln_1023.png["Bob extends the onion payload by 1,300 (zero-filled) bytes"]
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.
This empty space will become obfuscated and turn into "filler" by the same process that Bob uses to de-obfuscate his own hop payload. Let's see how that works.
[[bobDeobfuscates]]
==== Bob De-Obfuscates His Hop Payload
@ -690,20 +688,20 @@ The first 1,300 bytes of the byte stream generated by Bob are exactly the same a
Next, Bob applies the 2,600 bytes of the ++rho++ byte stream to the 2,600-byte onion payload with a bitwise XOR operation.
The first 1,300 bytes will become deobfuscated 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.
The first 1,300 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 1,300 zeroes that were added to the onion payload will turn them into seemingly random filler data. This operation is shown in <<bob_deobfuscates>>.
[[bob_deobfuscates]]
.Bob de-obfuscates the onion, obfuscates the filler
image::images/mtln_1024.png["Bob deobfuscates the onion, obfuscates the filler"]
image::images/mtln_1024.png["Bob de-obfuscates the onion, obfuscates the filler"]
==== Bob Extracts the Outer HMAC for the Next Hop
Remember that an inner HMAC is included for each hop, which will then become the outer HMAC for the _next_ hop.
In this case, Bob extracts the inner HMAC (he's already verified the integrity of the encrypted packet with the outer HMAC), and puts it aside because he'll append it to the deobfuscated packet to allow Chan to verify the HMAC of her encrypted packet.
In this case, Bob extracts the inner HMAC (he's already verified the integrity of the encrypted packet with the outer HMAC), and puts it aside because he'll append it to the de-obfuscated packet to allow Chan to verify the HMAC of her encrypted packet.
==== Bob Removes His Payload and Left Shifts the Onion
==== 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 1,300 bytes of filler will now shift into the onion payload space. This is shown in <<bob_removes_shifts>>.
@ -715,13 +713,13 @@ Now Bob can keep the first half 1,300 bytes, and discard the extended (filler) 1
Bob now has a 1,300-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. Note that if Bob (or one of Bob's other aliases) is present in the route in two disctinct locations, then they can tell the difference because the base protocol always uses the same payment hash across the entire route. Atomic multipath payments (AMP) and Point Time-Locked Contrats (PTLCs) eliminate the correlation vector by randomizing the payment identifier across each route/hop.
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. Note that if Bob (or one of Bob's other aliases) is present in the route in two distinct locations, then they can tell the difference because the base protocol always uses the same payment hash across the entire route. Atomic multipath payments (AMPs) and Point Time-Locked Contracts (PTLCs) eliminate the correlation vector by randomizing the payment identifier across each route/hop.
==== Bob Constructs the New Onion Packet
Bob now copies the onion payload into the onion packet, appends the outer HMAC for chan, re-randomizes the session key (the same way Alice the sender does) with the elliptic curve multiplication operation, and appends a fresh version byte.
To re-randomize the session key, bob first computes the blinding factor for his hop, using his node public key and the shared secret he derived:
To re-randomize the session key, Bob first computes the blinding factor for his hop, using his node public key and the shared secret he derived:
```
b_bob = SHA-256(P_bob || shared_secret_bob)
```
@ -741,25 +739,25 @@ In the hop payload, Bob finds a +short_channel_id+, +amt_to_forward+, and +cltv_
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.
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.
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>>).
+channel_id+:: This field contains 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+.
+id+:: The ID of this HTLC in this channel, starting at +0+.
amount_msat:: The amount of the HTLC, 50,100,000 millisatoshis.
+amount_msat+:: The amount of the HTLC: 50,100,000 millisatoshis.
payment_hash:: The RIPEMD160(SHA-256) payment hash, +9e017f6767971ed7cea17f98528d5f5c0ccb2c71+. This is the same as the payment hash from Alice's HTLC.
+payment_hash+:: The RIPEMD160(SHA-256) 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.
+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.
+onion_routing_packet+:: The onion packet Bob reconstructed after removing his hop payload.
==== Chan Forwards the Onion
@ -767,7 +765,7 @@ 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.
2. Chan generates the Alice-Chan shared key and the ++mu++ subkey
2. Chan generates the Alice-Chan shared key and the ++mu++ subkey.
3. Chan verifies the onion packet HMAC, then extracts the 1,300-byte onion payload
@ -775,7 +773,7 @@ Chan repeats the exact same process as Bob:
5. Chan uses the ++rho++ key to produce 2,600 bytes.
6. Chan uses the generated byte stream to XOR and deobfuscate the onion payload. Simultaneously the XOR operation obfuscates the extra 1,300 zeroes, turning them into filler.
6. Chan uses the generated byte stream to XOR and de-obfuscate the onion payload. Simultaneously, the XOR operation obfuscates the extra 1,300 zeroes, turning them into filler.
7. Chan extracts the inner HMAC in the payload, which will become the outer HMAC for Dina.
@ -785,7 +783,7 @@ Chan repeats the exact same process as Bob:
10. Chan builds an +update_add_htlc+ message for Dina and inserts the onion packet into it.
11. Chan sends the +update_add_htlc+ to Dina
11. Chan sends the +update_add_htlc+ to Dina.
12. Chan re-randomizes the session key as Bob did in the prior hop for Dina.
@ -805,12 +803,12 @@ Errors generally fall into three categories: onion failures, node failures, and
[NOTE]
====
Unlike messages in the Peer-to-Peer (P2P) protocol (defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md[BOLT #2: Peer Protocol for Channel Management]), errors are not sent as P2P messages but wrapped inside onion return packets and following the reverse of the onion path (back-propagating).
Unlike messages in the peer-to-peer (P2P) protocol (defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md[BOLT #2: Peer Protocol for Channel Management]), errors are not sent as P2P messages but are wrapped inside onion return packets and follow the reverse of the onion path (back-propagating).
====
Error return is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#returning-errors[BOLT #4-Onion Routing-Returning Errors].
Error return is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#returning-errors[BOLT #4: Onion Routing, Returning Errors].
Errors are encoded by the returning node (the one that discovered an error) encoded in a _return packet_ as follows:
Errors are encoded by the returning node (the one that discovered an error) in a _return packet_ as follows:
----
[32*byte:hmac]
@ -833,22 +831,22 @@ Finally the return node sends the return packet to the hop from which it receive
Each hop receiving an error will generate an +ammag+ key and obfuscate the return packet again using an XOR operation with the byte stream from +ammag+.
Eventually, the sender (origin node) receives a return packet. It will then generate +ammag+ and ++um++ keys for each hop and XOR deobfuscate the return error iteratively until it reveals the return packet.
Eventually, the sender (origin node) receives a return packet. It will then generate +ammag+ and ++um++ keys for each hop and XOR de-obfuscate the return error iteratively until it reveals the return packet.
[[failure_messages]]
==== Failure Messages
((("error return","failure messages", id="ix_10_onion_routing-asciidoc16", range="startofrange")))((("failure messages, onion routing and", id="ix_10_onion_routing-asciidoc17", range="startofrange")))The +failuremsg+ is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#failure-messages[BOLT #4-Onion Routing-Failure Messages].
((("error return","failure messages", id="ix_10_onion_routing-asciidoc16", range="startofrange")))((("failure messages, onion routing and", id="ix_10_onion_routing-asciidoc17", range="startofrange")))The +failuremsg+ is defined in https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#failure-messages[BOLT #4: Onion Routing, Failure Messages].
A failure message consists of a 2-byte +failure code+ followed by the data applicable to that failure type.
A failure message consists of a two-byte +failure code+ followed by the data applicable to that failure type.
The top byte of the +failure_code+ is a set of binary flags that can be combined (with binary OR):
0x8000 (BADONION):: Unparsable onion encrypted by sending peer
0x4000 (PERM):: Permanent failure (otherwise transient)
0x2000 (NODE):: Node failure (otherwise channel)
0x1000 (UPDATE):: New channel update enclosed
0x8000 (`BADONION`):: Unparsable onion encrypted by sending peer
0x4000 (`PERM`):: Permanent failure (otherwise transient)
0x2000 (`NODE`):: Node failure (otherwise channel)
0x1000 (`UPDATE`):: New channel update enclosed
The failure types shown in <<failure_types_table>> are currently defined.
@ -858,11 +856,11 @@ include::failure_types_table.asciidoc[]
[[stuck_payments]]
===== Stuck payments
((("onion routing","stuck payments")))((("stuck payments")))In the current implementation of the Lightning Network there is a possibility that a payment attempt becomes _stuck_, neither fulfilled nor cancelled by an error. This can happen due to a bug on an intermediary node, a node going offline while handling HTLCs, or a malicious node holding HTLCs without reporting an error. In all of these cases, the HTLC cannot be resolved until it expires. The timelock (CLTV) that is set on every HTLC helps resolve this condition (among other possible HTLC routing and channel failures).
((("onion routing","stuck payments")))((("stuck payments")))In the current implementation of the Lightning Network, there is a possibility that a payment attempt becomes _stuck_: neither fulfilled nor cancelled by an error. This can happen due to a bug on an intermediary node, a node going offline while handling HTLCs, or a malicious node holding HTLCs without reporting an error. In all of these cases, the HTLC cannot be resolved until it expires. The timelock (CLTV) that is set on every HTLC helps resolve this condition (among other possible HTLC routing and channel failures).
However, this means that the sender of the HTLC has to wait until expiry, and the funds committed to that HTLC remain unavailable until the HTLC expires. Furthermore, the sender _cannot retry_ that same payment, because if they do they run the risk of _both_ the original and the retried payment succeeding-the recipient gets paid twice. This is because once sent an HTLC cannot be "cancelled" by the sender-it either has to fail or expire. Stuck payments, while rare, create an unwanted user experience, where the user's wallet cannot pay or cancel a payment.
However, this means that the sender of the HTLC has to wait until expiry, and the funds committed to that HTLC remain unavailable until the HTLC expires. Furthermore, the sender _cannot retry_ that same payment, because if they do, they run the risk of _both_ the original and the retried payment succeeding—the recipient gets paid twice. This is because, once sent, an HTLC cannot be "cancelled" by the sender—it either has to fail or expire. Stuck payments, while rare, create an unwanted user experience, where the user's wallet cannot pay or cancel a payment.
((("Point Time-Locked Contract (PTLC)")))((("PTLC (Point Time-Locked Contract)")))((("stuckless payments")))One proposed solution to this problem is called _stuckless payments_, and it depends on Point Time-Locked Contracts (PTLCs), which are payment contract that use a different cryptographic primitive than HTLCs (i.e., point addition on the elliptic curve instead of a hash and secret preimage). PTLCs are cumbersome using ECDSA but much easier with Bitcoin's Taproot and Schnorr signature features, which were recently locked in for activation in November 2021. It is expected that PTLCs will be implemented in the Lightning Network after these Bitcoin features become activated(((range="endofrange", startref="ix_10_onion_routing-asciidoc17")))(((range="endofrange", startref="ix_10_onion_routing-asciidoc16"))).(((range="endofrange", startref="ix_10_onion_routing-asciidoc15")))(((range="endofrange", startref="ix_10_onion_routing-asciidoc14")))
((("Point Time-Locked Contract (PTLC)")))((("PTLC (Point Time-Locked Contract)")))((("stuckless payments")))One proposed solution to this problem is called _stuckless payments_, and it depends on Point Time-Locked Contracts (PTLCs), which are payment contracts that use a different cryptographic primitive than HTLCs (i.e., point addition on the elliptic curve instead of a hash and secret preimage). PTLCs are cumbersome using ECDSA but much easier with Bitcoin's Taproot and Schnorr signature features, which were recently locked in for activation in November 2021. It is expected that PTLCs will be implemented in the Lightning Network after these Bitcoin features become activated(((range="endofrange", startref="ix_10_onion_routing-asciidoc17")))(((range="endofrange", startref="ix_10_onion_routing-asciidoc16"))).(((range="endofrange", startref="ix_10_onion_routing-asciidoc15")))(((range="endofrange", startref="ix_10_onion_routing-asciidoc14")))
[[keysend]]
=== Keysend Spontaneous Payments
@ -871,7 +869,7 @@ However, this means that the sender of the HTLC has to wait until expiry, and th
received an invoice from Alice "out of band," or obtained it via some mechanism
unrelated to the protocol (typically copy/paste or QR code scans). This trait
means that the payment process always takes two steps: first, the sender
obtains an invoice and second, uses the payment hash (encoded in the invoice) to
obtains an invoice, and second, uses the payment hash (encoded in the invoice) to
successfully route an HTLC. The extra round trip required to obtain an invoice
before making a payment may be a bottleneck in applications that involve
streaming micropayments over Lightning. What if we could just "push" a payment
@ -888,7 +886,7 @@ forward the payment. Leveraging the TLV format, each piece of routing informatio
(like the next node to which to pass the HTLC) is assigned a specific type (or key)
encoded as a `BigSize` variable length integer (max sized as as 64-bit
integer). These "essential" (reversed values below `65536`) types are defined
in BOLT-04 along with the rest of the onion routing details. Onion types with a
in BOLT #4, along with the rest of the onion routing details. Onion types with a
value greater than `65536` are intended to be used by wallets and applications
as "custom records."
@ -896,10 +894,10 @@ Custom records allow payment applications to attach additional metadata or
context to a payment as key/value pairs in the onion. Since the custom records
are included in the onion payload itself, like all other hop contents, the
records are end-to-end encrypted. As the custom records effectively consume a
portion of the fixed-size `1300` bytes onion packet, encoding each key and
portion of the fixed-size 1300-bytes onion packet, encoding each key and
value of each custom record reduces the amount of available space for encoding
the rest of the route. In practice, this means that the more onion space used for custom records, the shorter the route can be. Given that each HTLC
packet is fixed-size, custom records don't _add_ any additional data to an
packet is fixed size, custom records don't _add_ any additional data to an
HTLC; rather, they reallocate bytes that would have been filled with random data
otherwise.
@ -907,7 +905,7 @@ otherwise.
((("onion routing","sending/receiving keysend payments")))A `keysend` payment inverts the typical flow of an HTLC where the receiver
reveals a secret preimage to the sender. Instead, the sender includes the
preimage _within_ the onion to the receiver and routes the HTLC to the
preimage _within_ the onion to the receiver, and routes the HTLC to the
receiver. The receiver then decrypts the onion payload, and uses the included
preimage (which _must_ match the payment hash of the HTLC) to settle the
payment. As a result, `keysend` payments can be carried out without first

Loading…
Cancel
Save