Skip to content

Commit 9555624

Browse files
authored
Merge pull request #622 from ipfs/release-v0.21.0
Release v0.21.0
2 parents 980447e + 4eec0e4 commit 9555624

File tree

18 files changed

+612
-338
lines changed

18 files changed

+612
-338
lines changed

.github/workflows/gateway-conformance.yml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
steps:
2323
# 1. Download the gateway-conformance fixtures
2424
- name: Download gateway-conformance fixtures
25-
uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.5
25+
uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.6
2626
with:
2727
output: fixtures
2828
merged: true
@@ -47,15 +47,15 @@ jobs:
4747

4848
# 4. Run the gateway-conformance tests
4949
- name: Run gateway-conformance tests
50-
uses: ipfs/gateway-conformance/.github/actions/test@v0.5
50+
uses: ipfs/gateway-conformance/.github/actions/test@v0.6
5151
with:
5252
gateway-url: http://127.0.0.1:8040
53+
subdomain-url: http://example.net:8040
54+
specs: -trustless-ipns-gateway,-path-ipns-gateway,-subdomain-ipns-gateway,-dnslink-gateway
5355
json: output.json
5456
xml: output.xml
5557
html: output.html
5658
markdown: output.md
57-
subdomain-url: http://example.net
58-
specs: -trustless-ipns-gateway,-path-ipns-gateway,-subdomain-ipns-gateway,-dnslink-gateway
5959

6060
# 5. Upload the results
6161
- name: Upload MD summary
@@ -84,7 +84,7 @@ jobs:
8484
steps:
8585
# 1. Download the gateway-conformance fixtures
8686
- name: Download gateway-conformance fixtures
87-
uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.5
87+
uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.6
8888
with:
8989
output: fixtures
9090
merged: true
@@ -114,16 +114,16 @@ jobs:
114114

115115
# 4. Run the gateway-conformance tests
116116
- name: Run gateway-conformance tests
117-
uses: ipfs/gateway-conformance/.github/actions/test@v0.5
117+
uses: ipfs/gateway-conformance/.github/actions/test@v0.6
118118
with:
119119
gateway-url: http://127.0.0.1:8040 # we test gateway that is backed by a remote block gateway
120+
subdomain-url: http://example.net:8040
121+
specs: -trustless-ipns-gateway,-path-ipns-gateway,-subdomain-ipns-gateway,-dnslink-gateway
122+
args: -skip 'TestGatewayCache/.*_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore'
120123
json: output.json
121124
xml: output.xml
122125
html: output.html
123126
markdown: output.md
124-
subdomain-url: http://example.net
125-
specs: -trustless-ipns-gateway,-path-ipns-gateway,-subdomain-ipns-gateway,-dnslink-gateway
126-
args: -skip 'TestGatewayCache/.*_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore'
127127

128128
# 5. Upload the results
129129
- name: Upload MD summary
@@ -152,7 +152,7 @@ jobs:
152152
steps:
153153
# 1. Download the gateway-conformance fixtures
154154
- name: Download gateway-conformance fixtures
155-
uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.5
155+
uses: ipfs/gateway-conformance/.github/actions/extract-fixtures@v0.6
156156
with:
157157
output: fixtures
158158
merged: true
@@ -182,16 +182,16 @@ jobs:
182182

183183
# 4. Run the gateway-conformance tests
184184
- name: Run gateway-conformance tests
185-
uses: ipfs/gateway-conformance/.github/actions/test@v0.5
185+
uses: ipfs/gateway-conformance/.github/actions/test@v0.6
186186
with:
187187
gateway-url: http://127.0.0.1:8040 # we test gateway that is backed by a remote car gateway
188+
subdomain-url: http://example.net:8040
189+
specs: -trustless-ipns-gateway,-path-ipns-gateway,-subdomain-ipns-gateway,-dnslink-gateway
190+
args: -skip 'TestGatewayCache/.*_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore'
188191
json: output.json
189192
xml: output.xml
190193
html: output.html
191194
markdown: output.md
192-
subdomain-url: http://example.net
193-
specs: -trustless-ipns-gateway,-path-ipns-gateway,-subdomain-ipns-gateway,-dnslink-gateway
194-
args: -skip 'TestGatewayCache/.*_for_%2Fipfs%2F_with_only-if-cached_succeeds_when_in_local_datastore'
195195

196196
# 5. Upload the results
197197
- name: Upload MD summary

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ The following emojis are used to highlight certain changes:
2424

2525
### Security
2626

