Skip to content

Commit 2ea39b8

Browse files
committed
feat!: remove all Provide* functions
1 parent 043fb2f commit 2ea39b8

10 files changed

+10
-690
lines changed

routing/http/client/client.go

+2-98
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,10 @@ import (
1010
"mime"
1111
"net/http"
1212
"strings"
13-
"time"
1413

1514
"github.com/benbjohnson/clock"
1615
ipns "github.com/ipfs/boxo/ipns"
1716
"github.com/ipfs/boxo/routing/http/contentrouter"
18-
"github.com/ipfs/boxo/routing/http/internal/drjson"
19-
"github.com/ipfs/boxo/routing/http/server"
2017
"github.com/ipfs/boxo/routing/http/types"
2118
"github.com/ipfs/boxo/routing/http/types/iter"
2219
jsontypes "github.com/ipfs/boxo/routing/http/types/json"
@@ -58,10 +55,6 @@ type client struct {
5855
peerID peer.ID
5956
addrs []types.Multiaddr
6057
identity crypto.PrivKey
61-
62-
// called immeidately after signing a provide req
63-
// used for testing, e.g. testing the server with a mangled signature
64-
afterSignCallback func(req *types.WriteBitswapProviderRecord)
6558
}
6659

6760
// defaultUserAgent is used as a fallback to inform HTTP server which library
@@ -168,7 +161,7 @@ func (c *client) FindProviders(ctx context.Context, key cid.Cid) (provs iter.Res
168161
// TODO test measurements
169162
m := newMeasurement("FindProviders")
170163

171-
url := c.baseURL + server.ProvidePath + key.String()
164+
url := c.baseURL + "/routing/v1/providers/" + key.String()
172165
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
173166
if err != nil {
174167
return nil, err
@@ -223,7 +216,7 @@ func (c *client) FindProviders(ctx context.Context, key cid.Cid) (provs iter.Res
223216
var it iter.ResultIter[types.ProviderResponse]
224217
switch mediaType {
225218
case mediaTypeJSON:
226-
parsedResp := &jsontypes.ReadProvidersResponse{}
219+
parsedResp := &jsontypes.ProvidersResponse{}
227220
err = json.NewDecoder(resp.Body).Decode(parsedResp)
228221
var sliceIt iter.Iter[types.ProviderResponse] = iter.FromSlice(parsedResp.Providers)
229222
it = iter.ToResultIter(sliceIt)
@@ -238,95 +231,6 @@ func (c *client) FindProviders(ctx context.Context, key cid.Cid) (provs iter.Res
238231
return &measuringIter[iter.Result[types.ProviderResponse]]{Iter: it, ctx: ctx, m: m}, nil
239232
}
240233

241-
func (c *client) ProvideBitswap(ctx context.Context, keys []cid.Cid, ttl time.Duration) (time.Duration, error) {
242-
if c.identity == nil {
243-
return 0, errors.New("cannot provide Bitswap records without an identity")
244-
}
245-
if c.peerID.Size() == 0 {
246-
return 0, errors.New("cannot provide Bitswap records without a peer ID")
247-
}
248-
249-
ks := make([]types.CID, len(keys))
250-
for i, c := range keys {
251-
ks[i] = types.CID{Cid: c}
252-
}
253-
254-
now := c.clock.Now()
255-
256-
req := types.WriteBitswapProviderRecord{
257-
Protocol: "transport-bitswap",
258-
Schema: types.SchemaBitswap,
259-
Payload: types.BitswapPayload{
260-
Keys: ks,
261-
AdvisoryTTL: &types.Duration{Duration: ttl},
262-
Timestamp: &types.Time{Time: now},
263-
ID: &c.peerID,
264-
Addrs: c.addrs,
265-
},
266-
}
267-
err := req.Sign(c.peerID, c.identity)
268-
if err != nil {
269-
return 0, err
270-
}
271-
272-
if c.afterSignCallback != nil {
273-
c.afterSignCallback(&req)
274-
}
275-
276-
advisoryTTL, err := c.provideSignedBitswapRecord(ctx, &req)
277-
if err != nil {
278-
return 0, err
279-
}
280-
281-
return advisoryTTL, err
282-
}
283-
284-
// ProvideAsync makes a provide request to a delegated router
285-
func (c *client) provideSignedBitswapRecord(ctx context.Context, bswp *types.WriteBitswapProviderRecord) (time.Duration, error) {
286-
req := jsontypes.WriteProvidersRequest{Providers: []types.WriteProviderRecord{bswp}}
287-
288-
url := c.baseURL + server.ProvidePath
289-
290-
b, err := drjson.MarshalJSONBytes(req)
291-
if err != nil {
292-
return 0, err
293-
}
294-
295-
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPut, url, bytes.NewBuffer(b))
296-
if err != nil {
297-
return 0, err
298-
}
299-
300-
resp, err := c.httpClient.Do(httpReq)
301-
if err != nil {
302-
return 0, fmt.Errorf("making HTTP req to provide a signed record: %w", err)
303-
}
304-
defer resp.Body.Close()
305-
306-
if resp.StatusCode != http.StatusOK {
307-
return 0, httpError(resp.StatusCode, resp.Body)
308-
}
309-
var provideResult jsontypes.WriteProvidersResponse
310-
err = json.NewDecoder(resp.Body).Decode(&provideResult)
311-
if err != nil {
312-
return 0, err
313-
}
314-
if len(provideResult.ProvideResults) != 1 {
315-
return 0, fmt.Errorf("expected 1 result but got %d", len(provideResult.ProvideResults))
316-
}
317-
318-
v, ok := provideResult.ProvideResults[0].(*types.WriteBitswapProviderRecordResponse)
319-
if !ok {
320-
return 0, fmt.Errorf("expected AdvisoryTTL field")
321-
}
322-
323-
if v.AdvisoryTTL != nil {
324-
return v.AdvisoryTTL.Duration, nil
325-
}
326-
327-
return 0, nil
328-
}
329-
330234
func (c *client) FindIPNSRecord(ctx context.Context, name ipns.Name) (*ipns.Record, error) {
331235
url := c.baseURL + "/routing/v1/ipns/" + name.String()
332236

routing/http/client/client_test.go

-143
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"testing"
1111
"time"
1212

13-
"github.com/benbjohnson/clock"
1413
"github.com/ipfs/boxo/coreiface/path"
1514
ipns "github.com/ipfs/boxo/ipns"
1615
ipfspath "github.com/ipfs/boxo/path"
@@ -22,7 +21,6 @@ import (
2221
"github.com/libp2p/go-libp2p/core/crypto"
2322
"github.com/libp2p/go-libp2p/core/peer"
2423
"github.com/multiformats/go-multiaddr"
25-
"github.com/multiformats/go-multibase"
2624
"github.com/multiformats/go-multihash"
2725
"github.com/stretchr/testify/assert"
2826
"github.com/stretchr/testify/mock"
@@ -36,16 +34,6 @@ func (m *mockContentRouter) FindProviders(ctx context.Context, key cid.Cid, limi
3634
return args.Get(0).(iter.ResultIter[types.ProviderResponse]), args.Error(1)
3735
}
3836

39-
func (m *mockContentRouter) ProvideBitswap(ctx context.Context, req *server.BitswapWriteProvideRequest) (time.Duration, error) {
40-
args := m.Called(ctx, req)
41-
return args.Get(0).(time.Duration), args.Error(1)
42-
}
43-
44-
func (m *mockContentRouter) Provide(ctx context.Context, req *server.WriteProvideRequest) (types.ProviderResponse, error) {
45-
args := m.Called(ctx, req)
46-
return args.Get(0).(types.ProviderResponse), args.Error(1)
47-
}
48-
4937
func (m *mockContentRouter) FindIPNSRecord(ctx context.Context, name ipns.Name) (*ipns.Record, error) {
5038
args := m.Called(ctx, name)
5139
return args.Get(0).(*ipns.Record), args.Error(1)
@@ -151,13 +139,6 @@ func addrsToDRAddrs(addrs []multiaddr.Multiaddr) (drmas []types.Multiaddr) {
151139
return
152140
}
153141

154-
func drAddrsToAddrs(drmas []types.Multiaddr) (addrs []multiaddr.Multiaddr) {
155-
for _, a := range drmas {
156-
addrs = append(addrs, a.Multiaddr)
157-
}
158-
return
159-
}
160-
161142
func makeBSReadProviderResp() types.ReadBitswapProviderRecord {
162143
peerID, addrs, _ := makeProviderAndIdentity()
163144
return types.ReadBitswapProviderRecord{
@@ -333,130 +314,6 @@ func TestClient_FindProviders(t *testing.T) {
333314
}
334315
}
335316

336-
func TestClient_Provide(t *testing.T) {
337-
cases := []struct {
338-
name string
339-
manglePath bool
340-
mangleSignature bool
341-
stopServer bool
342-
noProviderInfo bool
343-
noIdentity bool
344-
345-
cids []cid.Cid
346-
ttl time.Duration
347-
348-
routerAdvisoryTTL time.Duration
349-
routerErr error
350-
351-
expErrContains string
352-
expWinErrContains string
353-
354-
expAdvisoryTTL time.Duration
355-
}{
356-
{
357-
name: "happy case",
358-
cids: []cid.Cid{makeCID()},
359-
ttl: 1 * time.Hour,
360-
routerAdvisoryTTL: 1 * time.Minute,
361-
362-
expAdvisoryTTL: 1 * time.Minute,
363-
},
364-
{
365-
name: "should return a 403 if the payload signature verification fails",
366-
cids: []cid.Cid{},
367-
mangleSignature: true,
368-
expErrContains: "HTTP error with StatusCode=403",
369-
},
370-
{
371-
name: "should return error if identity is not provided",
372-
noIdentity: true,
373-
expErrContains: "cannot provide Bitswap records without an identity",
374-
},
375-
{
376-
name: "should return error if provider is not provided",
377-
noProviderInfo: true,
378-
expErrContains: "cannot provide Bitswap records without a peer ID",
379-
},
380-
{
381-
name: "returns an error if there's a non-200 response",
382-
manglePath: true,
383-
expErrContains: "HTTP error with StatusCode=404: 404 page not found",
384-
},
385-
{
386-
name: "returns an error if the HTTP client returns a non-HTTP error",
387-
stopServer: true,
388-
expErrContains: "connect: connection refused",
389-
expWinErrContains: "connectex: No connection could be made because the target machine actively refused it.",
390-
},
391-
}
392-
for _, c := range cases {
393-
t.Run(c.name, func(t *testing.T) {
394-
deps := makeTestDeps(t, nil, nil)
395-
client := deps.client
396-
router := deps.router
397-
398-
if c.noIdentity {
399-
client.identity = nil
400-
}
401-
if c.noProviderInfo {
402-
client.peerID = ""
403-
client.addrs = nil
404-
}
405-
406-
clock := clock.NewMock()
407-
clock.Set(time.Now())
408-
client.clock = clock
409-
410-
ctx := context.Background()
411-
412-
if c.manglePath {
413-
client.baseURL += "/foo"
414-
}
415-
if c.stopServer {
416-
deps.server.Close()
417-
}
418-
if c.mangleSignature {
419-
client.afterSignCallback = func(req *types.WriteBitswapProviderRecord) {
420-
mh, err := multihash.Encode([]byte("boom"), multihash.SHA2_256)
421-
require.NoError(t, err)
422-
mb, err := multibase.Encode(multibase.Base64, mh)
423-
require.NoError(t, err)
424-
425-
req.Signature = mb
426-
}
427-
}
428-
429-
expectedProvReq := &server.BitswapWriteProvideRequest{
430-
Keys: c.cids,
431-
Timestamp: clock.Now().Truncate(time.Millisecond),
432-
AdvisoryTTL: c.ttl,
433-
Addrs: drAddrsToAddrs(client.addrs),
434-
ID: client.peerID,
435-
}
436-
437-
router.On("ProvideBitswap", mock.Anything, expectedProvReq).
438-
Return(c.routerAdvisoryTTL, c.routerErr)
439-
440-
advisoryTTL, err := client.ProvideBitswap(ctx, c.cids, c.ttl)
441-
442-
var errorString string
443-
if runtime.GOOS == "windows" && c.expWinErrContains != "" {
444-
errorString = c.expWinErrContains
445-
} else {
446-
errorString = c.expErrContains
447-
}
448-
449-
if errorString != "" {
450-
require.ErrorContains(t, err, errorString)
451-
} else {
452-
require.NoError(t, err)
453-
}
454-
455-
assert.Equal(t, c.expAdvisoryTTL, advisoryTTL)
456-
})
457-
}
458-
}
459-
460317
func makeName(t *testing.T) (crypto.PrivKey, ipns.Name) {
461318
sk, _, err := crypto.GenerateEd25519Key(rand.Reader)
462319
require.NoError(t, err)

routing/http/contentrouter/contentrouter.go

+1-38
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,20 @@ import (
55
"reflect"
66
"time"
77

8-
"github.com/ipfs/boxo/routing/http/internal"
98
"github.com/ipfs/boxo/routing/http/types"
109
"github.com/ipfs/boxo/routing/http/types/iter"
1110
"github.com/ipfs/go-cid"
1211
logging "github.com/ipfs/go-log/v2"
1312
"github.com/libp2p/go-libp2p/core/peer"
1413
"github.com/libp2p/go-libp2p/core/routing"
1514
"github.com/multiformats/go-multiaddr"
16-
"github.com/multiformats/go-multihash"
1715
)
1816

1917
var logger = logging.Logger("service/contentrouting")
2018

2119
const ttl = 24 * time.Hour
2220

2321
type Client interface {
24-
ProvideBitswap(ctx context.Context, keys []cid.Cid, ttl time.Duration) (time.Duration, error)
2522
FindProviders(ctx context.Context, key cid.Cid) (iter.ResultIter[types.ProviderResponse], error)
2623
}
2724

@@ -60,41 +57,7 @@ func NewContentRoutingClient(c Client, opts ...option) *contentRouter {
6057
}
6158

6259
func (c *contentRouter) Provide(ctx context.Context, key cid.Cid, announce bool) error {
63-
// If 'true' is
64-
// passed, it also announces it, otherwise it is just kept in the local
65-
// accounting of which objects are being provided.
66-
if !announce {
67-
return nil
68-
}
69-
70-
_, err := c.client.ProvideBitswap(ctx, []cid.Cid{key}, ttl)
71-
return err
72-
}
73-
74-
// ProvideMany provides a set of keys to the remote delegate.
75-
// Large sets of keys are chunked into multiple requests and sent concurrently, according to the concurrency configuration.
76-
// TODO: implement retries through transient errors
77-
func (c *contentRouter) ProvideMany(ctx context.Context, mhKeys []multihash.Multihash) error {
78-
keys := make([]cid.Cid, 0, len(mhKeys))
79-
for _, m := range mhKeys {
80-
keys = append(keys, cid.NewCidV1(cid.Raw, m))
81-
}
82-
83-
if len(keys) <= c.maxProvideBatchSize {
84-
_, err := c.client.ProvideBitswap(ctx, keys, ttl)
85-
return err
86-
}
87-
88-
return internal.DoBatch(
89-
ctx,
90-
c.maxProvideBatchSize,
91-
c.maxProvideConcurrency,
92-
keys,
93-
func(ctx context.Context, batch []cid.Cid) error {
94-
_, err := c.client.ProvideBitswap(ctx, batch, ttl)
95-
return err
96-
},
97-
)
60+
return routing.ErrNotSupported
9861
}
9962

10063
// Ready is part of the existing `ProvideMany` interface.

0 commit comments

Comments
 (0)