[Lightning-dev] Decoy node_ids and short_channel_ids

ZmnSCPxj ZmnSCPxj at protonmail.com
Mon Feb 3 05:31:04 UTC 2020


Good morning Rusty,

> Bastien TEINTURIER bastien at acinq.fr writes:
>
> > We can easily get rid of (1.) by leveraging the `payment_secret`. The
> > improved scheme is:
> >
> > -   Alice draws a random `decoy_key`
> > -   Alice computes the corresponding `decoy_node_id = decoy_key * G`
> > -   Alice draws a random `payment_secret`
> > -   Alice computes `decoy_short_channel_id = H(payment_secret * decoy_key * bob_node_id) xor short_channel_id`
> > -   Alice uses the `decoy_key` to sign the invoice
> > -   Carol recovers `decoy_node_id` from the invoice signature
> > -   Carol includes `P_I = payment_secret * decoy_node_id` in the onion
> >     payload for Bob
> >
> > -   Bob can compute `short_channel_id = H(bob_private_key * P_I) xor decoy_short_channel_id`
> >
> > But I don't see how to get rid of (2.). If anyone has a clever idea on how
> > to do that, I'd love to hear it!
>
> I really don't want a special marker on Carol; she needs to just pay
> like normal. Not just because it's simple, but because it means that
> Carol can use a custodial wallet without having to flag the payment as
> somehow special.
>
> AFAICT, having Bob assign scids is the only viable way to do this. The
> current proposal limits to one scid at a time, but it could be extended
> to allow multiple scids.
>
> (I'm seeking a clever way that Bob can assign them and trivially tell
> which ID is assigned to which peer, but I can't figure it out, so I
> guess Bob keeps a mapping and restricts each peer to 256 live scids?).

We can observe that short-channel-ids have a 24-bit blocknum, but it is exceedingly unlikely that for most blockchains, the genesis block will have a Lightning network channel.

So we could reserve blocknum=0 to identify special SCIDs.

The rest of the SCID could refer to the lowest 40 bits of the X-coord of the node ID that is the destination.
We should remember that short channel IDs are used as a convenient way to refer to the next *node* and not the next channel in the onion routing (which is why in Adelaide 2018 we decided to make short channel IDs "advisory", implementation that support multiple channels per peer can use any channel with that peer to forward, not just the specific SCID indicated in the onion).
Now, 40 bits is not a lot, but we can observe that for almost all git repositories, 7 or 8 hex digits is usually enough to unambiguously identify a commit within the repository, even for git repositories with thousands of commits, and 8 hex digits is just 32 bits of identification.
So it seems to me that Bob could just look up the 40 bit identifier to each of the nodes with unpublished channels with it, and this will work well up to Bob having a few thousand peers with unpublished channels.

If we focus on Bitcoin specifically, we can observe as well that `when_lightning_became_cool` is well above 262144 (2^18 ) so we can steal 18 more bits from the blocknum, i.e. if none of the top 6 bits of blocknum are set (blocknum < 262144), then the lower 58 bits of the blockid are the lowest 58 bits of the node ID of the next hop.
Though obviously that is not as good for regtest and testnet, do note that, assuming a non-premined blockchain with a similar 100-block maturity for coinbases, we could still steal 6 bits (blocknum < 64), since no Lightning channel can occur on the first 100 blocks anyway due to the maturity requirement (there *are* no coins that can be spent before then, so no Lightning channels can be created then).


Admittedly, if somebody knows your node id, they need only 40 bits of work to grind a node id of their own whose last 40 bits matches yours, then connect to the same public node you are on.
In that case, it becomes ambiguous for Bob which of the nodes it should send the last hop to, so it could just try them one by one (trying them in parallel risks Bob getting ripped off by an attacker who specifically generates multiple nodes with the same lower bits in the node ID).
Or Bob could just reject future channels from nodes whose lower bits match that with something already channeled with it.


Finally, in this context, this is intended to be used for nodes with unpublished channels.
Of note is that the second-to-the-last node already knows the exact identity, timing, and amount of every payment to the last node anyway, because unpublished channels are not private.
So in this particular case, the second-to-the-last node can actually just drop the payer onion, and replace it with its own onion to the final node.
This is relevant if we ever want to hide the node id of the last node: Bob could provide a symmetric encryption key to all its peers with unpublished channels, which the peer can XOR with its own true node id and use the lowest 40 bits (or 46 bits or 58 bits) in the SCID.
Then when Bob receives an onion whose next SCID has the top 24 or 18 or 6 bits set to 0, it can XOR the symmetric key to the lower bits and then determine the lowest bits of the node id of the last node, and it can then replace the outgoing onion with the corrected onion to that node.
The last node cannot use the payment secret (invoice secret), but that is not going to protect against probe attacks from a public node to a completely unpublished node anyway.
Also the last node cannot receive any data via this method (because the onion is replaced by Bob) but for simple pay-for-preimage applications this will work perfectly fine.


It strikes me as well that a C-Lightning plugin can actually implement this due to `htlc_accepted` hook.


Regards,
ZmnSCPxj



More information about the Lightning-dev mailing list