Skip to content

Commit 067f8ab

Browse files
authored
Merge pull request #560 from libp2p/feat/ipns-default
Set record handlers for the default protocol prefix
2 parents 4a4e60e + 79296fb commit 067f8ab

File tree

4 files changed

+86
-31
lines changed

4 files changed

+86
-31
lines changed

dht.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ func New(ctx context.Context, h host.Host, options ...Option) (*IpfsDHT, error)
135135
if err := cfg.apply(append([]Option{defaults}, options...)...); err != nil {
136136
return nil, err
137137
}
138+
if err := cfg.applyFallbacks(h); err != nil {
139+
return nil, err
140+
}
138141

139142
if err := cfg.validate(); err != nil {
140143
return nil, err

dht_options.go

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package dht
22

33
import (
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.
3133
type 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.
7193
type 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.
7799
var 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

103123
func (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.
178217
func 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

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/ipfs/go-datastore v0.4.4
1212
github.com/ipfs/go-detect-race v0.0.1
1313
github.com/ipfs/go-ipfs-util v0.0.1
14+
github.com/ipfs/go-ipns v0.0.2
1415
github.com/ipfs/go-log v1.0.3
1516
github.com/jbenet/goprocess v0.1.4
1617
github.com/libp2p/go-eventbus v0.1.0

go.sum

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU=
105105
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
106106
github.com/ipfs/go-datastore v0.0.1 h1:AW/KZCScnBWlSb5JbnEnLKFWXL224LBEh/9KXXOrUms=
107107
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
108+
github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
109+
github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
108110
github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA=
109111
github.com/ipfs/go-datastore v0.4.1 h1:W4ZfzyhNi3xmuU5dQhjfuRn/wFuqEE1KnOmmQiOevEY=
110112
github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA=
@@ -114,12 +116,16 @@ github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ
114116
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
115117
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
116118
github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s=
119+
github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
117120
github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE=
118121
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
122+
github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8=
119123
github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s=
120124
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
121125
github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
122126
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
127+
github.com/ipfs/go-ipns v0.0.2 h1:oq4ErrV4hNQ2Eim257RTYRgfOSV/s8BDaf9iIl4NwFs=
128+
github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U=
123129
github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc=
124130
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
125131
github.com/ipfs/go-log v1.0.2 h1:s19ZwJxH8rPWzypjcDpqPLIyV7BnbLqvpli3iZoqYK0=
@@ -247,6 +253,7 @@ github.com/libp2p/go-libp2p-peerstore v0.1.0 h1:MKh7pRNPHSh1fLPj8u/M/s/napdmeNpo
247253
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
248254
github.com/libp2p/go-libp2p-peerstore v0.1.3 h1:wMgajt1uM2tMiqf4M+4qWKVyyFc8SfA+84VV9glZq1M=
249255
github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI=
256+
github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs=
250257
github.com/libp2p/go-libp2p-peerstore v0.2.0 h1:XcgJhI8WyUOCbHyRLNEX5542YNj8hnLSJ2G1InRjDhk=
251258
github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ=
252259
github.com/libp2p/go-libp2p-peerstore v0.2.1 h1:u+gOfsKgu73ZkGWhvckRm03z9C+iS9TrLqpANweELGs=

0 commit comments

Comments
 (0)