Christian Decker [ARCHIVE] on Nostr: 📅 Original date posted:2020-03-02 📝 Original message: Hi Bastien, thanks for ...
📅 Original date posted:2020-03-02
📝 Original message:
Hi Bastien,
thanks for verifying my proposal, and I do share your concerns regarding
privacy leaks (how many hops are encoded in the onion) and success ratio
if a payment is based on a fixed (partial) path.
> I believe this makes it quite usable in Bolt 11 invoices, without blowing up
> the size of the QR code (but more experimentation is needed on that).
It becomes a tradeoff of how small you want your onion to be, and how
many hops the partial onion can have. For longer partial onions we're
getting close to the current full onion size, but I expect most partial
onion to be close to the network diameter of ~6 (excluding degerenate
chains). So the example below with 5 hops seemed realistic, and dropping
the legacy format in favor of TLVs we can get a couple of bytes back as
well.
>> As an example such an onion, with 5 legacy hops (65 byte each) results
>> in a 325 + 66 bytes onion, and we save 975 bytes.
>
> While having flexibility when choosing the length of the prefill
> stream feels nice, wouldn't it be safer to impose a fixed size to
> avoid any kind of heuristic at `RV` to try to guess how many hops
> there are between him and the recipient?
I'm currently just using the maximum size, which is an obvious privacy
leak, but I'm also planning on exposing the size to be prefilled, and
hence cropped out when compressing, when generating. Ideally we'd have a
couple of presets, i.e., 1/4, 2/4, 3/4, and adhere to them, randomizing
which one we pick.
Having smaller partial onions would enable my stretch goal of being able
to chain multiple partial onions, though that might be a useless
achievement to unlock xD
>> Compute a shared secret using a random ephemeral private key and
>> `RV`s public key, and then generate a prefill-key
>
>
> While implementing, I felt that the part about the shared secret used
> to generate the prefill stream is a bit blurry (your proposal on
> Github doesn't phrase it the same way). I think it's important to
> stress that this secret is derived from both `ephkey` and `RV`'s
> private key, so that `RV+1` can't compute the same stream.
I noticed the same while implementing the decompress stage, which
requires the node ID from `RV` during generation, and performs ECDH +
HKDF with the `RV` node private and the ephemeral key in the *next*
onion, i.e., the one extracted from the payload itself. This is
necessary since the ephemeral key on the incoming onion, which delivered
the partial onion in its payload is not controlled by the partial onion
creator, while the one in the partial onion is.
This means that the ephemeral key in the partial onion is used twice:
- Once by `RV` to generate the obfuscation stream to fill in the gap
- As part of the reconstructed onion, processed by `RV+1` to decode the
onion.
I'm convinced this is secure and doesn't leak information since
otherwise transporting the ephemeral key publicly would be insecure
(`RV+1` can't generate the obfuscation secret used to fill in the gap
without access to `RV`s private key), and the ephemeral key is only
transmitted in cleartext once (from `RV` to `RV+1`), otherwise it is
hidden in the outer onion.
> Another thing that may be worth mentioning is error forwarding. Since
> the recipient generated the onion, `RV` won't have the shared secrets
> (that's by design). So it's expected that payment errors won't be
> readable by `RV`, but it's probably a good idea if `RV` returns an
> indication to the sender that the payment failed *after* the
> rendezvous point.
Indeed, this is pretty much by design, since otherwise the sender could
provoke errors, e.g., consuming all of `RV`s outgoing capacity with
probes to get back temporary channel failure errors for the channel that
was encoded in the partial onion, and then do that iteratively until we
have identified the real destination which we weren't supposed to learn.
So any error beyond `RV` should be treated by the sender as "rendez-vous
failed, discard partial onion".
> An important side-note is that your proposal is really quick and
> simple to implement from the existing Sphinx code. I have made ASCII
> diagrams of the scheme (see [1]). This may help readers visualize it
> more easily.
I quickly skimmed the drawings and they're very nice to understand how
regions overlap, that was my main problem with the whole sphinx
construction, so thanks for taking the time :+1:
> It still has the issue that each hop's amount/cltv is fixed at invoice
> generation time by the recipient. That means MPP cannot be used, and
> if any channel along the path updates their fee the partial onion
> becomes invalid (unless you overpay the fees).
>
> Trampoline should be able to address that since it provides more
> freedom to each trampoline node to find an efficient way to forward to
> the next trampoline. It's not yet obvious to me how I can mix these
> two proposals to make it work though. I'll spend more time
> experimenting with that.
True, I think rendez-vous routing have some use-cases, but routing in
the public network seems a bit brittle. It is definitely not MPP
compliant since the sphinx constructions says that each shared secret
should be blacklisted after use, and if we were to use the partial onion
on multiple path we'd be bound to use the same shared secret for the
subpaths contained in the partial onion.
I've been mostly thinking about systems in which you can guarantee
stability, e.g., in a subnetwork controlled by the recipient, but to
hide any internal routing decisions. That'd be similar to a supercharged
routing hint basically, without revealing the internal structure.
Cheers,
Christian
Published at
2023-06-09 12:59:07Event JSON
{
"id": "156bd13dbf87fba37cfea56690fd895d089e1a5f94de21d35be373d614226be0",
"pubkey": "72cd40332ec782dd0a7f63acb03e3b6fdafa6d91bd1b6125cd8b7117a1bb8057",
"created_at": 1686315547,
"kind": 1,
"tags": [
[
"e",
"9b67a24090ce4f2c016fd146756943a1599a99e34616bf17b25a5468fbe5b4b0",
"",
"reply"
],
[
"p",
"9456f7acb763eaab2e02bd8e60cf17df74f352c2ae579dce1f1dd25c95dd611c"
]
],
"content": "📅 Original date posted:2020-03-02\n📝 Original message:\nHi Bastien,\n\nthanks for verifying my proposal, and I do share your concerns regarding\nprivacy leaks (how many hops are encoded in the onion) and success ratio\nif a payment is based on a fixed (partial) path.\n\n\u003e I believe this makes it quite usable in Bolt 11 invoices, without blowing up\n\u003e the size of the QR code (but more experimentation is needed on that).\n\nIt becomes a tradeoff of how small you want your onion to be, and how\nmany hops the partial onion can have. For longer partial onions we're\ngetting close to the current full onion size, but I expect most partial\nonion to be close to the network diameter of ~6 (excluding degerenate\nchains). So the example below with 5 hops seemed realistic, and dropping\nthe legacy format in favor of TLVs we can get a couple of bytes back as\nwell.\n\n\u003e\u003e As an example such an onion, with 5 legacy hops (65 byte each) results\n\u003e\u003e in a 325 + 66 bytes onion, and we save 975 bytes.\n\u003e\n\u003e While having flexibility when choosing the length of the prefill\n\u003e stream feels nice, wouldn't it be safer to impose a fixed size to\n\u003e avoid any kind of heuristic at `RV` to try to guess how many hops\n\u003e there are between him and the recipient?\n\nI'm currently just using the maximum size, which is an obvious privacy\nleak, but I'm also planning on exposing the size to be prefilled, and\nhence cropped out when compressing, when generating. Ideally we'd have a\ncouple of presets, i.e., 1/4, 2/4, 3/4, and adhere to them, randomizing\nwhich one we pick.\n\nHaving smaller partial onions would enable my stretch goal of being able\nto chain multiple partial onions, though that might be a useless\nachievement to unlock xD\n\n\u003e\u003e Compute a shared secret using a random ephemeral private key and\n\u003e\u003e `RV`s public key, and then generate a prefill-key\n\u003e\n\u003e\n\u003e While implementing, I felt that the part about the shared secret used\n\u003e to generate the prefill stream is a bit blurry (your proposal on\n\u003e Github doesn't phrase it the same way). I think it's important to\n\u003e stress that this secret is derived from both `ephkey` and `RV`'s\n\u003e private key, so that `RV+1` can't compute the same stream.\n\nI noticed the same while implementing the decompress stage, which\nrequires the node ID from `RV` during generation, and performs ECDH +\nHKDF with the `RV` node private and the ephemeral key in the *next*\nonion, i.e., the one extracted from the payload itself. This is\nnecessary since the ephemeral key on the incoming onion, which delivered\nthe partial onion in its payload is not controlled by the partial onion\ncreator, while the one in the partial onion is.\n\nThis means that the ephemeral key in the partial onion is used twice:\n\n - Once by `RV` to generate the obfuscation stream to fill in the gap\n - As part of the reconstructed onion, processed by `RV+1` to decode the\n onion.\n\nI'm convinced this is secure and doesn't leak information since\notherwise transporting the ephemeral key publicly would be insecure\n(`RV+1` can't generate the obfuscation secret used to fill in the gap\nwithout access to `RV`s private key), and the ephemeral key is only\ntransmitted in cleartext once (from `RV` to `RV+1`), otherwise it is\nhidden in the outer onion.\n\n\u003e Another thing that may be worth mentioning is error forwarding. Since\n\u003e the recipient generated the onion, `RV` won't have the shared secrets\n\u003e (that's by design). So it's expected that payment errors won't be\n\u003e readable by `RV`, but it's probably a good idea if `RV` returns an\n\u003e indication to the sender that the payment failed *after* the\n\u003e rendezvous point.\n\nIndeed, this is pretty much by design, since otherwise the sender could\nprovoke errors, e.g., consuming all of `RV`s outgoing capacity with\nprobes to get back temporary channel failure errors for the channel that\nwas encoded in the partial onion, and then do that iteratively until we\nhave identified the real destination which we weren't supposed to learn.\n\nSo any error beyond `RV` should be treated by the sender as \"rendez-vous\nfailed, discard partial onion\".\n\n\u003e An important side-note is that your proposal is really quick and\n\u003e simple to implement from the existing Sphinx code. I have made ASCII\n\u003e diagrams of the scheme (see [1]). This may help readers visualize it\n\u003e more easily.\n\nI quickly skimmed the drawings and they're very nice to understand how\nregions overlap, that was my main problem with the whole sphinx\nconstruction, so thanks for taking the time :+1:\n\n\u003e It still has the issue that each hop's amount/cltv is fixed at invoice\n\u003e generation time by the recipient. That means MPP cannot be used, and\n\u003e if any channel along the path updates their fee the partial onion\n\u003e becomes invalid (unless you overpay the fees).\n\u003e\n\u003e Trampoline should be able to address that since it provides more\n\u003e freedom to each trampoline node to find an efficient way to forward to\n\u003e the next trampoline. It's not yet obvious to me how I can mix these\n\u003e two proposals to make it work though. I'll spend more time\n\u003e experimenting with that.\n\nTrue, I think rendez-vous routing have some use-cases, but routing in\nthe public network seems a bit brittle. It is definitely not MPP\ncompliant since the sphinx constructions says that each shared secret\nshould be blacklisted after use, and if we were to use the partial onion\non multiple path we'd be bound to use the same shared secret for the\nsubpaths contained in the partial onion.\n\nI've been mostly thinking about systems in which you can guarantee\nstability, e.g., in a subnetwork controlled by the recipient, but to\nhide any internal routing decisions. That'd be similar to a supercharged\nrouting hint basically, without revealing the internal structure.\n\nCheers,\nChristian",
"sig": "0e6ebd1fd60e955cb2ecaa7cba2b5a5825f0ade03643695075d1602bc4f98f3b4300b4b456896efbdebc0580f5e38d5b46eedb24df7a1f2f8731a5475a1f6af6"
}