1
0
Fork 0
mirror of https://github.com/lightning/bolts.git synced 2025-03-10 17:18:44 +01:00

BOLT 4: complete second-pass copy edit, introduced new terminology 'erring node', require a few clarifications

This commit is contained in:
Landon Mutch 2017-12-03 15:49:08 -08:00 committed by Rusty Russell
parent 051f98a75e
commit 54b49c09db

View file

@ -255,7 +255,7 @@ In the following example, it's assumed that a _sending node_ (origin node),
`n_0`, wants to route a packet to a _receiving node_ (final node), `n_r`. `n_0`, wants to route a packet to a _receiving node_ (final node), `n_r`.
First, the sender computes a route `{n_0, n_1, ..., n_{r-1}, n_r}`, where `n_0` First, the sender computes a route `{n_0, n_1, ..., n_{r-1}, n_r}`, where `n_0`
is the sender itself and `n_r` is the final recipient. The nodes `n_i` and is the sender itself and `n_r` is the final recipient. The nodes `n_i` and
`n_{i+1}` MUST be peers in the overlay network. The sender then gathers the `n_{i+1}` MUST be peers in the overlay network route. The sender then gathers the
public keys for `n_1` to `n_r` and generates a random 32-byte `sessionkey`. public keys for `n_1` to `n_r` and generates a random 32-byte `sessionkey`.
Optionally, the sender may pass in _associated data_, i.e. data that the Optionally, the sender may pass in _associated data_, i.e. data that the
packet commits to but that is not included in the packet itself. Associated packet commits to but that is not included in the packet itself. Associated
@ -269,32 +269,35 @@ The hop receiving the header will perform ECDH with the ephemeral public key
and its own private key in order to derive the same shared secret. and its own private key in order to derive the same shared secret.
However, when generating the packet, the sending node doesn't have access to the However, when generating the packet, the sending node doesn't have access to the
other nodes' private keys. So instead, it uses the commutative property of other nodes' private keys. So instead, it uses the commutative property of
multiplication to blind each node's public key with all previous blinding multiplication to blind each hop's public key with all previous blinding
factors and performs ECDH using each node's blinded public key and the `sessionkey`. factors and performs ECDH, using each hop's blinded public key and the
`sessionkey`.
The transformations at hop `k` are given by the following: The transformations at hop `k` are as follows:
- The shared secret `ss_k` is computed by first blinding the node's public key - The shared secret `ss_k` is computed by first blinding the hop's public key
`nodepk_k` with all previous blinding factors `{b_1, ..., b_{k-1}}` (if any), `nodepk_k` with all previous blinding factors `{b_1, ..., b_{k-1}}` (if any),
and second executing ECDH with the blinded public key and the `sessionkey`. and second, executing ECDH with the blinded public key and the `sessionkey`.
- The blinding factor is the `SHA256` hash of the concatenation between the - The blinding factor is the `SHA256` hash of the concatenation between the
node's public key `nodepk_k` and the hop's shared secret `ss_k`. Before hop's public key `nodepk_k` and its shared secret `ss_k`. Before
concatenation, the node's public key is serialized in the compressed format. concatenation, the hop's public key is serialized in the compressed format.
- The ephemeral public key `epk_k` is computed by blinding the previous hop's - The ephemeral public key `epk_k` is computed by blinding the hop's sending
ephemeral public key `epk_{k-1}` with the previous hop's blinding factor `b_{k-1}`. peer's ephemeral public key `epk_{k-1}` with the hop's sending peer's blinding
factor `b_{k-1}`.
This recursive algorithm is initialized by setting the first hop's (`k=1`) This recursive algorithm is initialized by setting the first hop's (`k=1`)
ephemeral public key to the public key corresponding to the `sessionkey`, i.e. ephemeral public key to the public key corresponding to the `sessionkey`, i.e.
`secp256k1` is used to derive a public key for the randomly selected `sessionkey`. `secp256k1` is used to derive a public key for the randomly selected
`sessionkey`.
The sender then iteratively computes the ephemeral public keys, shared secrets, The origin node then iteratively computes the ephemeral public keys, shared
and blinding factors for nodes `{n_2, ..., n_r}`. secrets, and blinding factors for hops `{n_2, ..., n_r}`.
Once the sender has all the required information above, it can construct the packet. Once the sender has all the required information above, it can construct the
Constructing a packet routed over `r` hops requires `r` 32-byte ephemeral packet. Constructing a packet routed over `r` hops requires `r` 32-byte
public keys, `r` 32-byte shared secrets, `r` 32-byte blinding factors, and `r` ephemeral public keys, `r` 32-byte shared secrets, `r` 32-byte blinding factors,
65-byte `per_hop` payloads. and `r` 65-byte `per_hop` payloads. The construction returns a single 1366-byte
The construction returns a single 1366-byte packet along with the first hop's address. packet along with the first receiving peer's address.
The packet construction is performed in the reverse order of the route, i.e. The packet construction is performed in the reverse order of the route, i.e.
the last hop's operations are applied first. the last hop's operations are applied first.
@ -313,19 +316,20 @@ following operations:
- The `version`, `short_channel_id`, `amt_to_forward`, `outgoing_cltv_value`, - The `version`, `short_channel_id`, `amt_to_forward`, `outgoing_cltv_value`,
`padding`, and `HMAC` are copied into the following 65 bytes. `padding`, and `HMAC` are copied into the following 65 bytes.
- The _rho_-key is used to generate 1300 bytes of pseudo-random byte stream - The _rho_-key is used to generate 1300 bytes of pseudo-random byte stream
and applied, with `XOR`, to the `hops_data` field. which is then applied, with `XOR`, to the `hops_data` field.
- If this is the last hop, i.e. the first iteration, then the tail of the - If this is the last hop, i.e. the first iteration, then the tail of the
`hops_data` field is overwritten with the routing information `filler`. `hops_data` field is overwritten with the routing information `filler`.
- The next HMAC is computed (with the _mu_-key as HMAC-key) over the - The next HMAC is computed (with the _mu_-key as HMAC-key) over the
concatenated `hops_data` and associated data. concatenated `hops_data` and associated data.
[FIXME: Please reword, meaning is unclear] The final value for the HMAC is the HMAC as it should be sent to the first hop. The resulting final HMAC value is the HMAC that will be used by the first
receiving peer in the route.
The packet generation returns a serialized packet that contains the `version` The packet generation returns a serialized packet that contains the `version`
byte, the ephemeral pubkey for the first hop, the HMAC for the first hop, and byte, the ephemeral pubkey for the first hop, the HMAC for the first hop, and
the obfuscated `hops_data`. the obfuscated `hops_data`.
The following code implements the packet construction in Go: The following Go code is an example implementation of the packet construction:
```Go ```Go
func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey, func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey,
@ -395,12 +399,12 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
# Packet Forwarding # Packet Forwarding
This specification is limited to `version` `0` packets; however, the structure of This specification is limited to `version` `0` packets; however, the structure
future versions may change. of future versions may change.
Upon receiving a packet, a processing node compares the version byte of the Upon receiving a packet, a processing node compares the version byte of the
packet with its supported versions and aborts the connection if the packet packet with its own supported versions and aborts the connection if the packet
specifies a version number it doesn't support. specifies a version number that it doesn't support.
For packets with supported version numbers, the processing node then parses the For packets with supported version numbers, the processing node first parses the
packet into its individual fields. packet into its individual fields.
The processing node: The processing node:
@ -408,37 +412,38 @@ The processing node:
- MUST abort processing the packet. - MUST abort processing the packet.
- MUST report a route failure to the origin node. - MUST report a route failure to the origin node.
The processing node then computes the shared secret, as described below, using the private Next, the processing node computes the shared secret using the private key
key corresponding to its public key and the ephemeral key from the packet. corresponding to its own public key and the ephemeral key from the packet, as
described in [Shared Secret](#shared-secret).
The processing node: The processing node:
- if the packet has previously been forwarded or locally redeemed, i.e. packet - if the packet has previously been forwarded or locally redeemed, i.e. the
contains duplicated routing information: packet contains duplicate routing information to a previously received packet:
- if preimage is known: - if preimage is known:
- MAY immediately redeem the HTLC using the preimage. - MAY immediately redeem the HTLC using the preimage.
- otherwise: - otherwise:
- MUST abort processing and report a route failure. - MUST abort processing and report a route failure.
The above requirements prevent any hop along the route from retrying a payment The above requirements prevent any hop along the route from retrying a payment
multiple times and attempting to track a payment's progress via traffic multiple times, in an attempt to track a payment's progress via traffic
analysis. Note that this could be accomplished using a log of previous shared analysis. Note that such traffic analysis could be accomplished using a log of
secrets or HMACs, which could be forgotten once the HTLC would not be accepted previous shared secrets or HMACs, which could be forgotten once the HTLC would
anyway (i.e. after `outgoing_cltv_value` has passed). Such a log may use a not be accepted anyway (i.e. after `outgoing_cltv_value` has passed). Such a log
probabilistic data structure, but it MUST rate-limit commitments, as necessary, may use a probabilistic data structure, but it MUST rate-limit commitments as
in order to constrain the worst-case storage requirements or false positives of necessary, in order to constrain the worst-case storage requirements or false
this log. positives of this log.
The shared secret is used to compute a _mu_-key. The processing node then Next, the processing node uses the shared secret to compute a _mu_-key, which it
computes the HMAC of the `hops_data` using the _mu_-key. The resulting HMAC is in turn uses to compute the HMAC of the `hops_data`. The resulting HMAC is then
compared with the HMAC from the packet. compared against the packet's HMAC.
The processing node: The processing node:
- if the computed HMAC and the HMAC from the packet differ: - if the computed HMAC and the packet's HMAC differ:
- MUST abort processing. - MUST abort processing.
- MUST report a route failure. - MUST report a route failure.
Comparison of the computed HMAC and the HMAC from the packet MUST be Comparison of the computed HMAC and the packet's HMAC MUST be
time-constant to avoid leaking information. time-constant to avoid information leaks.
At this point, the processing node can generate a _rho_-key and a _gamma_-key. At this point, the processing node can generate a _rho_-key and a _gamma_-key.
@ -471,24 +476,25 @@ The processing node:
- MUST drop the packet. - MUST drop the packet.
- MUST signal a route failure. - MUST signal a route failure.
[FIXME: separate processing node requirements into `Requirements` section, or is more it important to integrate them into the sequence of events?]
# Shared Secret # Shared Secret
The origin node performs ECDH with each hop of the route, in order to establish a secret. The origin node performs ECDH with each hop of the route, in order to establish a secret.
A new _sessionkey_, a 32-byte EC private key, is generated for each message. A new _sessionkey_, a 32-byte EC private key, is generated for each message.
The shared secret builder function takes a public key and a 32-byte secret The shared secret builder function takes a public key and a 32-byte secret
as input and returns a 32-byte secret as output. ,as inputs, and returns a 32-byte secret, as output.
During the packet generation phase, the secret is the `sessionkey`, and the During the packet generation phase, the secret is the `sessionkey`, and the
public key is the processing node's public key, which is public key is the hop's public key, which is blinded by all previous blinding
blinded by all previous blinding factors. factors.
During the processing phase, the secret is the processing node's private key, During the processing phase, the secret is the hop's (processing node's) private
while the public key is the ephemeral public key from the packet, which has been key, while the public key is the ephemeral public key from the packet, which has
incrementally blinded by its predecessors. been incrementally blinded by its predecessors.
The public key is multiplied by the secret, using the `secp256k1` curve. The public key is multiplied by the secret, using the `secp256k1` curve.
The DER compressed representation of the multiplication result is serialized and The DER compressed representation of the multiplication result is serialized and
hashed using `SHA256`. hashed using `SHA256`, and the resulting hash is returned as the shared secret.
The resulting hash is returned as the shared secret.
Notice that this is the ECDH variant implemented in `libsecp256k1`. Notice that this is the ECDH variant implemented in `libsecp256k1`.
# Filler Generation # Filler Generation
@ -496,12 +502,12 @@ Notice that this is the ECDH variant implemented in `libsecp256k1`.
Upon receiving a packet, the processing node extracts the information destined Upon receiving a packet, the processing node extracts the information destined
for it from the route information and the per-hop payload. for it from the route information and the per-hop payload.
The extraction is done by deobfuscating and left-shifting the field. The extraction is done by deobfuscating and left-shifting the field.
This would make the field shorter at each hop, allowing an attacker to deduce the route length. This would make the field shorter at each hop, allowing an attacker to deduce the
For this reason, the field is padded before forwarding. route length. For this reason, the field is pre-padded before forwarding.
Since the padding is part of the HMAC, the origin node will have to generate an Since the padding is part of the HMAC, the origin node will have to generate an
identical padding in order to compute the HMACs correctly for each hop. identical [FIXME: identical to what?] padding in order to compute the HMACs correctly for each hop.
The filler is also used to pad the field-length, in the case that the selected The filler is also used to pad the field-length, in the case that the selected
route is shorter than the maximum allowed route length. route is shorter than the maximum allowed route length of 20.
Before deobfuscating the `hops_data`, the processing node pads it with 65 Before deobfuscating the `hops_data`, the processing node pads it with 65
`0x00`-bytes, such that the total length is `(20 + 1) * 65`. `0x00`-bytes, such that the total length is `(20 + 1) * 65`.
@ -510,11 +516,12 @@ it with `XOR` to the `hops_data`.
This deobfuscates the information destined for it, while simultaneously This deobfuscates the information destined for it, while simultaneously
obfuscating the added `0x00`-bytes at the end. obfuscating the added `0x00`-bytes at the end.
In order to compute the correct HMAC, the origin node has to generate the `hops_data` In order to compute the correct HMAC, the origin node has to pre-generate the
for each hop, which includes the incrementally obfuscated padding added by each hop. `hops_data` for each hop, including the incrementally obfuscated padding added
The incrementally obfuscated padding is called the `filler`. by each hop. This incrementally obfuscated padding is referred to as the
`filler`.
The following code shows how the filler is generated in Go: The following example code shows how the filler is generated in Go:
```Go ```Go
func generateFiller(key string, numHops int, hopSize int, sharedSecrets [][sharedSecretSize]byte) []byte { func generateFiller(key string, numHops int, hopSize int, sharedSecrets [][sharedSecretSize]byte) []byte {
@ -544,30 +551,31 @@ func generateFiller(key string, numHops int, hopSize int, sharedSecrets [][share
} }
``` ```
Notice that this implementation is for demonstration purposes only; the filler Notice that this example implementation is for demonstration purposes only; the
can be generated much more efficiently. `filler` can be generated much more efficiently.
The last hop does not obfuscate the filler, since it will not forward the packet The last hop need not obfuscate the `filler`, since it won't forward the packet
and will not extract an HMAC for any further hops. any further and thus need not extract an HMAC either.
# Blinding EC Points # Blinding EC Points
In order to vary the ephemeral public key (the EC point) between hops, it is In order to vary the ephemeral public key (the EC point) between hops, it's
blinded at each hop. blinded at each hop.
The inputs for the blinding process are the EC point to be blinded, the hop's The inputs for the blinding process are the EC point to be blinded, the hop's
public key, and a 32-byte shared secret. The output is a single EC point, public key, and a 32-byte shared secret. The output is a single EC point, which
representing the blinded element. represents the blinded element.
Blinding is accomplished by computing a blinding factor from the hop's public Blinding is accomplished by computing a blinding factor from the hop's public
key and the shared secret for that hop. key and the shared secret for that hop.
The blinding factor is the result of serializing the hop's public key into its The blinding factor is the computed `SHA256` hash value of the result of
compressed format, appending the shared secret, and computing the `SHA256` hash. serializing the hop's public key into its compressed format and appending the
The blinded EC point then is the result of the scalar multiplication between the shared secret.
The blinded EC point, in turn, is the result of the scalar multiplication of the
EC point and the blinding factor. EC point and the blinding factor.
# Returning Errors # Returning Errors
The protocol includes a simple mechanism for returning encrypted error messages The onion routing protocol includes a simple mechanism for returning encrypted
to the origin node. error messages to the origin node.
The returned error messages may be failures reported by any hop, including the The returned error messages may be failures reported by any hop, including the
final node. final node.
The format of the forward packet is not usable for the return path, since no hop The format of the forward packet is not usable for the return path, since no hop
@ -576,11 +584,11 @@ Note that these error messages are not reliable, as they are not placed on-chain
due to the possibility of hop failure. due to the possibility of hop failure.
Intermediate hops store the shared secret from the forward path and reuse it to Intermediate hops store the shared secret from the forward path and reuse it to
obfuscate the error packet on each hop. obfuscate any corresponding return packet during each hop.
In addition, each node locally stores data regarding its sending peer in the In addition, each node locally stores data regarding its own sending peer in the
route, so it knows where to back-send an eventual return packet. route, so it knows where to return-forward any eventual return packets.
The node returning the message builds a return packet consisting of the The node generating the error message (_erring node_) builds a return packet
following fields: consisting of the following fields:
1. data: 1. data:
* [`32`:`hmac`] * [`32`:`hmac`]
@ -593,56 +601,59 @@ Where `hmac` is an HMAC authenticating the remainder of the packet, with a key
generated using the above process, with key type `um`, `failuremsg` as defined generated using the above process, with key type `um`, `failuremsg` as defined
below, and `pad` as the extra bytes used to conceal length. below, and `pad` as the extra bytes used to conceal length.
The node: The erring node:
- SHOULD set `pad` such that the `failure_len` plus `pad_len` is equal to 256. - SHOULD set `pad` such that the `failure_len` plus `pad_len` is equal to 256.
- Note: this value is 118 bytes longer than the longest currently-defined - Note: this value is 118 bytes longer than the longest currently-defined
message. message.
The node then generates a new key, using the key type `ammag`. The erring node then generates a new key, using the key type `ammag`.
This key is then used to generate a pseudo-random stream, which is then applied This key is then used to generate a pseudo-random stream, which is in turn
to the packet using `XOR`. applied to the packet using `XOR`.
The obfuscation step is repeated by every hop on the return path. The obfuscation step is repeated by every hop along the return path.
Upon receiving a packet, the hop will generate its `ammag`, generate the Upon receiving a return packet, each hop generates its `ammag`, generates the
pseudo-random byte stream, and apply it to the packet before forwarding. pseudo-random byte stream, and applies the result to the return packet before
return-forwarding it.
The origin node detects that it is the last hop of the return message, since it The origin node is able to detect that it's the intended final recipient of the
was the origin of the corresponding forward packet. return message, because of course, it was the originator of the corresponding
forward packet.
When an origin node receives an error message matching a transfer it initiated When an origin node receives an error message matching a transfer it initiated
(i.e. it cannot forward the error any further) it then generates the (i.e. it cannot return-forward the error any further) it generates the `ammag`
`ammag` and `um` keys for each hop in the route. and `um` keys for each hop in the route.
The origin node then iteratively decrypts the error message using each of the `ammag` It then iteratively decrypts the error message, using each hop's `ammag`
keys and computes the HMAC using the `um` keys. key, and computes the HMAC, using each hop's `um` key.
The origin node can detect the sender of the error message by matching the The origin node can detect the sender of the error message by matching the
`hmac` field with the computed HMAC. `hmac` field with the computed HMAC.
The origin node: The origin node:
- once the original message has been decrypted: - once the return message has been decrypted:
- SHOULD store a copy of the message. - SHOULD store a copy of the message.
- SHOULD continue decrypting, until the loop has been repeated 20 times. - SHOULD continue decrypting, until the loop has been repeated 20 times.
- SHOULD use constant `ammag` and `um` keys to obfuscate the route length. - SHOULD use constant `ammag` and `um` keys to de-obfuscate the route length.
The association between the forward and return packets is handled outside of The association between the forward and return packets is handled outside of
this protocol, e.g. via association with an HTLC in a payment channel. this onion routing protocol, e.g. via association with an HTLC in a payment
channel.
## Failure Messages ## Failure Messages
The failure message encapsulated in `failuremsg` has an identical format as The failure message encapsulated in `failuremsg` has an identical format as
a normal message: a 2-byte type `failure_code` followed by data applicable a normal message: a 2-byte type `failure_code` followed by data applicable
to that type. Following is a list of `failure_code` values currently supported to that type. Following is a list of the currently supported `failure_code`
along with their intended use cases. values and their associated use cases.
Notice that the `failure_code`s are not of the same type as other message types Notice that the `failure_code`s are not of the same type as other message types,
(defined in other BOLTs), as they are not sent directly on the transport layer defined in other BOLTs, as they are not sent directly on the transport layer
but are instead wrapped inside return packets. but are instead wrapped inside return packets.
The numeric values for the `failure_code` may therefore reuse values that are The numeric values for the `failure_code` may therefore reuse values, that are
also assigned as message types, without any danger of causing collisions. also assigned to other message types, without any danger of causing collisions.
A node: An erring node:
- MUST select one of these codes when creating an error message. - MUST select one of these codes when creating an error message.
- MUST include the appropriate data for that particular error type. - MUST include the appropriate data for that particular error type.
- if there is more than one error: - if there is more than one error:
- SHOULD select the first error listed below. - SHOULD select the first error it encounters from the list below.
The top byte of `failure_code` can be read as a set of flags: The top byte of `failure_code` can be read as a set of flags:
* 0x8000 (BADONION): unparsable onion encrypted by sending peer * 0x8000 (BADONION): unparsable onion encrypted by sending peer
@ -650,18 +661,18 @@ The top byte of `failure_code` can be read as a set of flags:
* 0x2000 (NODE): node failure (otherwise channel) * 0x2000 (NODE): node failure (otherwise channel)
* 0x1000 (UPDATE): new channel update enclosed * 0x1000 (UPDATE): new channel update enclosed
Any node MAY return one of the following errors: Any erring node MAY return one of the following errors:
- if the `realm` byte is unknown: - if the `realm` byte is unknown:
1. type: PERM|1 (`invalid_realm`) 1. type: PERM|1 (`invalid_realm`)
- if an otherwise unspecified transient error occurs for the entire node: - if an otherwise unspecified transient error occurs for the entire node:
1. type: NODE|2 (`temporary_node_failure`) 1. type: NODE|2 (`temporary_node_failure`)
- if an otherwise unspecified permanent error occurs for the entire node: - if an otherwise unspecified permanent error occurs for the entire node:
1. type: PERM|NODE|2 (`permanent_node_failure`) 1. type: PERM|NODE|2 (`permanent_node_failure`)
- if a node has requirement advertised in its `node_announcement` `features` - if a node has requirements advertised in its `node_announcement` `features`
which were not present in the onion: which were NOT included in the onion:
1. type: PERM|NODE|3 (`required_node_feature_missing`) 1. type: PERM|NODE|3 (`required_node_feature_missing`)
A _forwarding node_ MAY, but the _final node_ MUST NOT, return one of the following A _return-forwarding node_ MAY, but a _final node_ MUST NOT, return one of the following
errors: errors:
- if the onion `version` byte is unknown: - if the onion `version` byte is unknown:
1. type: BADONION|PERM|4 (`invalid_onion_version`) 1. type: BADONION|PERM|4 (`invalid_onion_version`)
@ -675,36 +686,36 @@ errors:
1. type: BADONION|PERM|6 (`invalid_onion_key`) 1. type: BADONION|PERM|6 (`invalid_onion_key`)
2. data: 2. data:
* [`32`:`sha256_of_onion`] * [`32`:`sha256_of_onion`]
- if an otherwise unspecified transient error occurs for the outgoing - if an otherwise unspecified, transient error occurs for the outgoing
channel (e.g. channel capacity reached, too many in-flight HTLCs): channel [FIXME: what is exact definition of 'outgoing' channel?] (e.g. channel capacity reached, too many in-flight HTLCs, etc.):
1. type: UPDATE|7 (`temporary_channel_failure`) 1. type: UPDATE|7 (`temporary_channel_failure`)
2. data: 2. data:
* [`2`:`len`] * [`2`:`len`]
* [`len`:`channel_update`] * [`len`:`channel_update`]
- if an otherwise unspecified, permanent error occurs for the outgoing channel - if an otherwise unspecified, permanent error occurs for the outgoing channel
(e.g. channel (recently) closed): (e.g. channel recently closed):
1. type: PERM|8 (`permanent_channel_failure`) 1. type: PERM|8 (`permanent_channel_failure`)
- if the outgoing channel has a requirement advertised in its - if the outgoing channel has requirements advertised in its
`channel_announcement` `features` which was not present in the onion: `channel_announcement` `features` which were NOT included in the onion:
1. type: PERM|9 (`required_channel_feature_missing`) 1. type: PERM|9 (`required_channel_feature_missing`)
- if the receiving peer specified by the onion is not known: - if the receiving peer specified by the onion is NOT known:
1. type: PERM|10 (`unknown_next_peer`) 1. type: PERM|10 (`unknown_next_peer`)
- if the HTLC does not reach the current minimum amount, the amount of the - if the HTLC amount is less than the currently specified minimum amount, the
incoming HTLC and the current channel setting for the outgoing channel are amount of the incoming HTLC and the current channel setting for the outgoing
reported: channel [FIXME: is there a more concise way to say this?] are reported:
1. type: UPDATE|11 (`amount_below_minimum`) 1. type: UPDATE|11 (`amount_below_minimum`)
2. data: 2. data:
* [`8`:`htlc_msat`] * [`8`:`htlc_msat`]
* [`2`:`len`] * [`2`:`len`]
* [`len`:`channel_update`] * [`len`:`channel_update`]
- if the HTLC does not pay a sufficient fee, the amount of the incoming HTLC - if the HTLC does NOT pay a sufficient fee, the amount of the incoming HTLC
and the current channel setting for the outgoing channel are reported: and the current channel setting for the outgoing channel are reported:
1. type: UPDATE|12 (`fee_insufficient`) 1. type: UPDATE|12 (`fee_insufficient`)
2. data: 2. data:
* [`8`:`htlc_msat`] * [`8`:`htlc_msat`]
* [`2`:`len`] * [`2`:`len`]
* [`len`:`channel_update`] * [`len`:`channel_update`]
- if the `outgoing_cltv_value` does not match the `update_add_htlc`'s - if the `outgoing_cltv_value` does NOT match the `update_add_htlc`'s
`cltv_expiry` minus the `cltv_expiry_delta` for the outgoing channel, the `cltv_expiry` minus the `cltv_expiry_delta` for the outgoing channel, the
`cltv_expiry` and the current channel setting for the outgoing channel are `cltv_expiry` and the current channel setting for the outgoing channel are
reported: reported:
@ -719,7 +730,8 @@ errors:
2. data: 2. data:
* [`2`:`len`] * [`2`:`len`]
* [`len`:`channel_update`] * [`len`:`channel_update`]
- if the `cltv_expiry` is unreasonably far, its also possible report an error: - if the `cltv_expiry` is unreasonably far in the future, its also possible to
report an error:
1. type: 21 (`expiry_too_far`) 1. type: 21 (`expiry_too_far`)
- if the channel is disabled, the current channel setting for the outgoing - if the channel is disabled, the current channel setting for the outgoing
channel are reported: channel are reported:
@ -729,37 +741,38 @@ errors:
* [`2`:`len`] * [`2`:`len`]
* [`len`:`channel_update`] * [`len`:`channel_update`]
The _final node_ MAY, but _intermediate hops_ MUST NOT, return one of the The _final node_ MAY, but an _intermediate hop_ MUST NOT, return one of the
following errors: following errors:
- if the payment hash has already been paid: - if the payment hash has already been paid:
- MAY treat the payment hash as unknown. - MAY treat the payment hash as unknown.
- MAY succeed in accepting the HTLC. - MAY succeed in accepting the HTLC [FIXME: is this correct?].
- if the payment hash is unknown: - if the payment hash is unknown:
- MUST fail the HTLC: - MUST fail the HTLC:
1. type: PERM|15 (`unknown_payment_hash`) 1. type: PERM|15 (`unknown_payment_hash`)
- if the amount paid is less than the amount expected: - if the amount paid is less than the amount expected:
- MUST fail the HTLC. - MUST fail the HTLC.
- if the amount paid is more than twice the amount expected: - if the amount paid is more than twice the amount expected:
- SHOULD fail the HTLC. This allows the origin node to reduce information leakage - SHOULD [FIXME: MUST?] fail the HTLC. Note: this allows the origin node to reduce
by altering the amount while not allowing for accidental gross overpayment: information leakage by altering the amount while not allowing for accidental
gross overpayment:
1. type: PERM|16 (`incorrect_payment_amount`) 1. type: PERM|16 (`incorrect_payment_amount`)
- if the `cltv_expiry` is too low: - if the `cltv_expiry` value is too near the present:
- MUST fail the HTLC: - MUST fail the HTLC:
1. type: 17 (`final_expiry_too_soon`) 1. type: 17 (`final_expiry_too_soon`)
- if the `outgoing_cltv_value` does not match the `cltv_expiry` of the HTLC at - if the `outgoing_cltv_value` does NOT correspond with the `cltv_expiry` from
the final node: the final node's HTLC:
1. type: 18 (`final_incorrect_cltv_expiry`) 1. type: 18 (`final_incorrect_cltv_expiry`)
2. data: 2. data:
* [`4`:`cltv_expiry`] * [`4`:`cltv_expiry`]
- if the `amt_to_forward` is greater than the `incoming_htlc_amt` of the HTLC - if the `amt_to_forward` is greater than the `incoming_htlc_amt` from the
at the final node: final node's HTLC:
1. type: 19 (`final_incorrect_htlc_amount`) 1. type: 19 (`final_incorrect_htlc_amount`)
2. data: 2. data:
* [`4`:`incoming_htlc_amt`] * [`4`:`incoming_htlc_amt`]
## Receiving Failure Codes ## Receiving Failure Codes
A node: A node [FIXME: 'origin', 'return-forwarding', or 'any' node?]:
- MUST ignore any extra bytes in `failuremsg`. - MUST ignore any extra bytes in `failuremsg`.
The _origin node_: The _origin node_:
@ -768,9 +781,9 @@ The _origin node_:
- SHOULD fail the payment. - SHOULD fail the payment.
- otherwise: - otherwise:
- if the error code is understood and valid: - if the error code is understood and valid:
- MAY retry the payment. (In particular, `final_expiry_too_soon` can - MAY retry the payment. In particular, `final_expiry_too_soon` can
occur if the block height has changed since sending, occur if the block height has changed since sending, and in this case
`temporary_node_failure` could resolve within a few seconds). `temporary_node_failure` could resolve within a few seconds.
- otherwise, an _intermediate hop_ is returning the error: - otherwise, an _intermediate hop_ is returning the error:
- if the NODE bit is set: - if the NODE bit is set:
- SHOULD remove all channels connected with the erring node from - SHOULD remove all channels connected with the erring node from
@ -780,7 +793,7 @@ The _origin node_:
- otherwise: - otherwise:
- if UPDATE is set, AND the `channel_update` is valid and more recent - if UPDATE is set, AND the `channel_update` is valid and more recent
than the `channel_update` used to send the payment: than the `channel_update` used to send the payment:
- if this [FIXME: what does 'this' refer to?] should not have caused the failure: - if this [FIXME: what does 'this' refer to?] should NOT have caused the failure:
- MAY treat the `channel_update` as invalid. - MAY treat the `channel_update` as invalid.
- otherwise: - otherwise:
- SHOULD apply the `channel_update`. - SHOULD apply the `channel_update`.
@ -788,17 +801,18 @@ The _origin node_:
- otherwise: - otherwise:
- SHOULD eliminate the channel outgoing from the erring node from - SHOULD eliminate the channel outgoing from the erring node from
consideration. consideration.
- if the PERM bit is not set: - if the PERM bit is NOT set:
- SHOULD restore the channel as it receives new `channel_update`s. - SHOULD restore the channel as it receives new `channel_update`s.
- SHOULD then retry routing and sending the payment. - SHOULD then retry routing and sending the payment.
- MAY use the data specified in the various types of failure for debugging - MAY use the data specified in the various failure types for debugging
purposes. purposes.
# Test Vector # Test Vector
## Packet Creation ## Packet Creation
The following is an in-depth trace of the packet creation, including intermediate data. The following is an in-depth trace (including intermediate data) of an example
of packet creation:
### Parameters ### Parameters
@ -816,8 +830,8 @@ The HMAC is omitted in the following `hop_data`, since it's likely to be filled
by the onion construction. Hence, the values below are the `realm`, the by the onion construction. Hence, the values below are the `realm`, the
`short_channel_id`, the `amt_to_forward`, the `outgoing_cltv`, and the 16-byte `short_channel_id`, the `amt_to_forward`, the `outgoing_cltv`, and the 16-byte
`padding`. They were initialized by byte-filling the `short_channel_id` to the `padding`. They were initialized by byte-filling the `short_channel_id` to the
respective position in the route and then (starting at 0) setting each hop's respective position in the route and then, starting at 0, setting
`amt_to_forward` and `outgoing_cltv` to the appropriate position in the route. `amt_to_forward` and `outgoing_cltv` to same route position.
hop_payload[0] = 0x000000000000000000000000000000000000000000000000000000000000000000 hop_payload[0] = 0x000000000000000000000000000000000000000000000000000000000000000000
hop_payload[1] = 0x000101010101010101000000010000000100000000000000000000000000000000 hop_payload[1] = 0x000101010101010101000000010000000100000000000000000000000000000000
@ -894,7 +908,7 @@ respective position in the route and then (starting at 0) setting
## Returning Errors ## Returning Errors
The same parameters (node IDs, shared secrets, ...) as above are used. The same parameters (node IDs, shared secrets, etc.) as above are used.
# node 4 is returning an error # node 4 is returning an error
failure_message = 2002 failure_message = 2002