# Modular DHT - High Level Package Design This idea draws some inspiration for package design from Go's [fs](https://pkg.go.dev/io/fs) package. The principle here is that key algorithms are implemented as free functions ([Glob](https://pkg.go.dev/io/fs#Glob), [ReadFile](https://pkg.go.dev/io/fs#ReadFile), [WalkDir](https://pkg.go.dev/io/fs#WalkDir)) that act on a simple data type interface ([FS](https://pkg.go.dev/io/fs#FS)). The interface can be specialised for more efficient implementations of the generic algorithm. For example the `ReadFile` function tests whether the passed `FS` implements the [ReadFileFS](https://pkg.go.dev/io/fs#ReadFileFS) interfacce and, if so, calls the optimized `ReadFile` method on the passed type. ## DHT Package The key algorithms for the DHT package are: ```Go func FindPeer(ctx context.Context, t DHT, p peer.ID) (peer.AddrInfo, error) ``` If `t` implements `FindPeerDHT`, `FindPeer` calls `t.FindPeer`. Otherwise `FindPeer` calls `t.FindClosestPeers` recursively until the peer is found. ```Go func GetValue(ctx context.Context, t DHT, key string, q int) (*Record, error) ``` If `t` implements `ValueDHT`, `FindPeer` calls `t.GetValue`. Otherwise `GetValue` calls `t.FindClosestPeers` recursively until `q` values that agree have been returned (a quorum). ```Go func SetValue(ctx context.Context, t DHT, key string, r *Record) error ``` If `t` implements `ValueDHT`, `FindPeer` calls `t.SetValue`. Otherwise `SetValue` calls `t.FindClosestPeers` recursively until `k` peers have been found then invokes the `PUT_VALUE` RPC on each discovered peer. ```Go func FindFeaturePeers(ctx context.Context, t DHT, f feature.ID, n int) ([]peer.AddrInfo, error) ``` `FindFeaturePeers` calls `t.FindClosestPeers` recursively until `n` peers have been found that support the given feature. The fundamental type is `DHT`: ```Go type DHT interface { FindClosestPeers(ctx context.Context, key string, n int) ([]peer.AddrInfo, error) } ``` Some specialized DHT interfaces that allow implementations to provide optimized versions of algorithms: ```Go type FindPeerDHT interface { DHT FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) } ``` ```Go type ValueDHT interface { DHT GetValue(ctx context.Context, key string, q int) (*Record, error) SetValue(ctx context.Context, key string, r *Record) error } ``` ## IPFS Feature Package The ipfs feature package provides IPFS-specific protocol features using the types and algorithms provided by the DHT package. ```Go func FindProviders(ctx context.Context, t DHT, c cid.Cid) ([]peer.AddrInfo, error) ``` If `t` implements `FindProvidersDHT`, `FindProviders` calls `t.FindProviders`. Otherwise `FindProviders` calls `t.FindFeaturePeers` passing the `IPFSGetProviders` feature and sends the RPC `GET_PROVIDERS` to the peers recursively until enough provider peers are found. ```Go func Provide(ctx context.Context, t DHT, p peer.ID, c cid.Cid) error ``` If `t` implements `ProvideDHT`, `Provide` calls `t.Provide`. Otherwise `Provide` calls `t.FindFeaturePeers` with the `IPFSProvide` feature and sends the RPC `ADD_PROVIDER` to the discovered peers. FindProvidersDHT allows DHT implementations to signal that they have an optimized version of the FindProviders algorithm. ```Go type FindProvidersDHT interface { dht.DHT FindProviders(ctx context.Context, c cid.Cid) ([]peer.AddrInfo, error) } ``` ProvideDHT allows DHT implementations to signal that they have an optimized version of the Provide algorithm. ```Go type ProvideDHT interface { dht.DHT Provide(ctx context.Context, p peer.ID, c cid.Cid) error } ```