# 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
}
```