1
0
mirror of https://github.com/lightning/bolts.git synced 2025-01-18 21:32:31 +01:00

BOLT-4 Re-Edits

Minor edits, clarifications, and standardizations.
This commit is contained in:
Shannon Appelcline 2017-12-21 15:41:59 -08:00 committed by Rusty Russell
parent 46c454cb56
commit 29ae44ec6e

View File

@ -15,18 +15,18 @@ the packet and can learn which node they should forward the
packet to. They cannot learn which other nodes, besides their
predecessor or successor, are part of the packet's route; nor can they learn
the length of the route or their position within it. The packet is
obfuscated at each hop, to ensure that a network level attacker cannot
associate packets belonging to the same route, i.e. packets belonging
to the same route do not share any correlating information. Notice that this
obfuscated at each hop, to ensure that a network-level attacker cannot
associate packets belonging to the same route (i.e. packets belonging
to the same route do not share any correlating information). Notice that this
does not preclude the possibility of packet association by an attacker
via traffic analysis.
The route is constructed by the origin node, which knows the public
keys of each intermediate node. Knowing each intermediate hop's public key
keys of each intermediate node and of the final node. Knowing each node's public key
allows the origin node to create a shared secret (using ECDH) for each
intermediate node, including the final recipient node. The shared secret is then
used to generate a _pseudo-random stream_ of bytes (used to obfuscate
the packet) and a number of _keys_ (used to encrypt the payload and
intermediate node and for the final node. The shared secret is then
used to generate a _pseudo-random stream_ of bytes (which is used to obfuscate
the packet) and a number of _keys_ (which are used to encrypt the payload and
compute the HMACs). The HMACs are then in turn used to ensure the integrity of
the packet at each hop.
@ -68,7 +68,7 @@ A node:
There are a number of conventions adhered to throughout this document:
- The maximum route length is limited to 20 hops.
- Length: the maximum route length is limited to 20 hops.
- HMAC: the integrity verification of the packet is based on Keyed-Hash
Message Authentication Code, as defined by the
[FIPS 198 Standard](http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf)/[RFC 2104](https://tools.ietf.org/html/rfc2104),
@ -120,6 +120,7 @@ path, so that each hop may only recover the address and HMAC of the next hop.
The pseudo-random byte stream is generated by encrypting (using `ChaCha20`) a
`0x00`-byte stream, of the required length, which is initialized with a key
derived from the shared secret and a zero-nonce (`0x00000000000000`).
The use of a fixed nonce is safe, since the keys are never reused.
# Packet Structure
@ -129,11 +130,11 @@ The packet consists of four sections:
- a `version` byte
- a 33-byte compressed `secp256k1` `public_key`, used during the shared secret
generation
- a 1300-byte `hops_data` consisting of 20 fixed-size packets, each containing
- a 1300-byte `hops_data` consisting of twenty fixed-size packets, each containing
information to be used by its associated hop during message forwarding
- a 32-byte `HMAC`, used to verify the packet's integrity
The network format of the packet consists of the individual sections being
The network format of the packet consists of the individual sections
serialized into one contiguous byte-stream and then transferred to the packet
recipient. Due to the fixed size of the packet, it need not be prefixed by its
length when transferred over a connection.
@ -150,7 +151,7 @@ The overall structure of the packet is as follows:
For this specification (_version 0_), `version` has a constant value of `0x00`.
The `hops_data` field is a structure that holds obfuscations of the next hop's
address, transfer information, and its associated HMAC. It is 1300 bytes long
address, transfer information, and its associated HMAC. It is 1300 bytes (`20x65`) long
and has the following structure:
1. type: `hops_data`
@ -161,13 +162,13 @@ and has the following structure:
* ...
* `filler`
Where, the `realm`, `HMAC`, and `per_hop` (of which contents depend on `realm`)
Where, the `realm`, `per_hop` (with contents dependent on `realm`), and `HMAC`
are repeated for each hop; and where, `filler` consists of obfuscated,
deterministically-generated padding, as detailed in
[Filler Generation](#filler-generation). Additionally, `hops_data` is
incrementally obfuscated at each hop.
The `realm` byte determines the format of the `per_hop`; currently, only `realm`
The `realm` byte determines the format of the `per_hop` field; currently, only `realm`
0 is defined, for which the `per_hop` format follows:
1. type: `per_hop` (for `realm` 0)
@ -177,15 +178,17 @@ The `realm` byte determines the format of the `per_hop`; currently, only `realm`
* [`4`:`outgoing_cltv_value`]
* [`12`:`padding`]
Using the `per_hop`, the origin node is able to precisely specify the path and
Using the `per_hop` field, the origin node is able to precisely specify the path and
structure of the HTLCs forwarded at each hop. As the `per_hop` is protected
under the packet-wide HMAC, the information it contains is fully authenticated
with each pair-wise relationship between the HTLC sender (origin node) and each
hop in the path.
Using this end-to-end authentication, in addition to
cross-checking the HTLC parameters with the `per_hop`'s specified values, each
hop is able to ensure the sending peer hasn't forwarded it an
Using this end-to-end authentication,
each
hop is able to
cross-check the HTLC parameters with the `per_hop`'s specified values
and to ensure that the sending peer hasn't forwarded an
ill-crafted HTLC.
Field descriptions:
@ -197,9 +200,9 @@ Field descriptions:
receiving peer specified within the routing information.
This value amount MUST include the origin node's computed _fee_ for the
receiving peer. When processing an incoming Sphinx packet, along with the HTLC
receiving peer. When processing an incoming Sphinx packet and the HTLC
message that it is encapsulated within, if the following inequality doesn't hold,
then the HTLC should be rejected; as this indicates a prior hop has
then the HTLC should be rejected as it would indicate that a prior hop has
deviated from the specified parameters:
incoming_htlc_amt - fee >= amt_to_forward
@ -217,9 +220,9 @@ Field descriptions:
specified by the origin node, and the parameters of the HTLC forwarded,
and ensure the origin node is using the current `cltv_expiry_delta` value.
If there is no next hop, `cltv_expiry_delta` is 0.
If the values don't correspond, then the HTLC should be failed and rejected as
If the values don't correspond, then the HTLC should be failed and rejected, as
this indicates that either a forwarding node has tampered with the intended HTLC
values, or the origin node has an obsolete `cltv_expiry_delta` value.
values or that the origin node has an obsolete `cltv_expiry_delta` value.
The hop MUST be consistent in responding to an unexpected
`outgoing_cltv_value`, whether it is the final node or not, to avoid
leaking its position in the route.
@ -254,7 +257,7 @@ simply discard its payload.
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
is the sender itself and `n_r` is the final recipient. All nodes `n_i` and
`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
@ -312,7 +315,7 @@ following operations:
- The _rho_-key and _mu_-key are generated using the hop's shared secret.
- The `hops_data` field is right-shifted by 65 bytes, discarding the last 65
bytes that exceed its 1300 byte size.
bytes that exceed its 1300-byte size.
- 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
@ -399,8 +402,9 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
# Packet Forwarding
This specification is limited to `version` `0` packets; however, the structure
This specification is limited to `version` `0` packets; the structure
of future versions may change.
Upon receiving a packet, a processing node compares the version byte of the
packet with its own supported versions and aborts the connection if the packet
specifies a version number that it doesn't support.
@ -443,8 +447,8 @@ processing hop is the intended recipient and that the packet should not be forwa
If the HMAC does not indicate route termination, and if the next hop is a peer of the
processing node; then the new packet is assembled. Packet assembly is accomplished
by blinding the ephemeral key with the processing node's public key along with the
shared secret and by serializing the `hops_data`.
by blinding the ephemeral key with the processing node's public key, along with the
shared secret, and by serializing the `hops_data`.
The resulting packet is then forwarded to the addressed peer.
## Requirements
@ -474,10 +478,10 @@ The processing node:
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 inputs, and returns a 32-byte secret, as output.
The shared secret builder function takes a public key and a 32-byte secret,
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 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
@ -485,7 +489,7 @@ 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
The DER-compressed representation of the multiplication result is serialized and
hashed using `SHA256`, and the resulting hash is returned as the shared secret.
Notice that this is the ECDH variant implemented in `libsecp256k1`.
@ -544,7 +548,7 @@ func generateFiller(key string, numHops int, hopSize int, sharedSecrets [][share
}
```
Notice that this example implementation is for demonstration purposes only; the
Note 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.
@ -857,11 +861,11 @@ of packet creation:
### Parameters
pubkey[0] 0x02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619
pubkey[1] 0x0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c
pubkey[2] 0x027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007
pubkey[3] 0x032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991
pubkey[4] 0x02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145
pubkey[0] = 0x02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619
pubkey[1] = 0x0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c
pubkey[2] = 0x027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007
pubkey[3] = 0x032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991
pubkey[4] = 0x02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145
nhops = 5/20
sessionkey = 0x4141414141414141414141414141414141414141414141414141414141414141