-
Notifications
You must be signed in to change notification settings - Fork 402
Randomize user_channel_id
for inbound channels
#1790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Randomize user_channel_id
for inbound channels
#1790
Conversation
Codecov ReportBase: 90.77% // Head: 91.67% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #1790 +/- ##
==========================================
+ Coverage 90.77% 91.67% +0.90%
==========================================
Files 87 89 +2
Lines 47595 55343 +7748
Branches 47595 55343 +7748
==========================================
+ Hits 43204 50737 +7533
- Misses 4391 4606 +215
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
Hmm, this is a bit awkward, given we require the user to pass an ID for outbound channel, but it gets picked at random for inbound ones? We run some risk of colliding, even if its not super high. Ideally we'd increment rather than randomize, and keep track of the last one for outbounds, if we want to do this. Do note that users can always set their own incrementing IDs if they do manual channel acceptance. |
Oh, no, I guess incrementing is inherintly race-y, we can't do that. Ugh, I guess we can randomize, but I feel really bad doing something that users may rely on (randomization being unique always) and then having it randomly fail. If its okay with your use-case it'd be nice to just have you rely on the manual acceptance, rather than relying on upstream. |
Hm, but are we really worried about a collision in an 64-bit identifier space for a non security critical feature? Especially since currently the default behavior to have a collision in ~50% of cases? Also, correct me if I'm wrong, but I couldn't find any part of the code where we would rely on the So I'd argue randomization is just a plain improvement over the status quo, even though you are correct, there is a negligible chance of collisions. That said, if we were to have a |
I would definitely call it "security critical", having users get confused between different channels definitely sounds like a potentially critical issue. That said, maybe we don't need to care? Mentally, my model is always (a) 32-bit -> dont use, (b) 64-bit -> fine for counters, even if a counterparty can cause you to increment it at a high rate, which they can here, (c) 128-bit -> fine if you dont want to care about collisions, (d) 256-bit -> just do it. But, in this case, 64-bit random numbers - if a counterparty is generating random inbound channels to try to cause collision, after 100million channels you still only have a ~0.02-0.03% chance of collisions. Its not impossible, but very very low, maybe sufficient that it will never happen in prod anywhere.
I think this is the wrong way of thinking about it - if there is a low-but-possible-edge-case of collisions, we'd rather cause collisions to be the "norm" so that users either handle it or avoid it via manual acceptance. Super rare bugs that could cause issues are worse than making it the "norm" where devs will see it during testing. |
Right, and it's not as if channel creation is a high-frequency action for which we blast through 100million events.
It's not as if we force users to supply their own identifiers, we simply notify them in the docs that the identifiers are all 0. |
If there's an attack with duplicate IDs, it absolutely is - a node can send
I don't understand this - if a user relies on the IDs being unique, they won't just hit it in prod, they'll hit it in their third day of testing, at the latest. Collisions you'll never hit in testing. |
That's quite optimistic. To me that sounds like the kind of bug that could easily slip through eventually. Also we still could have a note there explaining the risk and that users should roll their own IDs if possible, just that the default would be just a bit saner. |
Oh? Getting a second inbound channel from the LSP seems like something that any dev working with an LSP would test? In any case, maybe all of this just means our |
I would feel much more comfortable here if its something normally used as unique identifier in high scale systems, for example something like uuid which is 128-bit and regularly used as key in database systems at very high scale. |
Alright, so why not simply switch the
|
I'm fine with that. Sadly its not "trivially backwards compatible" because TLV reads must read the full expected byte count, so we'll need to write a separate "high bits" TLV. |
Yeah, figured so too, which is why there is no mention of "trivially backwards compatible" in above post anymore 😁 |
43403bf
to
1150480
Compare
Ah, I was responding to the email/initial copy, which was edited out from under me :) |
I think this fixes fuzz CI:
|
1150480
to
eacf4ef
Compare
Thanks, I should start to remember that. 🙏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after squash
eacf4ef
to
d26e4b5
Compare
Squashed commits. |
LGTM, feel free to squash. |
@@ -463,6 +463,7 @@ macro_rules! impl_writeable_primitive { | |||
} | |||
} | |||
|
|||
impl_writeable_primitive!(u128, 16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, so we should remove this - note that you broke backwards compat on the ChannelDetails
serialization. It'd be very nice to be able to avoid breaking out the macro for this, though...Maybe we define a new macro read type that's, like, custom_adapter and has a conversion method? Ugh...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LMK if you want me to take a look at this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working on it, will give an update ASAP. Still not sure if it won't be easier to break the macro though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline I explored a number of approaches, e.g., utilizing a custom adapter in conjunction with handing through a decode_custom_tlv
function. They seemed to be almost working on the decoding end (but don't really), and the encoding end is even trickier. Open for any suggestions how to move forward on this, otherwise I now broke the macro and now do custom de/ser as of 3a7bd26.
80699d9
to
d06e17b
Compare
Rebased on main after #1743 was merged. |
d06e17b
to
5093eba
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, thought about it more, I don't think we should try to shove the whole split-int thing into the broader impl_writeable_tlv_based
macro, but we I think there's at least one option for cleaning this up below.
3a7bd26
to
8899a83
Compare
We introduce a new macro that inits and reads tlv fields and DRY up `impl_writeable_tlv_based` and other macros.
Previously, all inbound channels defaulted to a `user_channel_id` of 0, which didn't allow for them being discerned on that basis. Here, we simply randomize the identifier to fix this and enable the use of `user_channel_id` as a true identifier for channels (assuming an equally reasonable value is chosen for outbound channels and given upon `create_channel()`).
8899a83
to
a2616a9
Compare
There are still a handful of incorrect docs in |
7371a52
to
d458fa8
Compare
Whoops, updated the docs. |
Feel free to squash, IMO. |
We increase the `user_channel_id` type from `u64` to `u128`. In order to maintain backwards compatibility, we have to de-/serialize it as two separate `u64`s in `Event` as well as in the `Channel` itself.
d458fa8
to
dc3ff54
Compare
Squashed without further changes. |
@@ -632,13 +632,13 @@ pub enum Event { | |||
/// The `user_channel_id` value passed in to [`ChannelManager::create_channel`] for outbound | |||
/// channels, or to [`ChannelManager::accept_inbound_channel`] for inbound channels if | |||
/// [`UserConfig::manually_accept_inbound_channels`] config flag is set to true. Otherwise | |||
/// `user_channel_id` will be 0 for an inbound channel. | |||
/// `user_channel_id` will be randomized for an inbound channel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big deal, but could say that the version it starts being randomized in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will make sure to include it in a follow-up, probably when having a look at #1800!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in #1855.
Gonna merge, will let @tnull tackle #1790 (comment) in a followup if desired. |
Previously, all inbound channels defaulted to a
user_channel_id
of 0, which didn't allow for them being discerned on that basis. Here, we simply randomize the identifier to fix this and enable the use ofuser_channel_id
as a true identifier for channels (assuming an equally reasonable value is chosen for outbound channels and given uponcreate_channel()
).