mirror of
https://github.com/lightning/bolts.git
synced 2025-03-10 09:10:07 +01:00
BOLT 4: complete second-pass copy edit, introduced new terminology 'erring node', require a few clarifications
This commit is contained in:
parent
051f98a75e
commit
54b49c09db
1 changed files with 150 additions and 136 deletions
|
@ -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`.
|
||||
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
|
||||
`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`.
|
||||
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
|
||||
|
@ -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.
|
||||
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
|
||||
multiplication to blind each node's public key with all previous blinding
|
||||
factors and performs ECDH using each node's blinded public key and the `sessionkey`.
|
||||
multiplication to blind each hop's public key with all previous blinding
|
||||
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),
|
||||
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
|
||||
node's public key `nodepk_k` and the hop's shared secret `ss_k`. Before
|
||||
concatenation, the node's public key is serialized in the compressed format.
|
||||
- The ephemeral public key `epk_k` is computed by blinding the previous hop's
|
||||
ephemeral public key `epk_{k-1}` with the previous hop's blinding factor `b_{k-1}`.
|
||||
hop's public key `nodepk_k` and its shared secret `ss_k`. Before
|
||||
concatenation, the hop's public key is serialized in the compressed format.
|
||||
- The ephemeral public key `epk_k` is computed by blinding the hop's sending
|
||||
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`)
|
||||
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,
|
||||
and blinding factors for nodes `{n_2, ..., n_r}`.
|
||||
The origin node then iteratively computes the ephemeral public keys, shared
|
||||
secrets, and blinding factors for hops `{n_2, ..., n_r}`.
|
||||
|
||||
Once the sender has all the required information above, it can construct the packet.
|
||||
Constructing a packet routed over `r` hops requires `r` 32-byte ephemeral
|
||||
public keys, `r` 32-byte shared secrets, `r` 32-byte blinding factors, and `r`
|
||||
65-byte `per_hop` payloads.
|
||||
The construction returns a single 1366-byte packet along with the first hop's address.
|
||||
Once the sender has all the required information above, it can construct the
|
||||
packet. Constructing a packet routed over `r` hops requires `r` 32-byte
|
||||
ephemeral public keys, `r` 32-byte shared secrets, `r` 32-byte blinding factors,
|
||||
and `r` 65-byte `per_hop` payloads. The construction returns a single 1366-byte
|
||||
packet along with the first receiving peer's address.
|
||||
|
||||
The packet construction is performed in the reverse order of the route, i.e.
|
||||
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`,
|
||||
`padding`, and `HMAC` are copied into the following 65 bytes.
|
||||
- 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
|
||||
`hops_data` field is overwritten with the routing information `filler`.
|
||||
- The next HMAC is computed (with the _mu_-key as HMAC-key) over the
|
||||
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`
|
||||
byte, the ephemeral pubkey for the first hop, the HMAC for the first hop, and
|
||||
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
|
||||
func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey,
|
||||
|
@ -395,12 +399,12 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
|
|||
|
||||
# Packet Forwarding
|
||||
|
||||
This specification is limited to `version` `0` packets; however, the structure of
|
||||
future versions may change.
|
||||
This specification is limited to `version` `0` packets; however, the structure
|
||||
of future versions may change.
|
||||
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
|
||||
specifies a version number it doesn't support.
|
||||
For packets with supported version numbers, the processing node then parses the
|
||||
packet with its own supported versions and aborts the connection if the packet
|
||||
specifies a version number that it doesn't support.
|
||||
For packets with supported version numbers, the processing node first parses the
|
||||
packet into its individual fields.
|
||||
|
||||
The processing node:
|
||||
|
@ -408,37 +412,38 @@ The processing node:
|
|||
- MUST abort processing the packet.
|
||||
- MUST report a route failure to the origin node.
|
||||
|
||||
The processing node then computes the shared secret, as described below, using the private
|
||||
key corresponding to its public key and the ephemeral key from the packet.
|
||||
Next, the processing node computes the shared secret using the private key
|
||||
corresponding to its own public key and the ephemeral key from the packet, as
|
||||
described in [Shared Secret](#shared-secret).
|
||||
|
||||
The processing node:
|
||||
- if the packet has previously been forwarded or locally redeemed, i.e. packet
|
||||
contains duplicated routing information:
|
||||
- if the packet has previously been forwarded or locally redeemed, i.e. the
|
||||
packet contains duplicate routing information to a previously received packet:
|
||||
- if preimage is known:
|
||||
- MAY immediately redeem the HTLC using the preimage.
|
||||
- otherwise:
|
||||
- MUST abort processing and report a route failure.
|
||||
|
||||
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
|
||||
analysis. Note that this could be accomplished using a log of previous shared
|
||||
secrets or HMACs, which could be forgotten once the HTLC would not be accepted
|
||||
anyway (i.e. after `outgoing_cltv_value` has passed). Such a log may use a
|
||||
probabilistic data structure, but it MUST rate-limit commitments, as necessary,
|
||||
in order to constrain the worst-case storage requirements or false positives of
|
||||
this log.
|
||||
multiple times, in an attempt to track a payment's progress via traffic
|
||||
analysis. Note that such traffic analysis could be accomplished using a log of
|
||||
previous shared secrets or HMACs, which could be forgotten once the HTLC would
|
||||
not be accepted anyway (i.e. after `outgoing_cltv_value` has passed). Such a log
|
||||
may use a probabilistic data structure, but it MUST rate-limit commitments as
|
||||
necessary, in order to constrain the worst-case storage requirements or false
|
||||
positives of this log.
|
||||
|
||||
The shared secret is used to compute a _mu_-key. The processing node then
|
||||
computes the HMAC of the `hops_data` using the _mu_-key. The resulting HMAC is
|
||||
compared with the HMAC from the packet.
|
||||
Next, the processing node uses the shared secret to compute a _mu_-key, which it
|
||||
in turn uses to compute the HMAC of the `hops_data`. The resulting HMAC is then
|
||||
compared against the packet's HMAC.
|
||||
|
||||
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 report a route failure.
|
||||
|
||||
Comparison of the computed HMAC and the HMAC from the packet MUST be
|
||||
time-constant to avoid leaking information.
|
||||
Comparison of the computed HMAC and the packet's HMAC MUST be
|
||||
time-constant to avoid information leaks.
|
||||
|
||||
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 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
|
||||
|
||||
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.
|
||||
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
|
||||
public key is the processing node's public key, which is
|
||||
blinded by all previous blinding factors.
|
||||
During the processing phase, the secret is the processing node's private key,
|
||||
while the public key is the ephemeral public key from the packet, which has been
|
||||
incrementally blinded by its predecessors.
|
||||
public key is the hop's public key, which is blinded by all previous blinding
|
||||
factors.
|
||||
During the processing phase, the secret is the hop's (processing node's) private
|
||||
key, while the public key is the ephemeral public key from the packet, which has
|
||||
been incrementally blinded by its predecessors.
|
||||
|
||||
The public key is multiplied by the secret, using the `secp256k1` curve.
|
||||
The DER compressed representation of the multiplication result is serialized and
|
||||
hashed using `SHA256`.
|
||||
The resulting hash is returned as the shared secret.
|
||||
hashed using `SHA256`, and the resulting hash is returned as the shared secret.
|
||||
Notice that this is the ECDH variant implemented in `libsecp256k1`.
|
||||
|
||||
# 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
|
||||
for it from the route information and the per-hop payload.
|
||||
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.
|
||||
For this reason, the field is padded before forwarding.
|
||||
This would make the field shorter at each hop, allowing an attacker to deduce the
|
||||
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
|
||||
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
|
||||
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
|
||||
`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
|
||||
obfuscating the added `0x00`-bytes at the end.
|
||||
|
||||
In order to compute the correct HMAC, the origin node has to generate the `hops_data`
|
||||
for each hop, which includes the incrementally obfuscated padding added by each hop.
|
||||
The incrementally obfuscated padding is called the `filler`.
|
||||
In order to compute the correct HMAC, the origin node has to pre-generate the
|
||||
`hops_data` for each hop, including the incrementally obfuscated padding added
|
||||
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
|
||||
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
|
||||
can be generated much more efficiently.
|
||||
The last hop does not obfuscate the filler, since it will not forward the packet
|
||||
and will not extract an HMAC for any further hops.
|
||||
Notice that this example implementation is for demonstration purposes only; the
|
||||
`filler` can be generated much more efficiently.
|
||||
The last hop need not obfuscate the `filler`, since it won't forward the packet
|
||||
any further and thus need not extract an HMAC either.
|
||||
|
||||
# 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.
|
||||
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,
|
||||
representing the blinded element.
|
||||
public key, and a 32-byte shared secret. The output is a single EC point, which
|
||||
represents the blinded element.
|
||||
|
||||
Blinding is accomplished by computing a blinding factor from the hop's public
|
||||
key and the shared secret for that hop.
|
||||
The blinding factor is the result of serializing the hop's public key into its
|
||||
compressed format, appending the shared secret, and computing the `SHA256` hash.
|
||||
The blinded EC point then is the result of the scalar multiplication between the
|
||||
The blinding factor is the computed `SHA256` hash value of the result of
|
||||
serializing the hop's public key into its compressed format and appending the
|
||||
shared secret.
|
||||
The blinded EC point, in turn, is the result of the scalar multiplication of the
|
||||
EC point and the blinding factor.
|
||||
|
||||
# Returning Errors
|
||||
|
||||
The protocol includes a simple mechanism for returning encrypted error messages
|
||||
to the origin node.
|
||||
The onion routing protocol includes a simple mechanism for returning encrypted
|
||||
error messages to the origin node.
|
||||
The returned error messages may be failures reported by any hop, including the
|
||||
final node.
|
||||
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.
|
||||
|
||||
Intermediate hops store the shared secret from the forward path and reuse it to
|
||||
obfuscate the error packet on each hop.
|
||||
In addition, each node locally stores data regarding its sending peer in the
|
||||
route, so it knows where to back-send an eventual return packet.
|
||||
The node returning the message builds a return packet consisting of the
|
||||
following fields:
|
||||
obfuscate any corresponding return packet during each hop.
|
||||
In addition, each node locally stores data regarding its own sending peer in the
|
||||
route, so it knows where to return-forward any eventual return packets.
|
||||
The node generating the error message (_erring node_) builds a return packet
|
||||
consisting of the following fields:
|
||||
|
||||
1. data:
|
||||
* [`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
|
||||
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.
|
||||
- Note: this value is 118 bytes longer than the longest currently-defined
|
||||
message.
|
||||
|
||||
The 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
|
||||
to the packet using `XOR`.
|
||||
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 in turn
|
||||
applied to the packet using `XOR`.
|
||||
|
||||
The obfuscation step is repeated by every hop on the return path.
|
||||
Upon receiving a packet, the hop will generate its `ammag`, generate the
|
||||
pseudo-random byte stream, and apply it to the packet before forwarding.
|
||||
The obfuscation step is repeated by every hop along the return path.
|
||||
Upon receiving a return packet, each hop generates its `ammag`, generates the
|
||||
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
|
||||
was the origin of the corresponding forward packet.
|
||||
The origin node is able to detect that it's the intended final recipient of the
|
||||
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
|
||||
(i.e. it cannot forward the error any further) it then generates the
|
||||
`ammag` and `um` keys for each hop in the route.
|
||||
The origin node then iteratively decrypts the error message using each of the `ammag`
|
||||
keys and computes the HMAC using the `um` keys.
|
||||
(i.e. it cannot return-forward the error any further) it generates the `ammag`
|
||||
and `um` keys for each hop in the route.
|
||||
It then iteratively decrypts the error message, using each hop's `ammag`
|
||||
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
|
||||
`hmac` field with the computed HMAC.
|
||||
|
||||
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 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
|
||||
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
|
||||
|
||||
The failure message encapsulated in `failuremsg` has an identical format as
|
||||
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
|
||||
along with their intended use cases.
|
||||
to that type. Following is a list of the currently supported `failure_code`
|
||||
values and their associated use cases.
|
||||
|
||||
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
|
||||
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
|
||||
but are instead wrapped inside return packets.
|
||||
The numeric values for the `failure_code` may therefore reuse values that are
|
||||
also assigned as message types, without any danger of causing collisions.
|
||||
The numeric values for the `failure_code` may therefore reuse values, that are
|
||||
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 include the appropriate data for that particular error type.
|
||||
- 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:
|
||||
* 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)
|
||||
* 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:
|
||||
1. type: PERM|1 (`invalid_realm`)
|
||||
- if an otherwise unspecified transient error occurs for the entire node:
|
||||
1. type: NODE|2 (`temporary_node_failure`)
|
||||
- if an otherwise unspecified permanent error occurs for the entire node:
|
||||
1. type: PERM|NODE|2 (`permanent_node_failure`)
|
||||
- if a node has requirement advertised in its `node_announcement` `features`
|
||||
which were not present in the onion:
|
||||
- if a node has requirements advertised in its `node_announcement` `features`
|
||||
which were NOT included in the onion:
|
||||
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:
|
||||
- if the onion `version` byte is unknown:
|
||||
1. type: BADONION|PERM|4 (`invalid_onion_version`)
|
||||
|
@ -675,36 +686,36 @@ errors:
|
|||
1. type: BADONION|PERM|6 (`invalid_onion_key`)
|
||||
2. data:
|
||||
* [`32`:`sha256_of_onion`]
|
||||
- if an otherwise unspecified transient error occurs for the outgoing
|
||||
channel (e.g. channel capacity reached, too many in-flight HTLCs):
|
||||
- if an otherwise unspecified, transient error occurs for the outgoing
|
||||
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`)
|
||||
2. data:
|
||||
* [`2`:`len`]
|
||||
* [`len`:`channel_update`]
|
||||
- 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`)
|
||||
- if the outgoing channel has a requirement advertised in its
|
||||
`channel_announcement` `features` which was not present in the onion:
|
||||
- if the outgoing channel has requirements advertised in its
|
||||
`channel_announcement` `features` which were NOT included in the onion:
|
||||
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`)
|
||||
- if the HTLC does not reach the current minimum amount, the amount of the
|
||||
incoming HTLC and the current channel setting for the outgoing channel are
|
||||
reported:
|
||||
- if the HTLC amount is less than the currently specified minimum amount, the
|
||||
amount of the incoming HTLC and the current channel setting for the outgoing
|
||||
channel [FIXME: is there a more concise way to say this?] are reported:
|
||||
1. type: UPDATE|11 (`amount_below_minimum`)
|
||||
2. data:
|
||||
* [`8`:`htlc_msat`]
|
||||
* [`2`:`len`]
|
||||
* [`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:
|
||||
1. type: UPDATE|12 (`fee_insufficient`)
|
||||
2. data:
|
||||
* [`8`:`htlc_msat`]
|
||||
* [`2`:`len`]
|
||||
* [`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` and the current channel setting for the outgoing channel are
|
||||
reported:
|
||||
|
@ -719,7 +730,8 @@ errors:
|
|||
2. data:
|
||||
* [`2`:`len`]
|
||||
* [`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`)
|
||||
- if the channel is disabled, the current channel setting for the outgoing
|
||||
channel are reported:
|
||||
|
@ -729,37 +741,38 @@ errors:
|
|||
* [`2`:`len`]
|
||||
* [`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:
|
||||
- if the payment hash has already been paid:
|
||||
- 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:
|
||||
- MUST fail the HTLC:
|
||||
1. type: PERM|15 (`unknown_payment_hash`)
|
||||
- if the amount paid is less than the amount expected:
|
||||
- MUST fail the HTLC.
|
||||
- if the amount paid is more than twice the amount expected:
|
||||
- SHOULD fail the HTLC. This allows the origin node to reduce information leakage
|
||||
by altering the amount while not allowing for accidental gross overpayment:
|
||||
- SHOULD [FIXME: MUST?] fail the HTLC. Note: this allows the origin node to reduce
|
||||
information leakage by altering the amount while not allowing for accidental
|
||||
gross overpayment:
|
||||
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:
|
||||
1. type: 17 (`final_expiry_too_soon`)
|
||||
- if the `outgoing_cltv_value` does not match the `cltv_expiry` of the HTLC at
|
||||
the final node:
|
||||
- if the `outgoing_cltv_value` does NOT correspond with the `cltv_expiry` from
|
||||
the final node's HTLC:
|
||||
1. type: 18 (`final_incorrect_cltv_expiry`)
|
||||
2. data:
|
||||
* [`4`:`cltv_expiry`]
|
||||
- if the `amt_to_forward` is greater than the `incoming_htlc_amt` of the HTLC
|
||||
at the final node:
|
||||
- if the `amt_to_forward` is greater than the `incoming_htlc_amt` from the
|
||||
final node's HTLC:
|
||||
1. type: 19 (`final_incorrect_htlc_amount`)
|
||||
2. data:
|
||||
* [`4`:`incoming_htlc_amt`]
|
||||
|
||||
## Receiving Failure Codes
|
||||
|
||||
A node:
|
||||
A node [FIXME: 'origin', 'return-forwarding', or 'any' node?]:
|
||||
- MUST ignore any extra bytes in `failuremsg`.
|
||||
|
||||
The _origin node_:
|
||||
|
@ -768,9 +781,9 @@ The _origin node_:
|
|||
- SHOULD fail the payment.
|
||||
- otherwise:
|
||||
- if the error code is understood and valid:
|
||||
- MAY retry the payment. (In particular, `final_expiry_too_soon` can
|
||||
occur if the block height has changed since sending,
|
||||
`temporary_node_failure` could resolve within a few seconds).
|
||||
- MAY retry the payment. In particular, `final_expiry_too_soon` can
|
||||
occur if the block height has changed since sending, and in this case
|
||||
`temporary_node_failure` could resolve within a few seconds.
|
||||
- otherwise, an _intermediate hop_ is returning the error:
|
||||
- if the NODE bit is set:
|
||||
- SHOULD remove all channels connected with the erring node from
|
||||
|
@ -780,7 +793,7 @@ The _origin node_:
|
|||
- otherwise:
|
||||
- if UPDATE is set, AND the `channel_update` is valid and more recent
|
||||
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.
|
||||
- otherwise:
|
||||
- SHOULD apply the `channel_update`.
|
||||
|
@ -788,17 +801,18 @@ The _origin node_:
|
|||
- otherwise:
|
||||
- SHOULD eliminate the channel outgoing from the erring node from
|
||||
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 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.
|
||||
|
||||
# Test Vector
|
||||
|
||||
## 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
|
||||
|
||||
|
@ -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
|
||||
`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
|
||||
respective position in the route and then (starting at 0) setting
|
||||
`amt_to_forward` and `outgoing_cltv` to the appropriate position in the route.
|
||||
each hop's respective position in the route and then, starting at 0, setting
|
||||
`amt_to_forward` and `outgoing_cltv` to same route position.
|
||||
|
||||
hop_payload[0] = 0x000000000000000000000000000000000000000000000000000000000000000000
|
||||
hop_payload[1] = 0x000101010101010101000000010000000100000000000000000000000000000000
|
||||
|
@ -894,7 +908,7 @@ respective position in the route and then (starting at 0) setting
|
|||
|
||||
## 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
|
||||
failure_message = 2002
|
||||
|
|
Loading…
Add table
Reference in a new issue