Skip to content

Commit

Permalink
BOLT 4: onion message support.
Browse files Browse the repository at this point in the history
These use onion encoding for simple one-way messaging: there are no error returns.
However, every onion uses route blinding *even if it doesn't need to*.

You can prove what path was used to reach you by including `path_id` in the
encrypted_data_tlv.

Note that this doesn't actually define the payload we're transporting:
that's explictly defined to be payloads in the 64-255 range.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell committed Aug 3, 2022
1 parent 03f0c7d commit 60c6f8a
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 0 deletions.
1 change: 1 addition & 0 deletions .aspell.en.pws
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ CHECKSIGVERIFY
IFDUP
sats
anysegwit
onionmsg
griefing
unspendable
pkh
Expand Down
139 changes: 139 additions & 0 deletions 04-onion-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ A node:
* [TLV Payload Format](#tlv_payload-format)
* [Basic Multi-Part Payments](#basic-multi-part-payments)
* [Route Blinding](#route-blinding)
* [Onion Message Payload Format](#onion-message-payload-format)
* [Accepting and Forwarding a Payment](#accepting-and-forwarding-a-payment)
* [Payload for the Last Node](#payload-for-the-last-node)
* [Non-strict Forwarding](#non-strict-forwarding)
Expand All @@ -63,6 +64,7 @@ A node:
* [Returning Errors](#returning-errors)
* [Failure Messages](#failure-messages)
* [Receiving Failure Codes](#receiving-failure-codes)
* [Onion Messages](#onion-messages)
* [Test Vector](#test-vector)
* [Returning Errors](#returning-errors)
* [References](#references)
Expand Down Expand Up @@ -598,6 +600,93 @@ sender that could help them unblind the identity of the blinded nodes. Also,
instead of forwarding errors, nodes should replace them with garbage, in case
a downstream node was buggy and returned a valid onion error.


### Onion Message Payload Format

Onion messages have an onion with an alternate `hop_payload`
format: a `bigsize` followed by a `onionmsg_payload`. Note that there
is no legacy format, thus a `bigsize` of 0 means no payload.

An intermediate node expects an `encrypted_data_tlv` which it can
decrypt using the `blinding` which it is handed along with the onion
message.

Field numbers 64 and above are reserved for payloads for the final
hop.

1. `tlv_stream`: `onionmsg_payload`
2. types:
1. type: 2 (`reply_path`)
2. data:
* [`point`:`first_node_id`]
* [`point`:`blinding`]
* [`...*onionmsg_path`:`path`]
1. type: 4 (`encrypted_data_tlv`)
2. data:
* [`...*byte`:`encrypted_data_tlv`]

1. subtype: `onionmsg_path`
2. data:
* [`point`:`node_id`]
* [`u16`:`enclen`]
* [`enclen*byte`:`encrypted_recipient_data`]


#### Requirements

The writer:
- For the non-final nodes' `onionmsg_payload`:
- MUST set `enctlv` to a valid `encrypted_data_tlv` stream containing `next_node_id`.
- MUST encrypt `enctlv` as detailed in [Route Blinding](#route-blinding).
- MAY include `padding`.
- MUST NOT set `path_id`.
- For the final node's `onionmsg_payload`:
- if the final node is permitted to reply:
- MUST set `reply_path` `blinding` to the initial blinding factor for the `next_node_id`
- MUST set `reply_path` `first_node_id` to the unblinded node id of the first node in the reply path.
- For every `reply_path` `path`:
- MUST set `node_id` to the blinded node id to encrypt the onion hop for.
- MUST encrypt `enctlv` as detailed in [Route Blinding](#route-blinding).
- MUST set `enctlv` to a valid `encrypted_data_tlv` stream which meets the requirements
of the `onionmsg_payload` when used by the recipient.
- MAY use `path_id` to contain a secret so it can recognize use of this `reply_path`.
- otherwise:
- MUST NOT set `reply_path`.

The reader:
- if it is not the final node according to the onion encryption:
- if `enctlv` is not present, or does not decrypt with the shared secret from the given `blinding` parameter:
- MUST drop the message.
- if the `enctlv` is not a valid `encrypted_data_tlv` tlvstream or does not contain `next_node_id`:
- MUST drop the message.
- if the `enctlv` contains `path_id`:
- MUST drop the message.
- otherwise:
- MUST ignore `padding`, if any.
- SHOULD forward the message using `onion_message` to the next peer indicated by `next_node_id`.
- if it forwards the message:
- MUST set `blinding` in the forwarded `onion_message` to the next blinding as calculated in [Route Blinding](#route-blinding).
- otherwise (it is the final node):
- if `path_id` is set and corresponds to a path the reader has previously published in a `reply_path`:
- if the onion message is not a reply to that previous onion:
- MUST ignore the onion message
- otherwise (unknown or unset `path_id`):
- if the onion message is a reply to an onion message which contained a `path_id`:
- MUST respond (or not respond) exactly as if it did not send the initial onion message.
- if it wants to send a reply:
- MUST create an onion message using `reply_path`.
- MUST send the reply via `onion_message` to the node indicated by
the `first_node_id`, using `reply_path` `blinding` to send
along `reply_path` `path`.


#### Rationale

Care must be taken that replies are only accepted using the exact
reply_path given, otherwise probing is possible. That means checking
both ways: non-replies don't use the reply path, and replies always
use the reply path.

# Accepting and Forwarding a Payment

Once a node has decoded the payload it either accepts the payment locally, or forwards it to the peer indicated as the next hop in the payload.
Expand Down Expand Up @@ -1391,6 +1480,56 @@ The _origin node_:
- MAY use the data specified in the various failure types for debugging
purposes.

# Onion Messages

Onion messages allow peers to use existing connections to query for
invoices (see [BOLT 12](12-offer-encoding.md)). Like gossip messages,
they are not associated with a particular local channel. Like HTLCs,
they use [onion messages](#onion-message-payload-format) protocol for
end-to-end encryption.

Onion messages are unreliable: in particular, they are designed to
be cheap to process and require no storage to forward. As a result,
there is no error returned from intermediary nodes.

For consistency, all onion messages use [Route Blinding](#route-blinding).

## The `onion_message` Message

1. type: 513 (`onion_message`) (`option_onion_messages`)
2. data:
* [`point`:`blinding`]
* [`u16`:`len`]
* [`len*byte`:`onionmsg`]

## Requirements

The writer:
- MUST populate the per-hop payloads as described in [Onion Message Payload Format](onion-message-payload-format).
- SHOULD retry via a different route if it expects a response and
doesn't receive one after a reasonable period.
- SHOULD set `len` to 1366 or 32834.

The reader:
- MUST handle the per-hop payloads as described in [Onion Message Payload Format](onion-message-payload-format).
- SHOULD accept onion messages from peers without an established channel.
- MAY rate-limit messages by dropping them.

## Rationale

All onion messages are blinded, even though this overhead is not
always necessary (33 bytes here, the 16-byte MAC for each enctlv in
the onion). This blinding allows nodes to use a path provided by
others without knowing its contents. Using it universally simplifies
implementations a little, and makes it more difficult to distinguish
onion messages.

`len` allows larger messages to be sent than the standard 1300 bytes
allowed for an HTLC onion, but this should be used sparingly as it is
reduces anonymity set, hence the recommendation that it either look
like an HTLC onion, or if larger, be a fixed size.


# Test Vector

## Returning Errors
Expand Down
1 change: 1 addition & 0 deletions 09-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The Context column decodes as follows:
| 22/23 | `option_anchors_zero_fee_htlc_tx` | Anchor commitment type with zero fee HTLC transactions | IN | `option_static_remotekey` | [BOLT #3][bolt03-htlc-tx], [lightning-dev][ml-sighash-single-harmful] |
| 24/25 | `option_route_blinding` | Node supports blinded paths | IN9 | `var_onion_optin` | [BOLT #4](bolt04-route-blinding) |
| 26/27 | `option_shutdown_anysegwit` | Future segwit versions allowed in `shutdown` | IN | | [BOLT #2][bolt02-shutdown] |
| 38/39 | `option_onion_messages` | Can forward onion messages | IN | | [BOLT #7](04-onion-routing.md#onion-messages) |
| 44/45 | `option_channel_type` | Node supports the `channel_type` field in open/accept | IN | | [BOLT #2](02-peer-protocol.md#the-open_channel-message) |
| 46/47 | `option_scid_alias` | Supply channel aliases for routing | IN | | [BOLT #2][bolt02-channel-ready] |
| 48/49 | `option_payment_metadata` | Payment metadata in tlv record | 9 | | [BOLT #11](11-payment-encoding.md#tagged-fields) |
Expand Down
61 changes: 61 additions & 0 deletions bolt04/enctlvs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
[
{
"test name": "Simple enctlv for Alice, next is Bob",
"node_privkey": "414141414141414141414141414141414141414141414141414141414141414101",
"node_id": "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619",
"blinding_secret": "050505050505050505050505050505050505050505050505050505050505050501",
"blinding": "0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7",
"encmsg": {
"next_node_id": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c"
},
"ss": "2e83e9bc7821d3f6cec7301fa8493aee407557624fb5745bede9084852430e3f",
"HMAC256('blinded_node_id', ss)": "7d846b3445621d49a665e5698c52141e9dda8fa2fe0c3da7e0f9008ccc588a38",
"blinded_node_id": "02004b5662061e9db495a6ad112b6c4eba228a079e8e304d9df50d61043acbc014",
"E": "0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f7",
"H(E || ss)": "bae3d9ea2b06efd1b7b9b49b6cdcaad0e789474a6939ffa54ff5ec9224d5b76c",
"next_e": "76d4de6c329c79623842dcf8f8eaee90c9742df1b5231f5350df4a231d16ebcf01",
"encmsg_hex": "04210324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c",
"rho": "030ddf4da23c97ada489fbdc4342e701de57f6170e46c66ea6c7585b0933db80",
"enctlv_hex": "6970e870b473ddbc27e3098bfa45bb1aa54f1f637f803d957e6271d8ffeba89da2665d62123763d9b634e30714144a1c165ac9"
},
{
"test name": "Blinding-key-override enctlv for Bob, next is Carol",
"node_privkey": "424242424242424242424242424242424242424242424242424242424242424201",
"node_id": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c",
"blinding_secret": "76d4de6c329c79623842dcf8f8eaee90c9742df1b5231f5350df4a231d16ebcf01",
"blinding": "03fc5e56da97b462744c9a6b0ba9d5b3ffbfb1a08367af9cc6ea5ae03c79a78eec",
"encmsg": {
"next_node_id": "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007",
"blinding": "070707070707070707070707070707070707070707070707070707070707070701"
},
"ss": "f18a1ddb1cb27d8fc4faf2cf317e87524fcc6b7f053496d95bf6e6809d09851e",
"HMAC256('blinded_node_id', ss)": "8074773a3745818b0d97dd875023486cc35e7afd95f5e9ec1363f517979e8373",
"blinded_node_id": "026ea8e36f78e038c659beba9229699796127471d9c7a24a0308533371fd63ad48",
"E": "03fc5e56da97b462744c9a6b0ba9d5b3ffbfb1a08367af9cc6ea5ae03c79a78eec",
"H(E || ss)": "9afb8b2ebc174dcf9e270be24771da7796542398d29d4ff6a4e7b6b4b9205cfe",
"next_e": "5149cb0ce6100209f9a2a1140c4e6e8235381aac6201da2c0f8ce1f91bcc3b6e01",
"encmsg_hex": "0421027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa20070c2102989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f",
"rho": "46b7af481999101f3d7fb20a87c4d6fb9191b93ddc0f163d00b94fcbc571f564",
"enctlv_hex": "1630da85e8759b8f3b94d74a539c6f0d870a87cf03d4986175865a2985553c997b560c36613bd9184c1a6d41a37027aabdab5433009d8409a1b638eb90373778a05716af2c215b3d31db7b2c2659716e663ba3d9c909"
},
{
"test name": "Padded enctlv for Carol, next is Dave",
"node_privkey": "434343434343434343434343434343434343434343434343434343434343434301",
"node_id": "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007",
"blinding_secret": "070707070707070707070707070707070707070707070707070707070707070701",
"blinding": "02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f",
"encmsg": {
"next_node_id": "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991",
"padding": "0000000000000000000000000000000000000000000000000000000000000000000000"
},
"ss": "8c0f7716da996c4913d720dbf691b559a4945bf70cdd18e0b61e3e42635efc9c",
"HMAC256('blinded_node_id', ss)": "02afb2187075c8af51488242194b44c02624785ccd6fd43b5796c68f3025bf88",
"blinded_node_id": "02f4f524562868a09d5f54fb956ade3fa51ef071d64d923e395cc6db5e290ec67b",
"E": "02989c0b76cb563971fdc9bef31ec06c3560f3249d6ee9e5d83c57625596e05f6f",
"H(E || ss)": "cc3b918cda6b1b049bdbe469c4dd952935e7c1518dd9c7ed0cd2cd5bc2742b82",
"next_e": "306f017c285aac7b613e0f70895b7e4fa5cce9ddaf96f50c613d5dcee847703801",
"encmsg_hex": "012300000000000000000000000000000000000000000000000000000000000000000000000421032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991",
"rho": "d6297b5645c27be8ea1240cc96e162c53fd9c389c6bec25cbdb4b6b3f654e7bc",
"enctlv_hex": "8285acbceb37dfb38b877a888900539be656233cd74a55c55344fb068f9d8da365340d21db96fb41b76123207daeafdfb1f571e3fea07a22e10da35f03109a0380b3c69fcbed9c698086671809658761cf65ecbc3c07a2e5"
}
]

0 comments on commit 60c6f8a

Please sign in to comment.