27+
## [v0.21.0]
28+
29+
### Changed
30+
31+
- `boxo/gateway` is now tested against [gateway-conformance v6](https://github.com/ipfs/gateway-conformance/releases/tag/v0.6.0)
32+
- `bitswap/client` supports additional tracing
33+
34+
### Removed
35+
36+
* 🛠 `routing/none` removed `ConstructNilRouting`, if you need this functionality you can use the Null Router from [go-libp2p-routing-helpers](https://github.com/libp2p/go-libp2p-routing-helpers).
37+
38+
### Fixed
39+
40+
- `routing/http`: the `FindPeer` now returns `routing.ErrNotFound` when no addresses are found
41+
- `routing/http`: the `FindProvidersAsync` no longer causes a goroutine buildup
42+
2743
## [v0.20.0]
2844

2945
### Added

bitswap/client/internal/providerquerymanager/providerquerymanager.go

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package providerquerymanager
22

33
import (
44
"context"
5-
"fmt"
65
"sync"
76
"time"
87

8+
"github.com/ipfs/boxo/bitswap/client/internal"
99
"github.com/ipfs/go-cid"
1010
logging "github.com/ipfs/go-log/v2"
1111
peer "github.com/libp2p/go-libp2p/core/peer"
12+
"go.opentelemetry.io/otel/attribute"
13+
"go.opentelemetry.io/otel/trace"
1214
)
1315

1416
var log = logging.Logger("bitswap")
@@ -39,7 +41,7 @@ type ProviderQueryNetwork interface {
3941
}
4042

4143
type providerQueryMessage interface {
42-
debugMessage() string
44+
debugMessage()
4345
handle(pqm *ProviderQueryManager)
4446
}
4547

@@ -61,6 +63,7 @@ type newProvideQueryMessage struct {
6163
}
6264

6365
type cancelRequestMessage struct {
66+
ctx context.Context
6467
incomingProviders chan peer.ID
6568
k cid.Cid
6669
}
@@ -121,6 +124,10 @@ func (pqm *ProviderQueryManager) SetFindProviderTimeout(findProviderTimeout time
121124
func (pqm *ProviderQueryManager) FindProvidersAsync(sessionCtx context.Context, k cid.Cid) <-chan peer.ID {
122125
inProgressRequestChan := make(chan inProgressRequest)
123126

127+
var span trace.Span
128+
sessionCtx, span = internal.StartSpan(sessionCtx, "ProviderQueryManager.FindProvidersAsync", trace.WithAttributes(attribute.Stringer("cid", k)))
129+
defer span.End()
130+
124131
select {
125132
case pqm.providerQueryMessages <- &newProvideQueryMessage{
126133
ctx: sessionCtx,
@@ -182,7 +189,7 @@ func (pqm *ProviderQueryManager) receiveProviders(sessionCtx context.Context, k
182189
return
183190
case <-sessionCtx.Done():
184191
if incomingProviders != nil {
185-
pqm.cancelProviderRequest(k, incomingProviders)
192+
pqm.cancelProviderRequest(sessionCtx, k, incomingProviders)
186193
}
187194
return
188195
case provider, ok := <-incomingProviders:
@@ -199,11 +206,12 @@ func (pqm *ProviderQueryManager) receiveProviders(sessionCtx context.Context, k
199206
return returnedProviders
200207
}
201208

202-
func (pqm *ProviderQueryManager) cancelProviderRequest(k cid.Cid, incomingProviders chan peer.ID) {
209+
func (pqm *ProviderQueryManager) cancelProviderRequest(ctx context.Context, k cid.Cid, incomingProviders chan peer.ID) {
203210
cancelMessageChannel := pqm.providerQueryMessages
204211
for {
205212
select {
206213
case cancelMessageChannel <- &cancelRequestMessage{
214+
ctx: ctx,
207215
incomingProviders: incomingProviders,
208216
k: k,
209217
}:
@@ -235,17 +243,22 @@ func (pqm *ProviderQueryManager) findProviderWorker() {
235243
pqm.timeoutMutex.RLock()
236244
findProviderCtx, cancel := context.WithTimeout(fpr.ctx, pqm.findProviderTimeout)
237245
pqm.timeoutMutex.RUnlock()
246+
span := trace.SpanFromContext(findProviderCtx)
247+
span.AddEvent("StartFindProvidersAsync")
238248
providers := pqm.network.FindProvidersAsync(findProviderCtx, k, maxProviders)
239249
wg := &sync.WaitGroup{}
240250
for p := range providers {
241251
wg.Add(1)
242252
go func(p peer.ID) {
243253
defer wg.Done()
254+
span.AddEvent("FoundProvider", trace.WithAttributes(attribute.Stringer("peer", p)))
244255
err := pqm.network.ConnectTo(findProviderCtx, p)
245256
if err != nil {
257+
span.RecordError(err, trace.WithAttributes(attribute.Stringer("peer", p)))
246258
log.Debugf("failed to connect to provider %s: %s", p, err)
247259
return
248260
}
261+
span.AddEvent("ConnectedToProvider", trace.WithAttributes(attribute.Stringer("peer", p)))
249262
select {
250263
case pqm.providerQueryMessages <- &receivedProviderMessage{
251264
ctx: findProviderCtx,
@@ -326,16 +339,17 @@ func (pqm *ProviderQueryManager) run() {
326339
for {
327340
select {
328341
case nextMessage := <-pqm.providerQueryMessages:
329-
log.Debug(nextMessage.debugMessage())
342+
nextMessage.debugMessage()
330343
nextMessage.handle(pqm)
331344
case <-pqm.ctx.Done():
332345
return
333346
}
334347
}
335348
}
336349

337-
func (rpm *receivedProviderMessage) debugMessage() string {
338-
return fmt.Sprintf("Received provider (%s) for cid (%s)", rpm.p.String(), rpm.k.String())
350+
func (rpm *receivedProviderMessage) debugMessage() {
351+
log.Debugf("Received provider (%s) (%s)", rpm.p, rpm.k)
352+
trace.SpanFromContext(rpm.ctx).AddEvent("ReceivedProvider", trace.WithAttributes(attribute.Stringer("provider", rpm.p), attribute.Stringer("cid", rpm.k)))
339353
}
340354

341355
func (rpm *receivedProviderMessage) handle(pqm *ProviderQueryManager) {
@@ -354,8 +368,9 @@ func (rpm *receivedProviderMessage) handle(pqm *ProviderQueryManager) {
354368
}
355369
}
356370

357-
func (fpqm *finishedProviderQueryMessage) debugMessage() string {
358-
return "Finished Provider Query on cid: " + fpqm.k.String()
371+
func (fpqm *finishedProviderQueryMessage) debugMessage() {
372+
log.Debugf("Finished Provider Query on cid: %s", fpqm.k)
373+
trace.SpanFromContext(fpqm.ctx).AddEvent("FinishedProviderQuery", trace.WithAttributes(attribute.Stringer("cid", fpqm.k)))
359374
}
360375

361376
func (fpqm *finishedProviderQueryMessage) handle(pqm *ProviderQueryManager) {
@@ -371,21 +386,28 @@ func (fpqm *finishedProviderQueryMessage) handle(pqm *ProviderQueryManager) {
371386
requestStatus.cancelFn()
372387
}
373388

374-
func (npqm *newProvideQueryMessage) debugMessage() string {
375-
return "New Provider Query on cid: " + npqm.k.String()
389+
func (npqm *newProvideQueryMessage) debugMessage() {
390+
log.Debugf("New Provider Query on cid: %s", npqm.k)
391+
trace.SpanFromContext(npqm.ctx).AddEvent("NewProvideQuery", trace.WithAttributes(attribute.Stringer("cid", npqm.k)))
376392
}
377393

378394
func (npqm *newProvideQueryMessage) handle(pqm *ProviderQueryManager) {
379395
requestStatus, ok := pqm.inProgressRequestStatuses[npqm.k]
380396
if !ok {
381397

382398
ctx, cancelFn := context.WithCancel(pqm.ctx)
399+
span := trace.SpanFromContext(npqm.ctx)
400+
span.AddEvent("NewQuery", trace.WithAttributes(attribute.Stringer("cid", npqm.k)))
401+
ctx = trace.ContextWithSpan(ctx, span)
402+
383403
requestStatus = &inProgressRequestStatus{
384404
listeners: make(map[chan peer.ID]struct{}),
385405
ctx: ctx,
386406
cancelFn: cancelFn,
387407
}
408+
388409
pqm.inProgressRequestStatuses[npqm.k] = requestStatus
410+
389411
select {
390412
case pqm.incomingFindProviderRequests <- &findProviderRequest{
391413
k: npqm.k,
@@ -394,6 +416,8 @@ func (npqm *newProvideQueryMessage) handle(pqm *ProviderQueryManager) {
394416
case <-pqm.ctx.Done():
395417
return
396418
}
419+
} else {
420+
trace.SpanFromContext(npqm.ctx).AddEvent("JoinQuery", trace.WithAttributes(attribute.Stringer("cid", npqm.k)))
397421
}
398422
inProgressChan := make(chan peer.ID)
399423
requestStatus.listeners[inProgressChan] = struct{}{}
@@ -406,8 +430,9 @@ func (npqm *newProvideQueryMessage) handle(pqm *ProviderQueryManager) {
406430
}
407431
}
408432

409-
func (crm *cancelRequestMessage) debugMessage() string {
410-
return "Cancel provider query on cid: " + crm.k.String()
433+
func (crm *cancelRequestMessage) debugMessage() {
434+
log.Debugf("Cancel provider query on cid: %s", crm.k)
435+
trace.SpanFromContext(crm.ctx).AddEvent("CancelRequest", trace.WithAttributes(attribute.Stringer("cid", crm.k)))
411436
}
412437

413438
func (crm *cancelRequestMessage) handle(pqm *ProviderQueryManager) {

bitswap/client/internal/session/session.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
delay "github.com/ipfs/go-ipfs-delay"
1616
logging "github.com/ipfs/go-log/v2"
1717
peer "github.com/libp2p/go-libp2p/core/peer"
18+
"go.opentelemetry.io/otel/trace"
1819
"go.uber.org/zap"
1920
)
2021

@@ -301,35 +302,46 @@ func (s *Session) run(ctx context.Context) {
301302

302303
s.idleTick = time.NewTimer(s.initialSearchDelay)
303304
s.periodicSearchTimer = time.NewTimer(s.periodicSearchDelay.NextWaitTime())
305+
sessionSpan := trace.SpanFromContext(ctx)
304306
for {
305307
select {
306308
case oper := <-s.incoming:
307309
switch oper.op {
308310
case opReceive:
309311
// Received blocks
312+
sessionSpan.AddEvent("Session.ReceiveOp")
310313
s.handleReceive(oper.keys)
311314
case opWant:
312315
// Client wants blocks
316+
sessionSpan.AddEvent("Session.WantOp")
313317
s.wantBlocks(ctx, oper.keys)
314318
case opCancel:
315319
// Wants were cancelled
320+
sessionSpan.AddEvent("Session.WantCancelOp")
316321
s.sw.CancelPending(oper.keys)
317322
s.sws.Cancel(oper.keys)
318323
case opWantsSent:
319324
// Wants were sent to a peer
325+
sessionSpan.AddEvent("Session.WantsSentOp")
320326
s.sw.WantsSent(oper.keys)
321327
case opBroadcast:
322328
// Broadcast want-haves to all peers
323-
s.broadcast(ctx, oper.keys)
329+
opCtx, span := internal.StartSpan(ctx, "Session.BroadcastOp")
330+
s.broadcast(opCtx, oper.keys)
331+
span.End()
324332
default:
325333
panic("unhandled operation")
326334
}
327335
case <-s.idleTick.C:
328336
// The session hasn't received blocks for a while, broadcast
329-
s.broadcast(ctx, nil)
337+
opCtx, span := internal.StartSpan(ctx, "Session.IdleBroadcast")
338+
s.broadcast(opCtx, nil)
339+
span.End()
330340
case <-s.periodicSearchTimer.C:
331341
// Periodically search for a random live want
332-
s.handlePeriodicSearch(ctx)
342+
opCtx, span := internal.StartSpan(ctx, "Session.PeriodicSearch")
343+
s.handlePeriodicSearch(opCtx)
344+
span.End()
333345
case baseTickDelay := <-s.tickDelayReqs:
334346
// Set the base tick delay
335347
s.baseTickDelay = baseTickDelay
@@ -392,9 +404,12 @@ func (s *Session) handlePeriodicSearch(ctx context.Context) {
392404
// providers for the given Cid
393405
func (s *Session) findMorePeers(ctx context.Context, c cid.Cid) {
394406
go func(k cid.Cid) {
407+
ctx, span := internal.StartSpan(ctx, "Session.FindMorePeers")
408+
defer span.End()
395409
for p := range s.providerFinder.FindProvidersAsync(ctx, k) {
396410
// When a provider indicates that it has a cid, it's equivalent to
397411
// the providing peer sending a HAVE
412+
span.AddEvent("FoundPeer")
398413
s.sws.Update(p, nil, []cid.Cid{c}, nil)
399414
}
400415
}(c)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
car-file-fetcher
2+
fetcher
3+
hello.txt
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# CAR File Fetcher
2+
3+
This example shows how to download a UnixFS file or directory from a gateway that implements
4+
[application/vnd.ipld.car](https://www.iana.org/assignments/media-types/application/vnd.ipld.car)
5+
responses of the [Trustles Gateway](https://specs.ipfs.tech/http-gateways/trustless-gateway/)
6+
specification, in a trustless, verifiable manner.
7+
8+
It relies on [IPIP-402](https://specs.ipfs.tech/ipips/ipip-0402/) to retrieve
9+
the file entity via a single CAR request with all blocks required for end-to-end
10+
verification.
11+
12+
## Build
13+
14+
```bash
15+
> go build -o fetcher
16+
```
17+
18+
## Usage
19+
20+
First, you need a gateway that complies with the Trustless Gateway specification.
21+
In our specific case, we need that the gateway supports CAR response type.
22+
23+
As an example, you can verifiably fetch a `hello.txt` file from IPFS gateway at `https://trustless-gateway.link`:
24+
25+
```
26+
./fetcher -g https://trustless-gateway.link -o hello.txt /ipfs/bafkreifzjut3te2nhyekklss27nh3k72ysco7y32koao5eei66wof36n5e
27+
```
107 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)