-
Notifications
You must be signed in to change notification settings - Fork 3
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
prefix lookup implementation #2
base: noot/double-hash
Are you sure you want to change the base?
Changes from 37 commits
cc4e42b
a8900f4
648fd4e
f528622
1fc0b02
681dd33
adda234
8bba3ce
a0577de
6c648f1
063e99e
88d68c7
a9ce60b
5c1eda5
675dfaa
32b9a49
e2434a9
2dcb661
bf1f5b4
780e8b7
af92e26
8abd351
3129f21
d8b4570
ca5e8ca
6a48f02
3708392
6884c30
236de05
3c81d7f
24e8f3b
9a733d2
af9c81c
2415ab3
96cedef
bd3535e
19a3d31
3b82cf8
30979a1
0feb15d
74ff325
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package dht | |
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math" | ||
"math/rand" | ||
|
@@ -149,6 +150,11 @@ type IpfsDHT struct { | |
|
||
// configuration variables for tests | ||
testAddressUpdateProcessing bool | ||
|
||
// length of prefix of keys for provider lookups | ||
// if 0, the whole key is used. | ||
prefixLength int | ||
prefixLengthMu sync.RWMutex | ||
} | ||
|
||
// Assert that IPFS assumptions about interfaces aren't broken. These aren't a | ||
|
@@ -197,6 +203,12 @@ func New(ctx context.Context, h host.Host, options ...Option) (*IpfsDHT, error) | |
return nil, err | ||
} | ||
|
||
dht.prefixLength = cfg.PrefixLookupLength | ||
if dht.prefixLength >= 256 { | ||
// if prefixLength is greater than the hash length, then just look up the whole hash | ||
dht.prefixLength = 0 | ||
} | ||
|
||
dht.testAddressUpdateProcessing = cfg.TestAddressUpdateProcessing | ||
|
||
dht.auto = cfg.Mode | ||
|
@@ -344,7 +356,7 @@ func makeDHT(ctx context.Context, h host.Host, cfg dhtcfg.Config) (*IpfsDHT, err | |
if cfg.ProviderStore != nil { | ||
dht.providerStore = cfg.ProviderStore | ||
} else { | ||
dht.providerStore, err = providers.NewProviderManager(dht.ctx, h.ID(), dht.peerstore, cfg.Datastore) | ||
dht.providerStore, err = providers.NewProviderManager(dht.ctx, h.ID(), h.Peerstore(), cfg.Datastore) | ||
if err != nil { | ||
return nil, fmt.Errorf("initializing default provider manager (%v)", err) | ||
} | ||
|
@@ -419,6 +431,21 @@ func makeRoutingTable(dht *IpfsDHT, cfg dhtcfg.Config, maxLastSuccessfulOutbound | |
return rt, err | ||
} | ||
|
||
// SetPrefixLength sets the prefix length for DHT provider lookups. | ||
func (dht *IpfsDHT) SetPrefixLength(prefixLength int) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no, it's meant to be called externally. I needed this for testing, but thought it could be useful for users of the library also, since the only other way to set the prefix length is at DHT initialization. |
||
if prefixLength > 256 || prefixLength < 0 { | ||
return errors.New("invalid prefix length") | ||
} | ||
|
||
dht.prefixLengthMu.Lock() | ||
if prefixLength == 0 { | ||
prefixLength = 256 | ||
} | ||
dht.prefixLength = prefixLength | ||
dht.prefixLengthMu.Unlock() | ||
return nil | ||
} | ||
|
||
// ProviderStore returns the provider storage object for storing and retrieving provider records. | ||
func (dht *IpfsDHT) ProviderStore() providers.ProviderStore { | ||
return dht.providerStore | ||
|
@@ -685,23 +712,42 @@ func (dht *IpfsDHT) FindLocal(id peer.ID) peer.AddrInfo { | |
} | ||
|
||
// nearestPeersToQuery returns the routing tables closest peers.Digest | ||
func (dht *IpfsDHT) nearestPeersToQuery(pmes *pb.Message, count int) []peer.ID { | ||
key := pmes.GetKey() | ||
func (dht *IpfsDHT) nearestPeersToQuery(pmes *pb.Message, count int) ([]peer.ID, error) { | ||
key := pmes.GetKey().GetKey() | ||
prefixBitLength := pmes.GetKey().GetPrefixBitLength() | ||
|
||
if prefixBitLength != 0 { | ||
key, err := internal.DecodePrefixedKey(key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// prefix lookup | ||
closer := dht.routingTable.NearestPeersToPrefix(kb.ID(string(key)), count) | ||
return closer, nil | ||
} | ||
|
||
// for GET_PROVIDERS messages, or sometimes FIND_NODE messages, | ||
// the message key is the hashed multihash, so don't hash it again | ||
decodedMH, err := multihash.Decode(key) | ||
if err == nil && decodedMH.Code == multihash.DBL_SHA2_256 { | ||
// normal non-prefixed lookup | ||
closer := dht.routingTable.NearestPeers(kb.ID(string(decodedMH.Digest)), count) | ||
return closer | ||
return closer, nil | ||
} | ||
|
||
// non-prefixed, non double-hashed lookup | ||
closer := dht.routingTable.NearestPeers(kb.ConvertKey(string(key)), count) | ||
return closer | ||
return closer, nil | ||
} | ||
|
||
// betterPeersToQuery returns nearestPeersToQuery with some additional filtering | ||
func (dht *IpfsDHT) betterPeersToQuery(pmes *pb.Message, from peer.ID, count int) []peer.ID { | ||
closer := dht.nearestPeersToQuery(pmes, count) | ||
closer, err := dht.nearestPeersToQuery(pmes, count) | ||
if err != nil { | ||
logger.Errorf("key decoding error: %w", err) | ||
return nil | ||
} | ||
|
||
// no node? nil | ||
if closer == nil { | ||
|
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.
General question: Is the prefix length set globally for the
kubo
node, or can it be changed for each request (e.g with Options, or argument)?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.
it can be changed for each request by calling
SetPrefixLength
right before the lookup. Another option I just thought of (that might be nicer API-wise?) would be to create an option specifically for theFindProviders
function that the caller can optionally pass in. what do you think?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.
Yeah, that would be awesome if the prefix can be set on a per request basis, with a global default value (either static e.g taken from the conf, or adaptive) for if the option isn't specifically set.