Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions cmd/retrieve.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"context"
"fmt"
"io"
"io/fs"
Expand All @@ -10,9 +11,14 @@ import (
"github.com/mitchellh/go-wordwrap"
"github.com/spf13/cobra"
contentcap "github.com/storacha/go-libstoracha/capabilities/space/content"
"github.com/storacha/go-libstoracha/principalresolver"
"github.com/storacha/go-ucanto/core/delegation"
"github.com/storacha/go-ucanto/did"
edverifier "github.com/storacha/go-ucanto/principal/ed25519/verifier"
"github.com/storacha/go-ucanto/principal/verifier"
"github.com/storacha/go-ucanto/server"
"github.com/storacha/go-ucanto/ucan"
"github.com/storacha/go-ucanto/validator"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
Expand All @@ -25,6 +31,11 @@ import (
"github.com/storacha/guppy/pkg/dagfs"
)

func init() {
retrieveCmd.Flags().StringP("network", "n", "", "Network to retrieve content from.")
retrieveCmd.Flags().MarkHidden("network")
}

var retrieveCmd = &cobra.Command{
Use: "retrieve <space> <content-path> <output-path>",
Aliases: []string{"get"},
Expand Down Expand Up @@ -79,6 +90,13 @@ var retrieveCmd = &cobra.Command{
}
}()

networkName, _ := cmd.Flags().GetString("network")
network := cmdutil.MustGetNetworkConfig(networkName)
pruningCtx, err := buildPruningContext(ctx, network.UploadID)
if err != nil {
return err
}

locator := locator.NewIndexLocator(indexer, func(spaces []did.DID) (delegation.Delegation, error) {
queries := make([]agentstore.CapabilityQuery, 0, len(spaces))
for _, space := range spaces {
Expand All @@ -98,6 +116,24 @@ var retrieveCmd = &cobra.Command{
}

// Allow the indexing service to retrieve indexes
// Prune proofs from the delegation to avoid sending large delegations to the indexer
draftDlg, err := contentcap.Retrieve.Delegate(
c.Issuer(),
indexerPrincipal,
space.DID().String(),
contentcap.RetrieveCaveats{},
delegation.WithProof(pfs...),
delegation.WithExpiration(int(time.Now().Add(30*time.Second).Unix())),
)
if err != nil {
return nil, fmt.Errorf("creating delegation to indexer: %w", err)
}

pfs, unauth := validator.PruneProofs(ctx, draftDlg, pruningCtx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should pruning be part of the client.Proofs(...) call? Perhaps as an option?

If no then please can we also add this to the gateway command?

return delegation.Delegate(c.Issuer(), indexerPrincipal, caps, opts...)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we not use SelectProofs instead? It's a waste of work to create and sign a delegation that is subsequently thrown away.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should pruning be part of the client.Proofs(...) call? Perhaps as an option?

If no then please can we also add this to the gateway command?

I think leaving client.Proofs as just a "query and filter proofs from store" API is cleaner. I added pruning to the gateway serve command.

Why do we not use SelectProofs instead? It's a waste of work to create and sign a delegation that is subsequently thrown away.

Is this reply satisfactory?

if unauth != nil {
return nil, unauth
}

return delegation.Delegate(
c.Issuer(),
indexerPrincipal,
Expand Down Expand Up @@ -151,3 +187,40 @@ var retrieveCmd = &cobra.Command{
return nil
},
}

func buildPruningContext(ctx context.Context, attestorDID did.DID) (validator.ValidationContext[contentcap.RetrieveCaveats], error) {
resolver, err := principalresolver.NewHTTPResolver([]did.DID{attestorDID})
if err != nil {
return nil, fmt.Errorf("creating principal resolver: %w", err)
}

resolvedKeyDID, unresolvedErr := resolver.ResolveDIDKey(ctx, attestorDID)
if unresolvedErr != nil {
return nil, fmt.Errorf("resolving attestor DID key: %w", unresolvedErr)
}

keyVerifier, err := edverifier.Parse(resolvedKeyDID.String())
if err != nil {
return nil, fmt.Errorf("parsing resolved key DID: %w", err)
}

attestor, err := verifier.Wrap(keyVerifier, attestorDID)
if err != nil {
return nil, fmt.Errorf("creating attestor verifier: %w", err)
}

return validator.NewValidationContext(
// For client evaluated chains, the authority must be the service that issued the ucan/attest
// delegations — e.g. the upload-service.
attestor,
contentcap.Retrieve,
validator.IsSelfIssued,
func(context.Context, validator.Authorization[any]) validator.Revoked {
return nil
},
validator.ProofUnavailable,
server.ParsePrincipal,
validator.FailDIDKeyResolution,
validator.NotExpiredNotTooEarly,
), nil
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module github.com/storacha/guppy

go 1.25.3

replace github.com/storacha/go-ucanto => ../go-ucanto
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will update this reference when the changes are merged and tagged in go-ucanto. CI builds will fail till then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can refer to the commit by sha instead, and CI should work. (Waiting to merge until that's pointing to a real release is still a good idea, though, even if we haven't been consistent about that.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the CI screaming at me so that I don't forget 😅


require (
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef
github.com/briandowns/spinner v1.23.2
Expand Down Expand Up @@ -115,6 +117,7 @@ require (
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
github.com/multiformats/go-multistream v0.6.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/paulmach/orb v0.11.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
Expand Down Expand Up @@ -794,8 +796,6 @@ github.com/storacha/go-fil-commp-hashhash v0.0.0-20251204184521-dc48123eb846 h1:
github.com/storacha/go-fil-commp-hashhash v0.0.0-20251204184521-dc48123eb846/go.mod h1:YbWvDVjuho1gx+xQNrbM95NNWnJ4oAy067mY5t5F0Bw=
github.com/storacha/go-libstoracha v0.7.3 h1:4X9XI0djmURhhabakvmRUy2NUq40Z04ns6NLTY8TmQ8=
github.com/storacha/go-libstoracha v0.7.3/go.mod h1:htUh/VZ0qHRLPJKWZsgXv9mCOqlAFGTVS//ApvQVNf0=
github.com/storacha/go-ucanto v0.7.3-0.20260217160605-b36b2fa2b6fc h1:zojq5HkvwbPGFpPQ4QokEJlScNLZlOc4fkj/QVigYrM=
github.com/storacha/go-ucanto v0.7.3-0.20260217160605-b36b2fa2b6fc/go.mod h1:DZlWyzuSkXk3phAuJpGDyhxYWpJogW1RFqp/VfldT64=
github.com/storacha/indexing-service v1.12.2 h1:DrcIzvM36Ux7i0UmGoSZiU8lR8WjVIqsTULSE1kA+7I=
github.com/storacha/indexing-service v1.12.2/go.mod h1:Yk+uHoTA6qaTE13Ptq6FArsR9hESOetzej9194KwjhM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
Loading