From 9d047f038db52d2b8013761b3918c740ed933fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 23 Jan 2025 17:12:26 +0100 Subject: [PATCH] container: Reader should keep around and expose the sealed bytes --- pkg/container/reader.go | 83 +++++++++++++++---- .../delegationtest/generator/generator.go | 3 +- token/delegation/delegationtest/token.go | 9 +- token/delegation/delegationtest/token_gen.go | 3 +- token/delegation/utilities.go | 7 -- token/interface.go | 7 ++ 6 files changed, 83 insertions(+), 29 deletions(-) diff --git a/pkg/container/reader.go b/pkg/container/reader.go index 085e1ca..a469671 100644 --- a/pkg/container/reader.go +++ b/pkg/container/reader.go @@ -21,7 +21,12 @@ var ErrNotFound = fmt.Errorf("not found") var ErrMultipleInvocations = fmt.Errorf("multiple invocations") // Reader is a token container reader. It exposes the tokens conveniently decoded. -type Reader map[cid.Cid]token.Token +type Reader map[cid.Cid]bundle + +type bundle struct { + sealed []byte + token token.Token +} // FromBytes decodes a container from a []byte func FromBytes(data []byte) (Reader, error) { @@ -92,11 +97,36 @@ func FromReader(r io.Reader) (Reader, error) { // GetToken returns an arbitrary decoded token, from its CID. // If not found, ErrNotFound is returned. func (ctn Reader) GetToken(cid cid.Cid) (token.Token, error) { - tkn, ok := ctn[cid] + bndl, ok := ctn[cid] if !ok { return nil, ErrNotFound } - return tkn, nil + return bndl.token, nil +} + +// GetSealed returns an arbitrary sealed token, from its CID. +// If not found, ErrNotFound is returned. +func (ctn Reader) GetSealed(cid cid.Cid) ([]byte, error) { + bndl, ok := ctn[cid] + if !ok { + return nil, ErrNotFound + } + return bndl.sealed, nil +} + +// GetAllTokens return all the tokens in the container. +func (ctn Reader) GetAllTokens() iter.Seq[token.Bundle[token.Token]] { + return func(yield func(token.Bundle[token.Token]) bool) { + for c, bndl := range ctn { + if !yield(token.Bundle[token.Token]{ + Cid: c, + Decoded: bndl.token, + Sealed: bndl.sealed, + }) { + return + } + } + } } // GetDelegation is the same as GetToken but only return a delegation.Token, with the right type. @@ -113,11 +143,15 @@ func (ctn Reader) GetDelegation(cid cid.Cid) (*delegation.Token, error) { } // GetAllDelegations returns all the delegation.Token in the container. -func (ctn Reader) GetAllDelegations() iter.Seq2[cid.Cid, *delegation.Token] { - return func(yield func(cid.Cid, *delegation.Token) bool) { - for c, t := range ctn { - if t, ok := t.(*delegation.Token); ok { - if !yield(c, t) { +func (ctn Reader) GetAllDelegations() iter.Seq[token.Bundle[*delegation.Token]] { + return func(yield func(token.Bundle[*delegation.Token]) bool) { + for c, bndl := range ctn { + if t, ok := bndl.token.(*delegation.Token); ok { + if !yield(token.Bundle[*delegation.Token]{ + Cid: c, + Decoded: t, + Sealed: bndl.sealed, + }) { return } } @@ -130,8 +164,8 @@ func (ctn Reader) GetAllDelegations() iter.Seq2[cid.Cid, *delegation.Token] { // If more than one invocation exists, ErrMultipleInvocations is returned. func (ctn Reader) GetInvocation() (*invocation.Token, error) { var res *invocation.Token - for _, t := range ctn { - if inv, ok := t.(*invocation.Token); ok { + for _, bndl := range ctn { + if inv, ok := bndl.token.(*invocation.Token); ok { if res != nil { return nil, ErrMultipleInvocations } @@ -145,11 +179,15 @@ func (ctn Reader) GetInvocation() (*invocation.Token, error) { } // GetAllInvocations returns all the invocation.Token in the container. -func (ctn Reader) GetAllInvocations() iter.Seq2[cid.Cid, *invocation.Token] { - return func(yield func(cid.Cid, *invocation.Token) bool) { - for c, t := range ctn { - if t, ok := t.(*invocation.Token); ok { - if !yield(c, t) { +func (ctn Reader) GetAllInvocations() iter.Seq[token.Bundle[*invocation.Token]] { + return func(yield func(token.Bundle[*invocation.Token]) bool) { + for c, bndl := range ctn { + if t, ok := bndl.token.(*invocation.Token); ok { + if !yield(token.Bundle[*invocation.Token]{ + Cid: c, + Decoded: t, + Sealed: bndl.sealed, + }) { return } } @@ -162,6 +200,19 @@ func (ctn Reader) addToken(data []byte) error { if err != nil { return err } - ctn[c] = tkn + ctn[c] = bundle{ + sealed: data, + token: tkn, + } return nil } + +// ToWriter convert a container Reader into a Writer. +// Most likely, you only want to use this in tests for convenience. +func (ctn Reader) ToWriter() Writer { + writer := NewWriter() + for _, bndl := range ctn { + writer.AddSealed(bndl.sealed) + } + return writer +} diff --git a/token/delegation/delegationtest/generator/generator.go b/token/delegation/delegationtest/generator/generator.go index 1f4a4ef..7f8b1f4 100644 --- a/token/delegation/delegationtest/generator/generator.go +++ b/token/delegation/delegationtest/generator/generator.go @@ -217,6 +217,7 @@ func (g *generator) writeGoFile() error { Println("import (") Println("\t\"github.com/ipfs/go-cid\"") Println() + Println("\t\"github.com/ucan-wg/go-ucan/token\"") Println("\t\"github.com/ucan-wg/go-ucan/token/delegation\"") Println(")") @@ -242,7 +243,7 @@ func (g *generator) writeGoFile() error { Println("}") Println() - Println("var AllBundles = []*delegation.Bundle{") + Println("var AllBundles = []token.Bundle[*delegation.Token]{") for _, d := range g.dlgs { Printf("\t%sBundle,\n", d.name) } diff --git a/token/delegation/delegationtest/token.go b/token/delegation/delegationtest/token.go index 89bb3ef..7d1b280 100644 --- a/token/delegation/delegationtest/token.go +++ b/token/delegation/delegationtest/token.go @@ -8,6 +8,7 @@ import ( "github.com/ipfs/go-cid" "github.com/ucan-wg/go-ucan/pkg/command" + "github.com/ucan-wg/go-ucan/token" "github.com/ucan-wg/go-ucan/token/delegation" ) @@ -38,7 +39,7 @@ var fs embed.FS var _ delegation.Loader = (*DelegationLoader)(nil) type DelegationLoader struct { - bundles map[cid.Cid]*delegation.Bundle + bundles map[cid.Cid]token.Bundle[*delegation.Token] } var ( @@ -75,7 +76,7 @@ func loadDelegations() (*DelegationLoader, error) { return nil, err } - bundles := make(map[cid.Cid]*delegation.Bundle, len(dirEntries)) + bundles := make(map[cid.Cid]token.Bundle[*delegation.Token], len(dirEntries)) for _, dirEntry := range dirEntries { data, err := fs.ReadFile(filepath.Join(TokenDir, dirEntry.Name())) @@ -88,7 +89,7 @@ func loadDelegations() (*DelegationLoader, error) { return nil, err } - bundles[id] = &delegation.Bundle{Cid: id, Decoded: tkn, Sealed: data} + bundles[id] = token.Bundle[*delegation.Token]{Cid: id, Decoded: tkn, Sealed: data} } return &DelegationLoader{ @@ -106,7 +107,7 @@ func CidToName(id cid.Cid) string { return cidToName[id] } -func mustGetBundle(id cid.Cid) *delegation.Bundle { +func mustGetBundle(id cid.Cid) token.Bundle[*delegation.Token] { bundle, ok := GetDelegationLoader().bundles[id] if !ok { panic(delegation.ErrDelegationNotFound) diff --git a/token/delegation/delegationtest/token_gen.go b/token/delegation/delegationtest/token_gen.go index e5a924e..4c1c217 100644 --- a/token/delegation/delegationtest/token_gen.go +++ b/token/delegation/delegationtest/token_gen.go @@ -5,6 +5,7 @@ package delegationtest import ( "github.com/ipfs/go-cid" + "github.com/ucan-wg/go-ucan/token" "github.com/ucan-wg/go-ucan/token/delegation" ) @@ -195,7 +196,7 @@ var AllTokens = []*delegation.Token{ TokenErinFrank_ValidExamplePolicy, } -var AllBundles = []*delegation.Bundle{ +var AllBundles = []token.Bundle[*delegation.Token]{ TokenAliceBobBundle, TokenBobCarolBundle, TokenCarolDanBundle, diff --git a/token/delegation/utilities.go b/token/delegation/utilities.go index 957ca9d..13dd81d 100644 --- a/token/delegation/utilities.go +++ b/token/delegation/utilities.go @@ -15,10 +15,3 @@ type Loader interface { // If not found, ErrDelegationNotFound is returned. GetDelegation(cid cid.Cid) (*Token, error) } - -// Bundle carries together a decoded delegation with its Cid and raw signed data. -type Bundle struct { - Cid cid.Cid - Decoded *Token - Sealed []byte -} diff --git a/token/interface.go b/token/interface.go index b3a8d21..08e86f9 100644 --- a/token/interface.go +++ b/token/interface.go @@ -39,3 +39,10 @@ type Marshaller interface { // ToDagJsonWriter is the same as ToDagJson, but it accepts an io.Writer. ToDagJsonWriter(w io.Writer, privKey crypto.PrivKey) error } + +// Bundle carries together a decoded token with its Cid and raw signed data. +type Bundle[T Token] struct { + Cid cid.Cid + Decoded T + Sealed []byte +}