core: deprecate CoreAPI.Dht, introduce CoreAPI.Routing
Henrique Dias committed
Jan 31, 2024 at 11:07 UTC
80973d87ccc189b3a23b01c1f02dbca4a840b462
18 files changed
+541
-470
client/rpc/api.go
+2
@@ -227,6 +227,8 @@ func (api *HttpApi) Object() iface.ObjectAPI {
227
return (*ObjectAPI)(api)
228
}
229
230
+// nolint deprecated
231
+// Deprecated: use [HttpApi.Routing] instead.
232
func (api *HttpApi) Dht() iface.DhtAPI {
233
return (*DhtAPI)(api)
234
}
client/rpc/dht.go
+9
-89
@@ -2,110 +2,30 @@ package rpc
2
3
import (
4
"context"
5
- "encoding/json"
5
6
"github.com/ipfs/boxo/path"
7
caopts "github.com/ipfs/kubo/core/coreiface/options"
8
"github.com/libp2p/go-libp2p/core/peer"
10
- "github.com/libp2p/go-libp2p/core/routing"
9
)
10
11
type DhtAPI HttpApi
12
13
+// nolint deprecated
14
+// Deprecated: use [RoutingAPI.FindPeer] instead.
15
func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
16
- var out struct {
17
- Type routing.QueryEventType
18
- Responses []peer.AddrInfo
19
- }
20
- resp, err := api.core().Request("dht/findpeer", p.String()).Send(ctx)
21
- if err != nil {
22
- return peer.AddrInfo{}, err
23
- }
24
- if resp.Error != nil {
25
- return peer.AddrInfo{}, resp.Error
26
- }
27
- defer resp.Close()
28
- dec := json.NewDecoder(resp.Output)
29
- for {
30
- if err := dec.Decode(&out); err != nil {
31
- return peer.AddrInfo{}, err
32
- }
33
- if out.Type == routing.FinalPeer {
34
- return out.Responses[0], nil
35
- }
36
- }
16
+ return api.core().Routing().FindPeer(ctx, p)
17
}
18
19
+// nolint deprecated
20
+// Deprecated: use [RoutingAPI.FindProviders] instead.
21
func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.DhtFindProvidersOption) (<-chan peer.AddrInfo, error) {
40
- options, err := caopts.DhtFindProvidersOptions(opts...)
41
- if err != nil {
42
- return nil, err
43
- }
44
-
45
- rp, _, err := api.core().ResolvePath(ctx, p)
46
- if err != nil {
47
- return nil, err
48
- }
49
-
50
- resp, err := api.core().Request("dht/findprovs", rp.RootCid().String()).
51
- Option("num-providers", options.NumProviders).
52
- Send(ctx)
53
- if err != nil {
54
- return nil, err
55
- }
56
- if resp.Error != nil {
57
- return nil, resp.Error
58
- }
59
- res := make(chan peer.AddrInfo)
60
-
61
- go func() {
62
- defer resp.Close()
63
- defer close(res)
64
- dec := json.NewDecoder(resp.Output)
65
-
66
- for {
67
- var out struct {
68
- Extra string
69
- Type routing.QueryEventType
70
- Responses []peer.AddrInfo
71
- }
72
-
73
- if err := dec.Decode(&out); err != nil {
74
- return // todo: handle this somehow
75
- }
76
- if out.Type == routing.QueryError {
77
- return // usually a 'not found' error
78
- // todo: handle other errors
79
- }
80
- if out.Type == routing.Provider {
81
- for _, pi := range out.Responses {
82
- select {
83
- case res <- pi:
84
- case <-ctx.Done():
85
- return
86
- }
87
- }
88
- }
89
- }
90
- }()
91
-
92
- return res, nil
22
+ return api.core().Routing().FindProviders(ctx, p, opts...)
23
}
24
25
+// nolint deprecated
26
+// Deprecated: use [RoutingAPI.Provide] instead.
27
func (api *DhtAPI) Provide(ctx context.Context, p path.Path, opts ...caopts.DhtProvideOption) error {
96
- options, err := caopts.DhtProvideOptions(opts...)
97
- if err != nil {
98
- return err
99
- }
100
-
101
- rp, _, err := api.core().ResolvePath(ctx, p)
102
- if err != nil {
103
- return err
104
- }
105
-
106
- return api.core().Request("dht/provide", rp.RootCid().String()).
107
- Option("recursive", options.Recursive).
108
- Exec(ctx, nil)
28
+ return api.core().Routing().Provide(ctx, p, opts...)
29
}
30
31
func (api *DhtAPI) core() *HttpApi {
client/rpc/routing.go
+98
@@ -6,7 +6,9 @@ import (
6
"encoding/base64"
7
"encoding/json"
8
9
+ "github.com/ipfs/boxo/path"
10
"github.com/ipfs/kubo/core/coreiface/options"
11
+ "github.com/libp2p/go-libp2p/core/peer"
12
"github.com/libp2p/go-libp2p/core/routing"
13
)
14
@@ -58,6 +60,102 @@ func (api *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts .
60
return nil
61
}
62
63
+func (api *RoutingAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
64
+ var out struct {
65
+ Type routing.QueryEventType
66
+ Responses []peer.AddrInfo
67
+ }
68
+ resp, err := api.core().Request("routing/findpeer", p.String()).Send(ctx)
69
+ if err != nil {
70
+ return peer.AddrInfo{}, err
71
+ }
72
+ if resp.Error != nil {
73
+ return peer.AddrInfo{}, resp.Error
74
+ }
75
+ defer resp.Close()
76
+ dec := json.NewDecoder(resp.Output)
77
+ for {
78
+ if err := dec.Decode(&out); err != nil {
79
+ return peer.AddrInfo{}, err
80
+ }
81
+ if out.Type == routing.FinalPeer {
82
+ return out.Responses[0], nil
83
+ }
84
+ }
85
+}
86
+
87
+func (api *RoutingAPI) FindProviders(ctx context.Context, p path.Path, opts ...options.RoutingFindProvidersOption) (<-chan peer.AddrInfo, error) {
88
+ options, err := options.RoutingFindProvidersOptions(opts...)
89
+ if err != nil {
90
+ return nil, err
91
+ }
92
+
93
+ rp, _, err := api.core().ResolvePath(ctx, p)
94
+ if err != nil {
95
+ return nil, err
96
+ }
97
+
98
+ resp, err := api.core().Request("routing/findprovs", rp.RootCid().String()).
99
+ Option("num-providers", options.NumProviders).
100
+ Send(ctx)
101
+ if err != nil {
102
+ return nil, err
103
+ }
104
+ if resp.Error != nil {
105
+ return nil, resp.Error
106
+ }
107
+ res := make(chan peer.AddrInfo)
108
+
109
+ go func() {
110
+ defer resp.Close()
111
+ defer close(res)
112
+ dec := json.NewDecoder(resp.Output)
113
+
114
+ for {
115
+ var out struct {
116
+ Extra string
117
+ Type routing.QueryEventType
118
+ Responses []peer.AddrInfo
119
+ }
120
+
121
+ if err := dec.Decode(&out); err != nil {
122
+ return // todo: handle this somehow
123
+ }
124
+ if out.Type == routing.QueryError {
125
+ return // usually a 'not found' error
126
+ // todo: handle other errors
127
+ }
128
+ if out.Type == routing.Provider {
129
+ for _, pi := range out.Responses {
130
+ select {
131
+ case res <- pi:
132
+ case <-ctx.Done():
133
+ return
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }()
139
+
140
+ return res, nil
141
+}
142
+
143
+func (api *RoutingAPI) Provide(ctx context.Context, p path.Path, opts ...options.RoutingProvideOption) error {
144
+ options, err := options.RoutingProvideOptions(opts...)
145
+ if err != nil {
146
+ return err
147
+ }
148
+
149
+ rp, _, err := api.core().ResolvePath(ctx, p)
150
+ if err != nil {
151
+ return err
152
+ }
153
+
154
+ return api.core().Request("routing/provide", rp.RootCid().String()).
155
+ Option("recursive", options.Recursive).
156
+ Exec(ctx, nil)
157
+}
158
+
159
func (api *RoutingAPI) core() *HttpApi {
160
return (*HttpApi)(api)
161
}
core/coreapi/coreapi.go
+2
-1
@@ -130,7 +130,8 @@ func (api *CoreAPI) Pin() coreiface.PinAPI {
130
return (*PinAPI)(api)
131
}
132
133
-// Dht returns the DhtAPI interface implementation backed by the go-ipfs node
133
+// nolint deprecated
134
+// Deprecated: use [CoreAPI.Routing] instead.
135
func (api *CoreAPI) Dht() coreiface.DhtAPI {
136
return (*DhtAPI)(api)
137
}
core/coreapi/dht.go
+10
-130
@@ -2,151 +2,31 @@ package coreapi
2
3
import (
4
"context"
5
- "fmt"
5
7
- blockservice "github.com/ipfs/boxo/blockservice"
8
- blockstore "github.com/ipfs/boxo/blockstore"
9
- offline "github.com/ipfs/boxo/exchange/offline"
10
- dag "github.com/ipfs/boxo/ipld/merkledag"
6
"github.com/ipfs/boxo/path"
12
- cid "github.com/ipfs/go-cid"
13
- cidutil "github.com/ipfs/go-cidutil"
7
coreiface "github.com/ipfs/kubo/core/coreiface"
8
caopts "github.com/ipfs/kubo/core/coreiface/options"
16
- "github.com/ipfs/kubo/tracing"
9
peer "github.com/libp2p/go-libp2p/core/peer"
18
- routing "github.com/libp2p/go-libp2p/core/routing"
19
- "go.opentelemetry.io/otel/attribute"
20
- "go.opentelemetry.io/otel/trace"
10
)
11
12
type DhtAPI CoreAPI
13
14
+// nolint deprecated
15
+// Deprecated: use [RoutingAPI.FindPeer] instead.
16
func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
26
- ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindPeer", trace.WithAttributes(attribute.String("peer", p.String())))
27
- defer span.End()
28
- err := api.checkOnline(false)
29
- if err != nil {
30
- return peer.AddrInfo{}, err
31
- }
32
-
33
- pi, err := api.routing.FindPeer(ctx, peer.ID(p))
34
- if err != nil {
35
- return peer.AddrInfo{}, err
36
- }
37
-
38
- return pi, nil
17
+ return api.core().Routing().FindPeer(ctx, p)
18
}
19
20
+// nolint deprecated
21
+// Deprecated: use [RoutingAPI.FindProviders] instead.
22
func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.DhtFindProvidersOption) (<-chan peer.AddrInfo, error) {
42
- ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindProviders", trace.WithAttributes(attribute.String("path", p.String())))
43
- defer span.End()
44
-
45
- settings, err := caopts.DhtFindProvidersOptions(opts...)
46
- if err != nil {
47
- return nil, err
48
- }
49
- span.SetAttributes(attribute.Int("numproviders", settings.NumProviders))
50
-
51
- err = api.checkOnline(false)
52
- if err != nil {
53
- return nil, err
54
- }
55
-
56
- rp, _, err := api.core().ResolvePath(ctx, p)
57
- if err != nil {
58
- return nil, err
59
- }
60
-
61
- numProviders := settings.NumProviders
62
- if numProviders < 1 {
63
- return nil, fmt.Errorf("number of providers must be greater than 0")
64
- }
65
-
66
- pchan := api.routing.FindProvidersAsync(ctx, rp.RootCid(), numProviders)
67
- return pchan, nil
23
+ return api.core().Routing().FindProviders(ctx, p, opts...)
24
}
25
70
-func (api *DhtAPI) Provide(ctx context.Context, path path.Path, opts ...caopts.DhtProvideOption) error {
71
- ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "Provide", trace.WithAttributes(attribute.String("path", path.String())))
72
- defer span.End()
73
-
74
- settings, err := caopts.DhtProvideOptions(opts...)
75
- if err != nil {
76
- return err
77
- }
78
- span.SetAttributes(attribute.Bool("recursive", settings.Recursive))
79
-
80
- err = api.checkOnline(false)
81
- if err != nil {
82
- return err
83
- }
84
-
85
- rp, _, err := api.core().ResolvePath(ctx, path)
86
- if err != nil {
87
- return err
88
- }
89
-
90
- c := rp.RootCid()
91
-
92
- has, err := api.blockstore.Has(ctx, c)
93
- if err != nil {
94
- return err
95
- }
96
-
97
- if !has {
98
- return fmt.Errorf("block %s not found locally, cannot provide", c)
99
- }
100
-
101
- if settings.Recursive {
102
- err = provideKeysRec(ctx, api.routing, api.blockstore, []cid.Cid{c})
103
- } else {
104
- err = provideKeys(ctx, api.routing, []cid.Cid{c})
105
- }
106
- if err != nil {
107
- return err
108
- }
109
-
110
- return nil
111
-}
112
-
113
-func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
114
- for _, c := range cids {
115
- err := r.Provide(ctx, c, true)
116
- if err != nil {
117
- return err
118
- }
119
- }
120
- return nil
121
-}
122
-
123
-func provideKeysRec(ctx context.Context, r routing.Routing, bs blockstore.Blockstore, cids []cid.Cid) error {
124
- provided := cidutil.NewStreamingSet()
125
-
126
- errCh := make(chan error)
127
- go func() {
128
- dserv := dag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
129
- for _, c := range cids {
130
- err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, provided.Visitor(ctx))
131
- if err != nil {
132
- errCh <- err
133
- }
134
- }
135
- }()
136
-
137
- for {
138
- select {
139
- case k := <-provided.New:
140
- err := r.Provide(ctx, k, true)
141
- if err != nil {
142
- return err
143
- }
144
- case err := <-errCh:
145
- return err
146
- case <-ctx.Done():
147
- return ctx.Err()
148
- }
149
- }
26
+// nolint deprecated
27
+// Deprecated: use [RoutingAPI.Provide] instead.
28
+func (api *DhtAPI) Provide(ctx context.Context, p path.Path, opts ...caopts.DhtProvideOption) error {
29
+ return api.core().Routing().Provide(ctx, p, opts...)
30
}
31
32
func (api *DhtAPI) core() coreiface.CoreAPI {
core/coreapi/routing.go
+149
-6
@@ -3,17 +3,29 @@ package coreapi
3
import (
4
"context"
5
"errors"
6
+ "fmt"
7
"strings"
8
9
+ blockservice "github.com/ipfs/boxo/blockservice"
10
+ blockstore "github.com/ipfs/boxo/blockstore"
11
+ offline "github.com/ipfs/boxo/exchange/offline"
12
+ dag "github.com/ipfs/boxo/ipld/merkledag"
13
+ "github.com/ipfs/boxo/path"
14
+ cid "github.com/ipfs/go-cid"
15
+ cidutil "github.com/ipfs/go-cidutil"
16
coreiface "github.com/ipfs/kubo/core/coreiface"
17
caopts "github.com/ipfs/kubo/core/coreiface/options"
18
+ "github.com/ipfs/kubo/tracing"
19
peer "github.com/libp2p/go-libp2p/core/peer"
20
+ routing "github.com/libp2p/go-libp2p/core/routing"
21
+ "go.opentelemetry.io/otel/attribute"
22
+ "go.opentelemetry.io/otel/trace"
23
)
24
25
type RoutingAPI CoreAPI
26
15
-func (r *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) {
16
- if !r.nd.IsOnline {
27
+func (api *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) {
28
+ if !api.nd.IsOnline {
29
return nil, coreiface.ErrOffline
30
}
31
@@ -22,16 +34,16 @@ func (r *RoutingAPI) Get(ctx context.Context, key string) ([]byte, error) {
34
return nil, err
35
}
36
25
- return r.routing.GetValue(ctx, dhtKey)
37
+ return api.routing.GetValue(ctx, dhtKey)
38
}
39
28
-func (r *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...caopts.RoutingPutOption) error {
40
+func (api *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...caopts.RoutingPutOption) error {
41
options, err := caopts.RoutingPutOptions(opts...)
42
if err != nil {
43
return err
44
}
45
34
- err = r.checkOnline(options.AllowOffline)
46
+ err = api.checkOnline(options.AllowOffline)
47
if err != nil {
48
return err
49
}
@@ -41,7 +53,7 @@ func (r *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...
53
return err
54
}
55
44
- return r.routing.PutValue(ctx, dhtKey, value)
56
+ return api.routing.PutValue(ctx, dhtKey, value)
57
}
58
59
func normalizeKey(s string) (string, error) {
@@ -58,3 +70,134 @@ func normalizeKey(s string) (string, error) {
70
}
71
return strings.Join(append(parts[:2], string(k)), "/"), nil
72
}
73
+
74
+func (api *RoutingAPI) FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error) {
75
+ ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindPeer", trace.WithAttributes(attribute.String("peer", p.String())))
76
+ defer span.End()
77
+ err := api.checkOnline(false)
78
+ if err != nil {
79
+ return peer.AddrInfo{}, err
80
+ }
81
+
82
+ pi, err := api.routing.FindPeer(ctx, peer.ID(p))
83
+ if err != nil {
84
+ return peer.AddrInfo{}, err
85
+ }
86
+
87
+ return pi, nil
88
+}
89
+
90
+func (api *RoutingAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopts.RoutingFindProvidersOption) (<-chan peer.AddrInfo, error) {
91
+ ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "FindProviders", trace.WithAttributes(attribute.String("path", p.String())))
92
+ defer span.End()
93
+
94
+ settings, err := caopts.RoutingFindProvidersOptions(opts...)
95
+ if err != nil {
96
+ return nil, err
97
+ }
98
+ span.SetAttributes(attribute.Int("numproviders", settings.NumProviders))
99
+
100
+ err = api.checkOnline(false)
101
+ if err != nil {
102
+ return nil, err
103
+ }
104
+
105
+ rp, _, err := api.core().ResolvePath(ctx, p)
106
+ if err != nil {
107
+ return nil, err
108
+ }
109
+
110
+ numProviders := settings.NumProviders
111
+ if numProviders < 1 {
112
+ return nil, fmt.Errorf("number of providers must be greater than 0")
113
+ }
114
+
115
+ pchan := api.routing.FindProvidersAsync(ctx, rp.RootCid(), numProviders)
116
+ return pchan, nil
117
+}
118
+
119
+func (api *RoutingAPI) Provide(ctx context.Context, path path.Path, opts ...caopts.RoutingProvideOption) error {
120
+ ctx, span := tracing.Span(ctx, "CoreAPI.DhtAPI", "Provide", trace.WithAttributes(attribute.String("path", path.String())))
121
+ defer span.End()
122
+
123
+ settings, err := caopts.RoutingProvideOptions(opts...)
124
+ if err != nil {
125
+ return err
126
+ }
127
+ span.SetAttributes(attribute.Bool("recursive", settings.Recursive))
128
+
129
+ err = api.checkOnline(false)
130
+ if err != nil {
131
+ return err
132
+ }
133
+
134
+ rp, _, err := api.core().ResolvePath(ctx, path)
135
+ if err != nil {
136
+ return err
137
+ }
138
+
139
+ c := rp.RootCid()
140
+
141
+ has, err := api.blockstore.Has(ctx, c)
142
+ if err != nil {
143
+ return err
144
+ }
145
+
146
+ if !has {
147
+ return fmt.Errorf("block %s not found locally, cannot provide", c)
148
+ }
149
+
150
+ if settings.Recursive {
151
+ err = provideKeysRec(ctx, api.routing, api.blockstore, []cid.Cid{c})
152
+ } else {
153
+ err = provideKeys(ctx, api.routing, []cid.Cid{c})
154
+ }
155
+ if err != nil {
156
+ return err
157
+ }
158
+
159
+ return nil
160
+}
161
+
162
+func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
163
+ for _, c := range cids {
164
+ err := r.Provide(ctx, c, true)
165
+ if err != nil {
166
+ return err
167
+ }
168
+ }
169
+ return nil
170
+}
171
+
172
+func provideKeysRec(ctx context.Context, r routing.Routing, bs blockstore.Blockstore, cids []cid.Cid) error {
173
+ provided := cidutil.NewStreamingSet()
174
+
175
+ errCh := make(chan error)
176
+ go func() {
177
+ dserv := dag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
178
+ for _, c := range cids {
179
+ err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, provided.Visitor(ctx))
180
+ if err != nil {
181
+ errCh <- err
182
+ }
183
+ }
184
+ }()
185
+
186
+ for {
187
+ select {
188
+ case k := <-provided.New:
189
+ err := r.Provide(ctx, k, true)
190
+ if err != nil {
191
+ return err
192
+ }
193
+ case err := <-errCh:
194
+ return err
195
+ case <-ctx.Done():
196
+ return ctx.Err()
197
+ }
198
+ }
199
+}
200
+
201
+func (api *RoutingAPI) core() coreiface.CoreAPI {
202
+ return (*CoreAPI)(api)
203
+}
core/coreiface/coreapi.go
+2
-1
@@ -34,7 +34,8 @@ type CoreAPI interface {
34
// Object returns an implementation of Object API
35
Object() ObjectAPI
36
37
- // Dht returns an implementation of Dht API
37
+ // nolint deprecated
38
+ // Deprecated: use [Routing] instead.
39
Dht() DhtAPI
40
41
// Swarm returns an implementation of Swarm API
core/coreiface/dht.go
+8
-10
@@ -4,24 +4,22 @@ import (
4
"context"
5
6
"github.com/ipfs/boxo/path"
7
-
7
"github.com/ipfs/kubo/core/coreiface/options"
9
-
8
"github.com/libp2p/go-libp2p/core/peer"
9
)
10
13
-// DhtAPI specifies the interface to the DHT
14
-// Note: This API will likely get deprecated in near future, see
15
-// https://github.com/ipfs/interface-ipfs-core/issues/249 for more context.
11
+// nolint deprecated
12
+// Deprecated: use [RoutingAPI] instead.
13
type DhtAPI interface {
17
- // FindPeer queries the DHT for all of the multiaddresses associated with a
18
- // Peer ID
14
+ // nolint deprecated
15
+ // Deprecated: use [RoutingAPI.FindPeer] instead.
16
FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
17
21
- // FindProviders finds peers in the DHT who can provide a specific value
22
- // given a key.
18
+ // nolint deprecated
19
+ // Deprecated: use [RoutingAPI.FindProviders] instead.
20
FindProviders(context.Context, path.Path, ...options.DhtFindProvidersOption) (<-chan peer.AddrInfo, error)
21
25
- // Provide announces to the network that you are providing given values
22
+ // nolint deprecated
23
+ // Deprecated: use [RoutingAPI.Provide] instead.
24
Provide(context.Context, path.Path, ...options.DhtProvideOption) error
25
}
core/coreiface/options/dht.go
+21
-56
@@ -1,64 +1,29 @@
1
package options
2
3
-type DhtProvideSettings struct {
4
- Recursive bool
5
-}
3
+// nolint deprecated
4
+// Deprecated: use [RoutingProvideSettings] instead.
5
+type DhtProvideSettings = RoutingProvideSettings
6
7
-type DhtFindProvidersSettings struct {
8
- NumProviders int
9
-}
7
+// nolint deprecated
8
+// Deprecated: use [RoutingFindProvidersSettings] instead.
9
+type DhtFindProvidersSettings = RoutingFindProvidersSettings
10
11
-type (
12
- DhtProvideOption func(*DhtProvideSettings) error
13
- DhtFindProvidersOption func(*DhtFindProvidersSettings) error
14
-)
11
+// nolint deprecated
12
+// Deprecated: use [RoutingProvideOption] instead.
13
+type DhtProvideOption = RoutingProvideOption
14
16
-func DhtProvideOptions(opts ...DhtProvideOption) (*DhtProvideSettings, error) {
17
- options := &DhtProvideSettings{
18
- Recursive: false,
19
- }
15
+// nolint deprecated
16
+// Deprecated: use [RoutingFindProvidersOption] instead.
17
+type DhtFindProvidersOption = RoutingFindProvidersOption
18
21
- for _, opt := range opts {
22
- err := opt(options)
23
- if err != nil {
24
- return nil, err
25
- }
26
- }
27
- return options, nil
28
-}
19
+// nolint deprecated
20
+// Deprecated: use [RoutingProvideOptions] instead.
21
+var DhtProvideOptions = RoutingProvideOptions
22
30
-func DhtFindProvidersOptions(opts ...DhtFindProvidersOption) (*DhtFindProvidersSettings, error) {
31
- options := &DhtFindProvidersSettings{
32
- NumProviders: 20,
33
- }
23
+// nolint deprecated
24
+// Deprecated: use [RoutingFindProvidersOptions] instead.
25
+var DhtFindProvidersOptions = RoutingFindProvidersOptions
26
35
- for _, opt := range opts {
36
- err := opt(options)
37
- if err != nil {
38
- return nil, err
39
- }
40
- }
41
- return options, nil
42
-}
43
-
44
-type dhtOpts struct{}
45
-
46
-var Dht dhtOpts
47
-
48
-// Recursive is an option for Dht.Provide which specifies whether to provide
49
-// the given path recursively
50
-func (dhtOpts) Recursive(recursive bool) DhtProvideOption {
51
- return func(settings *DhtProvideSettings) error {
52
- settings.Recursive = recursive
53
- return nil
54
- }
55
-}
56
-
57
-// NumProviders is an option for Dht.FindProviders which specifies the
58
-// number of peers to look for. Default is 20
59
-func (dhtOpts) NumProviders(numProviders int) DhtFindProvidersOption {
60
- return func(settings *DhtFindProvidersSettings) error {
61
- settings.NumProviders = numProviders
62
- return nil
63
- }
64
-}
27
+// nolint deprecated
28
+// Deprecated: use [Routing] instead.
29
+var Dht = Routing
core/coreiface/options/routing.go
+67
-4
@@ -21,13 +21,76 @@ func RoutingPutOptions(opts ...RoutingPutOption) (*RoutingPutSettings, error) {
21
return options, nil
22
}
23
24
-type putOpts struct{}
24
+// nolint deprecated
25
+// Deprecated: use [Routing] instead.
26
+var Put = Routing
27
26
-var Put putOpts
28
+type RoutingProvideSettings struct {
29
+ Recursive bool
30
+}
31
+
32
+type RoutingFindProvidersSettings struct {
33
+ NumProviders int
34
+}
35
+
36
+type (
37
+ RoutingProvideOption func(*DhtProvideSettings) error
38
+ RoutingFindProvidersOption func(*DhtFindProvidersSettings) error
39
+)
40
+
41
+func RoutingProvideOptions(opts ...RoutingProvideOption) (*RoutingProvideSettings, error) {
42
+ options := &RoutingProvideSettings{
43
+ Recursive: false,
44
+ }
45
+
46
+ for _, opt := range opts {
47
+ err := opt(options)
48
+ if err != nil {
49
+ return nil, err
50
+ }
51
+ }
52
+ return options, nil
53
+}
54
+
55
+func RoutingFindProvidersOptions(opts ...RoutingFindProvidersOption) (*RoutingFindProvidersSettings, error) {
56
+ options := &RoutingFindProvidersSettings{
57
+ NumProviders: 20,
58
+ }
59
+
60
+ for _, opt := range opts {
61
+ err := opt(options)
62
+ if err != nil {
63
+ return nil, err
64
+ }
65
+ }
66
+ return options, nil
67
+}
68
+
69
+type routingOpts struct{}
70
+
71
+var Routing routingOpts
72
+
73
+// Recursive is an option for [Routing.Provide] which specifies whether to provide
74
+// the given path recursively.
75
+func (routingOpts) Recursive(recursive bool) RoutingProvideOption {
76
+ return func(settings *DhtProvideSettings) error {
77
+ settings.Recursive = recursive
78
+ return nil
79
+ }
80
+}
81
+
82
+// NumProviders is an option for [Routing.FindProviders] which specifies the
83
+// number of peers to look for. Default is 20.
84
+func (routingOpts) NumProviders(numProviders int) RoutingFindProvidersOption {
85
+ return func(settings *DhtFindProvidersSettings) error {
86
+ settings.NumProviders = numProviders
87
+ return nil
88
+ }
89
+}
90
28
-// AllowOffline is an option for Routing.Put which specifies whether to allow
91
+// AllowOffline is an option for [Routing.Put] which specifies whether to allow
92
// publishing when the node is offline. Default value is false
30
-func (putOpts) AllowOffline(allow bool) RoutingPutOption {
93
+func (routingOpts) AllowOffline(allow bool) RoutingPutOption {
94
return func(settings *RoutingPutSettings) error {
95
settings.AllowOffline = allow
96
return nil
core/coreiface/routing.go
+13
@@ -3,7 +3,9 @@ package iface
3
import (
4
"context"
5
6
+ "github.com/ipfs/boxo/path"
7
"github.com/ipfs/kubo/core/coreiface/options"
8
+ "github.com/libp2p/go-libp2p/core/peer"
9
)
10
11
// RoutingAPI specifies the interface to the routing layer.
@@ -13,4 +15,15 @@ type RoutingAPI interface {
15
16
// Put sets a value for a given key
17
Put(ctx context.Context, key string, value []byte, opts ...options.RoutingPutOption) error
18
+
19
+ // FindPeer queries the routing system for all the multiaddresses associated
20
+ // with the given [peer.ID].
21
+ FindPeer(context.Context, peer.ID) (peer.AddrInfo, error)
22
+
23
+ // FindProviders finds the peers in the routing system who can provide a specific
24
+ // value given a key.
25
+ FindProviders(context.Context, path.Path, ...options.RoutingFindProvidersOption) (<-chan peer.AddrInfo, error)
26
+
27
+ // Provide announces to the network that you are providing given values
28
+ Provide(context.Context, path.Path, ...options.RoutingProvideOption) error
29
}
core/coreiface/tests/api.go
-1
@@ -75,7 +75,6 @@ func TestApi(p Provider) func(t *testing.T) {
75
return func(t *testing.T) {
76
t.Run("Block", tp.TestBlock)
77
t.Run("Dag", tp.TestDag)
78
- t.Run("Dht", tp.TestDht)
78
t.Run("Key", tp.TestKey)
79
t.Run("Name", tp.TestName)
80
t.Run("Object", tp.TestObject)
core/coreiface/tests/dht.go
deleted
-166
@@ -1,166 +0,0 @@
1
-package tests
2
-
3
-import (
4
- "context"
5
- "io"
6
- "testing"
7
- "time"
8
-
9
- iface "github.com/ipfs/kubo/core/coreiface"
10
- "github.com/ipfs/kubo/core/coreiface/options"
11
-)
12
-
13
-func (tp *TestSuite) TestDht(t *testing.T) {
14
- tp.hasApi(t, func(api iface.CoreAPI) error {
15
- if api.Dht() == nil {
16
- return errAPINotImplemented
17
- }
18
- return nil
19
- })
20
-
21
- t.Run("TestDhtFindPeer", tp.TestDhtFindPeer)
22
- t.Run("TestDhtFindProviders", tp.TestDhtFindProviders)
23
- t.Run("TestDhtProvide", tp.TestDhtProvide)
24
-}
25
-
26
-func (tp *TestSuite) TestDhtFindPeer(t *testing.T) {
27
- ctx, cancel := context.WithCancel(context.Background())
28
- defer cancel()
29
- apis, err := tp.MakeAPISwarm(t, ctx, 5)
30
- if err != nil {
31
- t.Fatal(err)
32
- }
33
-
34
- self0, err := apis[0].Key().Self(ctx)
35
- if err != nil {
36
- t.Fatal(err)
37
- }
38
-
39
- laddrs0, err := apis[0].Swarm().LocalAddrs(ctx)
40
- if err != nil {
41
- t.Fatal(err)
42
- }
43
- if len(laddrs0) != 1 {
44
- t.Fatal("unexpected number of local addrs")
45
- }
46
-
47
- time.Sleep(3 * time.Second)
48
-
49
- pi, err := apis[2].Dht().FindPeer(ctx, self0.ID())
50
- if err != nil {
51
- t.Fatal(err)
52
- }
53
-
54
- if pi.Addrs[0].String() != laddrs0[0].String() {
55
- t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
56
- }
57
-
58
- self2, err := apis[2].Key().Self(ctx)
59
- if err != nil {
60
- t.Fatal(err)
61
- }
62
-
63
- pi, err = apis[1].Dht().FindPeer(ctx, self2.ID())
64
- if err != nil {
65
- t.Fatal(err)
66
- }
67
-
68
- laddrs2, err := apis[2].Swarm().LocalAddrs(ctx)
69
- if err != nil {
70
- t.Fatal(err)
71
- }
72
- if len(laddrs2) != 1 {
73
- t.Fatal("unexpected number of local addrs")
74
- }
75
-
76
- if pi.Addrs[0].String() != laddrs2[0].String() {
77
- t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
78
- }
79
-}
80
-
81
-func (tp *TestSuite) TestDhtFindProviders(t *testing.T) {
82
- ctx, cancel := context.WithCancel(context.Background())
83
- defer cancel()
84
- apis, err := tp.MakeAPISwarm(t, ctx, 5)
85
- if err != nil {
86
- t.Fatal(err)
87
- }
88
-
89
- p, err := addTestObject(ctx, apis[0])
90
- if err != nil {
91
- t.Fatal(err)
92
- }
93
-
94
- time.Sleep(3 * time.Second)
95
-
96
- out, err := apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
97
- if err != nil {
98
- t.Fatal(err)
99
- }
100
-
101
- provider := <-out
102
-
103
- self0, err := apis[0].Key().Self(ctx)
104
- if err != nil {
105
- t.Fatal(err)
106
- }
107
-
108
- if provider.ID.String() != self0.ID().String() {
109
- t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
110
- }
111
-}
112
-
113
-func (tp *TestSuite) TestDhtProvide(t *testing.T) {
114
- ctx, cancel := context.WithCancel(context.Background())
115
- defer cancel()
116
- apis, err := tp.MakeAPISwarm(t, ctx, 5)
117
- if err != nil {
118
- t.Fatal(err)
119
- }
120
-
121
- off0, err := apis[0].WithOptions(options.Api.Offline(true))
122
- if err != nil {
123
- t.Fatal(err)
124
- }
125
-
126
- s, err := off0.Block().Put(ctx, &io.LimitedReader{R: rnd, N: 4092})
127
- if err != nil {
128
- t.Fatal(err)
129
- }
130
-
131
- p := s.Path()
132
-
133
- time.Sleep(3 * time.Second)
134
-
135
- out, err := apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
136
- if err != nil {
137
- t.Fatal(err)
138
- }
139
-
140
- _, ok := <-out
141
-
142
- if ok {
143
- t.Fatal("did not expect to find any providers")
144
- }
145
-
146
- self0, err := apis[0].Key().Self(ctx)
147
- if err != nil {
148
- t.Fatal(err)
149
- }
150
-
151
- err = apis[0].Dht().Provide(ctx, p)
152
- if err != nil {
153
- t.Fatal(err)
154
- }
155
-
156
- out, err = apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
157
- if err != nil {
158
- t.Fatal(err)
159
- }
160
-
161
- provider := <-out
162
-
163
- if provider.ID.String() != self0.ID().String() {
164
- t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
165
- }
166
-}
core/coreiface/tests/routing.go
+147
-1
@@ -2,6 +2,7 @@ package tests
2
3
import (
4
"context"
5
+ "io"
6
"testing"
7
"time"
8
@@ -23,6 +24,9 @@ func (tp *TestSuite) TestRouting(t *testing.T) {
24
t.Run("TestRoutingGet", tp.TestRoutingGet)
25
t.Run("TestRoutingPut", tp.TestRoutingPut)
26
t.Run("TestRoutingPutOffline", tp.TestRoutingPutOffline)
27
+ t.Run("TestRoutingFindPeer", tp.TestRoutingFindPeer)
28
+ t.Run("TestRoutingFindProviders", tp.TestRoutingFindProviders)
29
+ t.Run("TestRoutingProvide", tp.TestRoutingProvide)
30
}
31
32
func (tp *TestSuite) testRoutingPublishKey(t *testing.T, ctx context.Context, api iface.CoreAPI, opts ...options.NamePublishOption) (path.Path, ipns.Name) {
@@ -95,6 +99,148 @@ func (tp *TestSuite) TestRoutingPutOffline(t *testing.T) {
99
err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data)
100
require.Error(t, err, "this operation should fail because we are offline")
101
98
- err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data, options.Put.AllowOffline(true))
102
+ err = api.Routing().Put(ctx, ipns.NamespacePrefix+name.String(), data, options.Routing.AllowOffline(true))
103
require.NoError(t, err)
104
}
105
+
106
+func (tp *TestSuite) TestRoutingFindPeer(t *testing.T) {
107
+ ctx, cancel := context.WithCancel(context.Background())
108
+ defer cancel()
109
+ apis, err := tp.MakeAPISwarm(t, ctx, 5)
110
+ if err != nil {
111
+ t.Fatal(err)
112
+ }
113
+
114
+ self0, err := apis[0].Key().Self(ctx)
115
+ if err != nil {
116
+ t.Fatal(err)
117
+ }
118
+
119
+ laddrs0, err := apis[0].Swarm().LocalAddrs(ctx)
120
+ if err != nil {
121
+ t.Fatal(err)
122
+ }
123
+ if len(laddrs0) != 1 {
124
+ t.Fatal("unexpected number of local addrs")
125
+ }
126
+
127
+ time.Sleep(3 * time.Second)
128
+
129
+ pi, err := apis[2].Routing().FindPeer(ctx, self0.ID())
130
+ if err != nil {
131
+ t.Fatal(err)
132
+ }
133
+
134
+ if pi.Addrs[0].String() != laddrs0[0].String() {
135
+ t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
136
+ }
137
+
138
+ self2, err := apis[2].Key().Self(ctx)
139
+ if err != nil {
140
+ t.Fatal(err)
141
+ }
142
+
143
+ pi, err = apis[1].Routing().FindPeer(ctx, self2.ID())
144
+ if err != nil {
145
+ t.Fatal(err)
146
+ }
147
+
148
+ laddrs2, err := apis[2].Swarm().LocalAddrs(ctx)
149
+ if err != nil {
150
+ t.Fatal(err)
151
+ }
152
+ if len(laddrs2) != 1 {
153
+ t.Fatal("unexpected number of local addrs")
154
+ }
155
+
156
+ if pi.Addrs[0].String() != laddrs2[0].String() {
157
+ t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
158
+ }
159
+}
160
+
161
+func (tp *TestSuite) TestRoutingFindProviders(t *testing.T) {
162
+ ctx, cancel := context.WithCancel(context.Background())
163
+ defer cancel()
164
+ apis, err := tp.MakeAPISwarm(t, ctx, 5)
165
+ if err != nil {
166
+ t.Fatal(err)
167
+ }
168
+
169
+ p, err := addTestObject(ctx, apis[0])
170
+ if err != nil {
171
+ t.Fatal(err)
172
+ }
173
+
174
+ time.Sleep(3 * time.Second)
175
+
176
+ out, err := apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
177
+ if err != nil {
178
+ t.Fatal(err)
179
+ }
180
+
181
+ provider := <-out
182
+
183
+ self0, err := apis[0].Key().Self(ctx)
184
+ if err != nil {
185
+ t.Fatal(err)
186
+ }
187
+
188
+ if provider.ID.String() != self0.ID().String() {
189
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
190
+ }
191
+}
192
+
193
+func (tp *TestSuite) TestRoutingProvide(t *testing.T) {
194
+ ctx, cancel := context.WithCancel(context.Background())
195
+ defer cancel()
196
+ apis, err := tp.MakeAPISwarm(t, ctx, 5)
197
+ if err != nil {
198
+ t.Fatal(err)
199
+ }
200
+
201
+ off0, err := apis[0].WithOptions(options.Api.Offline(true))
202
+ if err != nil {
203
+ t.Fatal(err)
204
+ }
205
+
206
+ s, err := off0.Block().Put(ctx, &io.LimitedReader{R: rnd, N: 4092})
207
+ if err != nil {
208
+ t.Fatal(err)
209
+ }
210
+
211
+ p := s.Path()
212
+
213
+ time.Sleep(3 * time.Second)
214
+
215
+ out, err := apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
216
+ if err != nil {
217
+ t.Fatal(err)
218
+ }
219
+
220
+ _, ok := <-out
221
+
222
+ if ok {
223
+ t.Fatal("did not expect to find any providers")
224
+ }
225
+
226
+ self0, err := apis[0].Key().Self(ctx)
227
+ if err != nil {
228
+ t.Fatal(err)
229
+ }
230
+
231
+ err = apis[0].Routing().Provide(ctx, p)
232
+ if err != nil {
233
+ t.Fatal(err)
234
+ }
235
+
236
+ out, err = apis[2].Routing().FindProviders(ctx, p, options.Routing.NumProviders(1))
237
+ if err != nil {
238
+ t.Fatal(err)
239
+ }
240
+
241
+ provider := <-out
242
+
243
+ if provider.ID.String() != self0.ID().String() {
244
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
245
+ }
246
+}
docs/changelogs/v0.27.md
+8
@@ -7,6 +7,8 @@
7
- [Overview](#overview)
8
- [🔦 Highlights](#-highlights)
9
- [Gateway: support for `/api/v0` is deprecated](#gateway-support-for-apiv0-is-deprecated)
10
+ - [IPNS resolver cache's TTL can now be configured](#ipns-resolver-caches-ttl-can-now-be-configured)
11
+ - [RPC client: deprecated DHT API, added Routing API](#rpc-client-deprecated-dht-api-added-routing-api)
12
- [📝 Changelog](#-changelog)
13
- [👨👩👧👦 Contributors](#-contributors)
14
@@ -24,6 +26,12 @@ If you have a legacy software that relies on this behavior, and want to expose p
26
27
You can now configure the upper-bound of a cached IPNS entry's Time-To-Live via [`Ipns.MaxCacheTTL`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsmaxcachettl).
28
29
+#### RPC client: deprecated DHT API, added Routing API
30
+
31
+The RPC client now includes a Routing API to match the available commands in `/api/v0/routing`. In addition, the DHT API has been marked as deprecated.
32
+
33
+In the next version, all DHT deprecated methods will be removed from the Go RPC client.
34
+
35
### 📝 Changelog
36
37
### 👨👩👧👦 Contributors
docs/file-transfer.md
+2
-2
@@ -68,12 +68,12 @@ pitfalls that people run into)
68
### Checking providers
69
When requesting content on ipfs, nodes search the DHT for 'provider records' to
70
see who has what content. Let's manually do that on node B to make sure that
71
-node B is able to determine that node A has the data. Run `ipfs dht findprovs
71
+node B is able to determine that node A has the data. Run `ipfs routing findprovs
72
<hash>`. We expect to see the peer ID of node A printed out. If this command
73
returns nothing (or returns IDs that are not node A), then no record of A
74
having the data exists on the network. This can happen if the data is added
75
while node A does not have a daemon running. If this happens, you can run `ipfs
76
-dht provide <hash>` on node A to announce to the network that you have that
76
+routing provide <hash>` on node A to announce to the network that you have that
77
hash. Then if you restart the `ipfs get` command, node B should now be able
78
to tell that node A has the content it wants. If node A's peer ID showed up in
79
the initial `findprovs` call, or manually providing the hash didn't resolve the
test/cli/dht_opt_prov_test.go
+1
-1
@@ -22,7 +22,7 @@ func TestDHTOptimisticProvide(t *testing.T) {
22
nodes.StartDaemons().Connect()
23
24
hash := nodes[0].IPFSAddStr(testutils.RandomStr(100))
25
- nodes[0].IPFS("dht", "provide", hash)
25
+ nodes[0].IPFS("routing", "provide", hash)
26
27
res := nodes[1].IPFS("routing", "findprovs", "--num-providers=1", hash)
28
assert.Equal(t, nodes[0].PeerID().String(), res.Stdout.Trimmed())
test/sharness/lib/test-lib.sh
+2
-2
@@ -512,7 +512,7 @@ port_from_maddr() {
512
513
findprovs_empty() {
514
test_expect_success 'findprovs '$1' succeeds' '
515
- ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut
515
+ ipfsi 1 routing findprovs -n 1 '$1' > findprovsOut
516
'
517
518
test_expect_success "findprovs $1 output is empty" '
@@ -522,7 +522,7 @@ findprovs_empty() {
522
523
findprovs_expect() {
524
test_expect_success 'findprovs '$1' succeeds' '
525
- ipfsi 1 dht findprovs -n 1 '$1' > findprovsOut &&
525
+ ipfsi 1 routing findprovs -n 1 '$1' > findprovsOut &&
526
echo '$2' > expected
527
'
528