-
Notifications
You must be signed in to change notification settings - Fork 46
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
A question about the invariant of kademlia #30
Comments
This is done via Node.fillBuckets() |
Thanks for the reply. But IMHO |
When a node joins it does an iterative lookup from a distant vantage point, which means it'll traverse, bit by bit, towards the home ID. And since buckets are only split when there would be more than 8 entries per bucket this statistically means that after the split both siblings will have entries most of the time (rather than requiring a double-split), which in turn means most intermediate buckets between the home ID and the most distant ones generally get populated with some entries, which then triggers the fill to do the remainder. Additionally incoming requests will go into the replacement bucket, get pinged and promoted on success. So in practice it does fill up buckets if peers exist in those keyspace ranges. But you're right that it does not ensure this eagerly. I used to have the eager variant in the code, but if I recall correctly this lead to excessive fill attempts when malicious peers temporarily made it into the routing table and caused deep splits. Perhaps the mitigation is a bit blunt and could be reconsidered since I have implemented better defenses since then, but based on observing routing tables of deployed instances buckets do get filled as I expect them to be. |
Thanks again! I understand your concern for malicious peers. But I think the iterative lookup from a distant vantage point won't cover entire keyspace ranges. Suppose the |
The most distant bucket covers 50% of the keyspace and gets populated quickly with high probability so "distant vantage point" generally means 0 shared prefix bits. |
Oh I see. It seems the problem becomes how to ensure the It also seems that a deliberate lookup for a node in the 0 shared prefix bit space will do, but I didn't find such logic in the code -_-b |
This is governed by the NodeLookup.isBootstrap flag |
Awesome ! It's a great piece of work, thanks! |
I'm still thinking about the iterative lookup from a distant vantage point(a node with 0 shared prefix bits), and found that it may not "traverse, bit by bit, towards the home ID", but rather by a step of 1 bit ( |
You have to consider that the lookups contact multiple nodes in parallel and are repeated over time. But sure, this is all probabilistic. Perhaps a cleaner and more reliable approach would be to start filling the most remote bucket if it isn't already, if that succeeds then fill the second-furthest bucket and so on until a lookup doesn't manage to fill a bucket, then stop the filling procedure. This would probably solve the overzealousness problem of the current |
The invariant of kademlia requires that every k-bucket of every node contains at least one contact if a node exists in the appropriate range.
This may not be guaranteed when a node bootstrap, I checked the code and find the bootstrap calls
routerBootstrap
orfillHomeBuckets
based on the peers count in the routing table, the main difference is the id to lookup(Key.createRandomKey()
orsrv.getDerivedID()
), but it doesn't seem obvious how this will guarantee the invariant, is there anything I'm missing?The text was updated successfully, but these errors were encountered: