[Lightning-dev] Blind paths revisited

Rusty Russell rusty at rustcorp.com.au
Tue Mar 10 00:19:03 UTC 2020


I recently hit a dead-end on rendezvous routing; the single-use
requirement is a showstopper for offers (which are supposed to be static
and reusable).

Fortunately, t-bast has a scheme for blinded paths (see
https://gist.github.com/t-bast/9972bfe9523bb18395bdedb8dc691faf ) so
I've been examining that more closely.  I think it can be simplified
to use more standard primitives.

The problem: Alice wants to present Mallory with a path (Carol, Bob,
Alice) for which he can create an onion, which is obscured in some way,
but can be unobscured by the various nodes.  Mallory should be forced to
use the entire path.

Alice can give Mallory two ECDH blobs to place inside the per-hop
payload to establish shared secrets with Bob and Carol.  But crucially,
Bob needs the secret *before* he can unwrap the onion, so the ECDH
blob for the next peer needs to be sent alongside the onion itself.

t-bast proposed using the secret to XOR the scid, but Christian
suggested it's more powerful to encrypt a general payload.

What does this leave us with?

1. A new invoice letter `b`.  Encodes
   1 or more pubkey/feebase/feeprop/cltvdelta/features/encblob.

2. An additional (tlv of course) field to update_add_htlc, `blinding`.

3. New `tlv_payload` field `encblob` (varlen).

4. ECDH on incoming `blinding` to get a shared secret which tells
   this node how to tweak its nodeid to decrypt onion, and also how to
   decrypt `encblob`.  This gives a tlv, which presumably contains
   `short_channel_id` as well as `blinding`.

5. Use `blinding` for the next update_add_htlc.

6. If you get an error from downstream and you sent `blinding`, turn it
   into your own error for maximum obfuscation.  Perhaps a new
   "blinded_path_error"?  Obviously does not include a channel_update :)

So, if you get an invoice `b`, with path starting at (known) Carol:

        Carol/1/1/9/""/enc1
          Bob'/1/1/9/""/enc2
            [Optional: decoy hops...]

Payer constructs the onion to get to Carol as normal, then:

        Carol: No `blinding` in incoming HTLC, but once it decrypts the
               onion, she sees `encblob` (value enc1).  Uses first 32
               bytes of `enc1` as `blinding`: do ECDH to get SS1, uses
               SS1 to decrypt rest to get next scid and `blinding`, send
               `blinding` with update_add_htlc to Bob.

        Bob: Gets `blinding` from update_add_htlc. ECDH -> SS2.  Tweak
               own key with SS2 to decode onion.  Use SS2 to decrypt
               `enc2` to get next scid and blinding.  Send `blinding`
               with update_add_htlc to Alice.

        Alice: Gets `blinding` from update_add_htlc. ECDH -> SS3.  Tweak
               own key with SS3 to decode onion.  If it put in decoy
               hops, this onion won't be terminal, but otherwise it can
               be treated as terminal iff `blinding` is the expected value
               for this invoice.

Note that this means no payment secret is necessary, since the incoming
`blinding` serves the same purpose.  If we wanted to, we could (ab)use
payment_secret as the first 32-bytes to put in Carol's enc1 (i.e. it's
the ECDH for Carol to decrypt enc1).

Thoughts?
Rusty.


More information about the Lightning-dev mailing list