Rusty Russell [ARCHIVE] on Nostr: 📅 Original date posted:2018-02-11 📝 Original message: Christian Decker ...
📅 Original date posted:2018-02-11
📝 Original message:
Christian Decker <decker.christian at gmail.com> writes:
> Rusty Russell <rusty at rustcorp.com.au> writes:
>> Finally catching up. I prefer the simplicity of the timestamp
>> mechanism, with a more ambitious mechanism TBA.
>
> Fabrice and I had a short chat a few days ago and decided that we'll
> simulate both approaches and see what consumes less bandwidth. With
> zombie channels and the chances for missing channels during a weak form
> of synchronization, it's not that clear to us which one has the better
> tradeoff. With some numbers behind it it may become easier to decide :-)
Maybe; I think we'd be best off with an IBLT-approach similar to
Fabrice's proposal. An IBLT is better than a simple hash, since if your
results are similar you can just extract the differences, and they're
easier to maintain. Even easier if we make the boundaries static rather
than now-relative. For node_announce and channel_update you'd probably
want separate IBLTs (perhaps, though not necessarily, as a separate
RTT).
Note that this approach fits really well as a complement to the
timestamp approach: you'd use this for older pre-timestamp, where you're
likely to have a similar idea of channels.
>> Deployment suggestions:
>>
>> 1. This should be a feature bit pair. As usual, even == 'support this or
>> disconnect', and odd == 'ok even if you don't understand'.
>
> If we add the timestamp to the end of the `init` message, instead of
> introducing a new message altogether, we are forced to use the required
> bit, otherwise we just made any future field appended to the `init`
> message unparseable to non-supporting nodes. Let's say we add another
> field to it later, that the peer supports, but it follows the timestamp
> which the peer does not. The peer doesn't know how many bytes to skip
> (if any) for the timestamp bit he doesn't understand, to get to the
> bytes he does know how to parse. I'm slowly getting to like the extra
> message more, since it also allows a number of cute tricks later.
This, of course, is the nature of all appendings. You can't understand
feature N+1 without understanding feature N, if they both append to the
same message.
You don't have to *support* feature N, of course.
>> 2. This `timestamp_routing_sync`? feature overrides `initial_routing_sync`.
>> That lets you decide what old nodes do, using the older
>> `initial_routing_sync` option. Similarly, a future `fancy_sync` would
>> override `timestamp_routing_sync`.
>
> So you'd set both bits, and if the peer knows `timestamp_routing_sync`
> that then force-sets the `initial_routing_sync`? Sounds ok, if we allow
> optional implementations, even though I'd like to avoid feature
> interactions as much as possible.
If we don't allow optional implementations we're breaking the spec. And
we're not going to do that*
[* Yeah, OK, we'll eventually do that. But we'll do it when we're
pretty sure that ~0 users would break, because they'd be ancient ]
>> 3. We can append an optional 4 byte `routing_sync_timestamp` field to to
>> `init` without issues, since all lengths in there are explicit. If you
>> don't offer the `timestamp_sync` feature, this Must Be Zero (for appending
>> more stuff in future).
>
> That'd still require the peer to know that it has to skip 4 bytes to get
> any future fields, which is why I am convinced that either forcing it to
> be mandatory, or adding a new message is the better way to go, even if
> now everybody implements it correctly.
This is simply how we upgrade. See `open_channel` for how this is
already done, for example; in fact, we originally had two different
upgrades (but we broke spec instead) and they used exactly this
technique.
A separate message here is supremely awkward, too.
>> Now, as to the proposal specifics.
>>
>> I dislike the re-transmission of all old channel_announcement and
>> node_announcement messages, just because there's been a recent
>> channel_update. Simpler to just say 'send anything >=
>> routing_sync_timestamp`.
>
> I'm afraid we can't really omit the `channel_announcement` since a
> `channel_update` that isn't preceded by a `channel_announcement` is
> invalid and will be dropped by peers (especially because the
> `channel_update` doesn't contain the necessary information for
> validation).
OTOH this is a rare corner case which will eventually be fixed by weekly
channel_announce retransmission. In particular, the receiver should
have already seen the channel_announce, since it preceeded the timestamp
they asked for.
Presumably IRL you'd ask for a timestamp sometime before you were last
disconnected, say 30 minutes.
"The perfect is the enemy of the good".
>> Background: c-lightning internally keeps an tree of gossip in the order
>> we received them, keeping a 'current' pointer for each peer. This is
>> very efficient (though we don't remember if a peer sent us a gossip msg
>> already, so uses twice the bandwidth it could).
>
> We can solve that by keeping a filter of the messages we received from
> the peer, it's more of an optimization than anything, other than the
> bandwidth cost, it doesn't hurt.
Yes, it's on the TODO somewhere... we should do this!
>> But this isn't *quite* the same as timestamp order, so we can't just set
>> the 'current' pointer based on the first entry >=
>> `routing_sync_timestamp`; we need to actively filter. This is still a
>> simple traverse, however, skipping over any entry less than
>> routing_sync_timestamp.
>>
>> OTOH, if we need to retransmit announcements, when do we stop
>> retransmitting them? If a new channel_update comes in during this time,
>> are we still to dump the announcements? Do we have to remember which
>> ones we've sent to each peer?
>
> That's more of an implementation detail. In c-lightning we can just
> remember the index at which the initial sync started, and send
> announcements along until the index is larger than the initial sync
> index.
True. It is an implementation detail which is critical to saving
bandwidth though.
> A more general approach would be to have 2 timestamps, one highwater and
> one lowwater mark. Anything inbetween these marks will be forwarded
> together with all associated announcements (node / channel), anything
> newer than that will only forward the update. The two timestamps
> approach, combined with a new message, would also allow us to send
> multiple `timestamp_routing_sync` messages, e.g., first sync the last
> hour, then the last day, then the last week, etc. It gives the syncing
> node control over what timewindow to send, inverting the current initial
> sync.
That would fit neatly with the more complicated bucketing approaches:
you'd use this technique to ask for the entire bucket if the SHA
mismatched/IBLT failed.
Cheers,
Rusty.
Published at
2023-06-09 12:48:52Event JSON
{
"id": "1ba57c694aa8d283314e454133ea2c005324650de3d4cc88878496e46c4a298e",
"pubkey": "13bd8c1c5e3b3508a07c92598647160b11ab0deef4c452098e223e443c1ca425",
"created_at": 1686314932,
"kind": 1,
"tags": [
[
"e",
"c3f2627a28f3f44c130da7dce36c10040222ba86792d87bfb3e3dcd970958ae9",
"",
"root"
],
[
"e",
"48d512e22c1a5258a23ccd37a043f3e849b6cada90700567cf3f7a5af79d8b33",
"",
"reply"
],
[
"p",
"72cd40332ec782dd0a7f63acb03e3b6fdafa6d91bd1b6125cd8b7117a1bb8057"
]
],
"content": "📅 Original date posted:2018-02-11\n📝 Original message:\nChristian Decker \u003cdecker.christian at gmail.com\u003e writes:\n\u003e Rusty Russell \u003crusty at rustcorp.com.au\u003e writes:\n\u003e\u003e Finally catching up. I prefer the simplicity of the timestamp\n\u003e\u003e mechanism, with a more ambitious mechanism TBA.\n\u003e\n\u003e Fabrice and I had a short chat a few days ago and decided that we'll\n\u003e simulate both approaches and see what consumes less bandwidth. With\n\u003e zombie channels and the chances for missing channels during a weak form\n\u003e of synchronization, it's not that clear to us which one has the better\n\u003e tradeoff. With some numbers behind it it may become easier to decide :-)\n\nMaybe; I think we'd be best off with an IBLT-approach similar to\nFabrice's proposal. An IBLT is better than a simple hash, since if your\nresults are similar you can just extract the differences, and they're\neasier to maintain. Even easier if we make the boundaries static rather\nthan now-relative. For node_announce and channel_update you'd probably\nwant separate IBLTs (perhaps, though not necessarily, as a separate\nRTT).\n\nNote that this approach fits really well as a complement to the\ntimestamp approach: you'd use this for older pre-timestamp, where you're\nlikely to have a similar idea of channels.\n\n\u003e\u003e Deployment suggestions:\n\u003e\u003e\n\u003e\u003e 1. This should be a feature bit pair. As usual, even == 'support this or\n\u003e\u003e disconnect', and odd == 'ok even if you don't understand'.\n\u003e\n\u003e If we add the timestamp to the end of the `init` message, instead of\n\u003e introducing a new message altogether, we are forced to use the required\n\u003e bit, otherwise we just made any future field appended to the `init`\n\u003e message unparseable to non-supporting nodes. Let's say we add another\n\u003e field to it later, that the peer supports, but it follows the timestamp\n\u003e which the peer does not. The peer doesn't know how many bytes to skip\n\u003e (if any) for the timestamp bit he doesn't understand, to get to the\n\u003e bytes he does know how to parse. I'm slowly getting to like the extra\n\u003e message more, since it also allows a number of cute tricks later.\n\nThis, of course, is the nature of all appendings. You can't understand\nfeature N+1 without understanding feature N, if they both append to the\nsame message.\n\nYou don't have to *support* feature N, of course.\n\n\u003e\u003e 2. This `timestamp_routing_sync`? feature overrides `initial_routing_sync`.\n\u003e\u003e That lets you decide what old nodes do, using the older\n\u003e\u003e `initial_routing_sync` option. Similarly, a future `fancy_sync` would\n\u003e\u003e override `timestamp_routing_sync`.\n\u003e\n\u003e So you'd set both bits, and if the peer knows `timestamp_routing_sync`\n\u003e that then force-sets the `initial_routing_sync`? Sounds ok, if we allow\n\u003e optional implementations, even though I'd like to avoid feature\n\u003e interactions as much as possible.\n\nIf we don't allow optional implementations we're breaking the spec. And\nwe're not going to do that*\n\n[* Yeah, OK, we'll eventually do that. But we'll do it when we're\n pretty sure that ~0 users would break, because they'd be ancient ]\n\n\u003e\u003e 3. We can append an optional 4 byte `routing_sync_timestamp` field to to\n\u003e\u003e `init` without issues, since all lengths in there are explicit. If you\n\u003e\u003e don't offer the `timestamp_sync` feature, this Must Be Zero (for appending\n\u003e\u003e more stuff in future).\n\u003e\n\u003e That'd still require the peer to know that it has to skip 4 bytes to get\n\u003e any future fields, which is why I am convinced that either forcing it to\n\u003e be mandatory, or adding a new message is the better way to go, even if\n\u003e now everybody implements it correctly.\n\nThis is simply how we upgrade. See `open_channel` for how this is\nalready done, for example; in fact, we originally had two different\nupgrades (but we broke spec instead) and they used exactly this\ntechnique.\n\nA separate message here is supremely awkward, too.\n\n\u003e\u003e Now, as to the proposal specifics.\n\u003e\u003e\n\u003e\u003e I dislike the re-transmission of all old channel_announcement and\n\u003e\u003e node_announcement messages, just because there's been a recent\n\u003e\u003e channel_update. Simpler to just say 'send anything \u003e=\n\u003e\u003e routing_sync_timestamp`.\n\u003e\n\u003e I'm afraid we can't really omit the `channel_announcement` since a\n\u003e `channel_update` that isn't preceded by a `channel_announcement` is\n\u003e invalid and will be dropped by peers (especially because the\n\u003e `channel_update` doesn't contain the necessary information for\n\u003e validation).\n\nOTOH this is a rare corner case which will eventually be fixed by weekly\nchannel_announce retransmission. In particular, the receiver should\nhave already seen the channel_announce, since it preceeded the timestamp\nthey asked for.\n\nPresumably IRL you'd ask for a timestamp sometime before you were last\ndisconnected, say 30 minutes.\n\n\"The perfect is the enemy of the good\".\n\n\u003e\u003e Background: c-lightning internally keeps an tree of gossip in the order\n\u003e\u003e we received them, keeping a 'current' pointer for each peer. This is\n\u003e\u003e very efficient (though we don't remember if a peer sent us a gossip msg\n\u003e\u003e already, so uses twice the bandwidth it could).\n\u003e\n\u003e We can solve that by keeping a filter of the messages we received from\n\u003e the peer, it's more of an optimization than anything, other than the\n\u003e bandwidth cost, it doesn't hurt.\n\nYes, it's on the TODO somewhere... we should do this!\n\n\u003e\u003e But this isn't *quite* the same as timestamp order, so we can't just set\n\u003e\u003e the 'current' pointer based on the first entry \u003e=\n\u003e\u003e `routing_sync_timestamp`; we need to actively filter. This is still a\n\u003e\u003e simple traverse, however, skipping over any entry less than\n\u003e\u003e routing_sync_timestamp.\n\u003e\u003e\n\u003e\u003e OTOH, if we need to retransmit announcements, when do we stop\n\u003e\u003e retransmitting them? If a new channel_update comes in during this time,\n\u003e\u003e are we still to dump the announcements? Do we have to remember which\n\u003e\u003e ones we've sent to each peer?\n\u003e\n\u003e That's more of an implementation detail. In c-lightning we can just\n\u003e remember the index at which the initial sync started, and send\n\u003e announcements along until the index is larger than the initial sync\n\u003e index.\n\nTrue. It is an implementation detail which is critical to saving\nbandwidth though.\n\n\u003e A more general approach would be to have 2 timestamps, one highwater and\n\u003e one lowwater mark. Anything inbetween these marks will be forwarded\n\u003e together with all associated announcements (node / channel), anything\n\u003e newer than that will only forward the update. The two timestamps\n\u003e approach, combined with a new message, would also allow us to send\n\u003e multiple `timestamp_routing_sync` messages, e.g., first sync the last\n\u003e hour, then the last day, then the last week, etc. It gives the syncing\n\u003e node control over what timewindow to send, inverting the current initial\n\u003e sync.\n\nThat would fit neatly with the more complicated bucketing approaches:\nyou'd use this technique to ask for the entire bucket if the SHA\nmismatched/IBLT failed.\n\nCheers,\nRusty.",
"sig": "c20a3098531df3a124fda6a4d30cf76c2ca43491947117a182f95acbf9d3c126b88d91fb664ae4a71fd96ae79ac4a3783d1ec073e42f5dab6cdabc6113039ae0"
}