@@ -2,10 +2,12 @@ package dht
22
33import (
44 "fmt"
5+ "github.com/ipfs/go-ipns"
56 "time"
67
78 ds "github.com/ipfs/go-datastore"
89 dssync "github.com/ipfs/go-datastore/sync"
10+ "github.com/libp2p/go-libp2p-core/host"
911 "github.com/libp2p/go-libp2p-core/network"
1012 "github.com/libp2p/go-libp2p-core/peer"
1113 "github.com/libp2p/go-libp2p-core/protocol"
@@ -29,17 +31,18 @@ const DefaultPrefix protocol.ID = "/ipfs"
2931
3032// Options is a structure containing all the options that can be used when constructing a DHT.
3133type config struct {
32- datastore ds.Batching
33- validator record.Validator
34- mode ModeOpt
35- protocolPrefix protocol.ID
36- bucketSize int
37- concurrency int
38- resiliency int
39- maxRecordAge time.Duration
40- enableProviders bool
41- enableValues bool
42- queryPeerFilter QueryFilterFunc
34+ datastore ds.Batching
35+ validator record.Validator
36+ validatorChanged bool // if true implies that the validator has been changed and that defaults should not be used
37+ mode ModeOpt
38+ protocolPrefix protocol.ID
39+ bucketSize int
40+ concurrency int
41+ resiliency int
42+ maxRecordAge time.Duration
43+ enableProviders bool
44+ enableValues bool
45+ queryPeerFilter QueryFilterFunc
4346
4447 routingTable struct {
4548 refreshQueryTimeout time.Duration
@@ -67,6 +70,25 @@ func (c *config) apply(opts ...Option) error {
6770 return nil
6871}
6972
73+ // applyFallbacks sets default values that could not be applied during config creation since they are dependent
74+ // on other configuration parameters (e.g. optA is by default 2x optB) and/or on the Host
75+ func (c * config ) applyFallbacks (h host.Host ) error {
76+ if ! c .validatorChanged {
77+ nsval , ok := c .validator .(record.NamespacedValidator )
78+ if ok {
79+ if _ , pkFound := nsval ["pk" ]; ! pkFound {
80+ nsval ["pk" ] = record.PublicKeyValidator {}
81+ }
82+ if _ , ipnsFound := nsval ["ipns" ]; ! ipnsFound {
83+ nsval ["ipns" ] = ipns.Validator {KeyBook : h .Peerstore ()}
84+ }
85+ } else {
86+ return fmt .Errorf ("the default validator was changed without being marked as changed" )
87+ }
88+ }
89+ return nil
90+ }
91+
7092// Option DHT option type.
7193type Option func (* config ) error
7294
@@ -75,9 +97,7 @@ const defaultBucketSize = 20
7597// defaults are the default DHT options. This option will be automatically
7698// prepended to any options you pass to the DHT constructor.
7799var defaults = func (o * config ) error {
78- o .validator = record.NamespacedValidator {
79- "pk" : record.PublicKeyValidator {},
80- }
100+ o .validator = record.NamespacedValidator {}
81101 o .datastore = dssync .MutexWrap (ds .NewMapDatastore ())
82102 o .protocolPrefix = DefaultPrefix
83103 o .enableProviders = true
@@ -101,23 +121,39 @@ var defaults = func(o *config) error {
101121}
102122
103123func (c * config ) validate () error {
104- if c .protocolPrefix == DefaultPrefix {
105- if c .bucketSize != defaultBucketSize {
106- return fmt .Errorf ("protocol prefix %s must use bucket size %d" , DefaultPrefix , defaultBucketSize )
107- }
108- if ! c .enableProviders {
109- return fmt .Errorf ("protocol prefix %s must have providers enabled" , DefaultPrefix )
110- }
111- if ! c .enableValues {
112- return fmt .Errorf ("protocol prefix %s must have values enabled" , DefaultPrefix )
113- }
114- if nsval , ok := c .validator .(record.NamespacedValidator ); ! ok {
115- return fmt .Errorf ("protocol prefix %s must use a namespaced validator" , DefaultPrefix )
116- } else if len (nsval ) > 2 || nsval ["pk" ] == nil || nsval ["ipns" ] == nil {
117- return fmt .Errorf ("protocol prefix %s must support only the /pk and /ipns namespaces" , DefaultPrefix )
118- }
124+ if c .protocolPrefix != DefaultPrefix {
119125 return nil
120126 }
127+ if c .bucketSize != defaultBucketSize {
128+ return fmt .Errorf ("protocol prefix %s must use bucket size %d" , DefaultPrefix , defaultBucketSize )
129+ }
130+ if ! c .enableProviders {
131+ return fmt .Errorf ("protocol prefix %s must have providers enabled" , DefaultPrefix )
132+ }
133+ if ! c .enableValues {
134+ return fmt .Errorf ("protocol prefix %s must have values enabled" , DefaultPrefix )
135+ }
136+
137+ nsval , isNSVal := c .validator .(record.NamespacedValidator )
138+ if ! isNSVal {
139+ return fmt .Errorf ("protocol prefix %s must use a namespaced validator" , DefaultPrefix )
140+ }
141+
142+ if len (nsval ) != 2 {
143+ return fmt .Errorf ("protocol prefix %s must have exactly two namespaced validators - /pk and /ipns" , DefaultPrefix )
144+ }
145+
146+ if pkVal , pkValFound := nsval ["pk" ]; ! pkValFound {
147+ return fmt .Errorf ("protocol prefix %s must support the /pk namespaced validator" , DefaultPrefix )
148+ } else if _ , ok := pkVal .(record.PublicKeyValidator ); ! ok {
149+ return fmt .Errorf ("protocol prefix %s must use the record.PublicKeyValidator for the /pk namespace" , DefaultPrefix )
150+ }
151+
152+ if ipnsVal , ipnsValFound := nsval ["ipns" ]; ! ipnsValFound {
153+ return fmt .Errorf ("protocol prefix %s must support the /ipns namespaced validator" , DefaultPrefix )
154+ } else if _ , ok := ipnsVal .(ipns.Validator ); ! ok {
155+ return fmt .Errorf ("protocol prefix %s must use ipns.Validator for the /ipns namespace" , DefaultPrefix )
156+ }
121157 return nil
122158}
123159
@@ -174,17 +210,25 @@ func Mode(m ModeOpt) Option {
174210
175211// Validator configures the DHT to use the specified validator.
176212//
177- // Defaults to a namespaced validator that can only validate public keys.
213+ // Defaults to a namespaced validator that can validate both public key (under the "pk"
214+ // namespace) and IPNS records (under the "ipns" namespace). Setting the validator
215+ // implies that the user wants to control the validators and therefore the default
216+ // public key and IPNS validators will not be added.
178217func Validator (v record.Validator ) Option {
179218 return func (c * config ) error {
180219 c .validator = v
220+ c .validatorChanged = true
181221 return nil
182222 }
183223}
184224
185225// NamespacedValidator adds a validator namespaced under `ns`. This option fails
186- // if the DHT is not using a `record.NamespacedValidator` as it's validator (it
226+ // if the DHT is not using a `record.NamespacedValidator` as its validator (it
187227// uses one by default but this can be overridden with the `Validator` option).
228+ // Adding a namespaced validator without changing the `Validator` will result in
229+ // adding a new validator in addition to the default public key and IPNS validators.
230+ // The "pk" and "ipns" namespaces cannot be overridden here unless a new `Validator`
231+ // has been set first.
188232//
189233// Example: Given a validator registered as `NamespacedValidator("ipns",
190234// myValidator)`, all records with keys starting with `/ipns/` will be validated
0 commit comments