diff --git a/authority_options.go b/authority_options.go new file mode 100644 index 0000000..a8fae43 --- /dev/null +++ b/authority_options.go @@ -0,0 +1,74 @@ +package ucan + +// Code generated by github.com/launchdarkly/go-options. DO NOT EDIT. + +import "fmt" + +import ( + "time" +) + +type ApplyAuthorityOptionFunc func(c *authorityConfig) error + +func (f ApplyAuthorityOptionFunc) apply(c *authorityConfig) error { + return f(c) +} + +func applyAuthorityConfigOptions(c *authorityConfig, options ...AuthorityOption) error { + for _, o := range options { + if err := o.apply(c); err != nil { + return err + } + } + return nil +} + +type AuthorityOption interface { + apply(*authorityConfig) error +} + +type withExpirationImpl struct { + o time.Duration +} + +func (o withExpirationImpl) apply(c *authorityConfig) error { + c.expiration = o.o + return nil +} + +func (o withExpirationImpl) String() string { + name := "WithExpiration" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithExpiration(o time.Duration) AuthorityOption { + return withExpirationImpl{ + o: o, + } +} + +type withNonceLengthImpl struct { + o int +} + +func (o withNonceLengthImpl) apply(c *authorityConfig) error { + c.nonceLength = o.o + return nil +} + +func (o withNonceLengthImpl) String() string { + name := "WithNonceLength" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithNonceLength(o int) AuthorityOption { + return withNonceLengthImpl{ + o: o, + } +} diff --git a/delegation/delegatiom_options.go b/delegation/delegatiom_options.go new file mode 100644 index 0000000..7ac5d47 --- /dev/null +++ b/delegation/delegatiom_options.go @@ -0,0 +1,174 @@ +package delegation + +// Code generated by github.com/launchdarkly/go-options. DO NOT EDIT. + +import "fmt" + +import ( + "github.com/ucan-wg/go-ucan/v1/did" + "time" +) + +type ApplyOptionFunc func(c *config) error + +func (f ApplyOptionFunc) apply(c *config) error { + return f(c) +} + +func newConfig(options ...Option) (config, error) { + var c config + err := applyConfigOptions(&c, options...) + return c, err +} + +func applyConfigOptions(c *config, options ...Option) error { + for _, o := range options { + if err := o.apply(c); err != nil { + return err + } + } + return nil +} + +type Option interface { + apply(*config) error +} + +type withExpirationImpl struct { + o *time.Time +} + +func (o withExpirationImpl) apply(c *config) error { + c.Expiration = o.o + return nil +} + +func (o withExpirationImpl) String() string { + name := "WithExpiration" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithExpiration(o *time.Time) Option { + return withExpirationImpl{ + o: o, + } +} + +type withMetaImpl struct { + o map[string]any +} + +func (o withMetaImpl) apply(c *config) error { + c.Meta = o.o + return nil +} + +func (o withMetaImpl) String() string { + name := "WithMeta" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithMeta(o map[string]any) Option { + return withMetaImpl{ + o: o, + } +} + +type withNoExpirationImpl struct { + o bool +} + +func (o withNoExpirationImpl) apply(c *config) error { + c.NoExpiration = o.o + return nil +} + +func (o withNoExpirationImpl) String() string { + name := "WithNoExpiration" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithNoExpiration(o bool) Option { + return withNoExpirationImpl{ + o: o, + } +} + +type withNotBeforeImpl struct { + o *time.Time +} + +func (o withNotBeforeImpl) apply(c *config) error { + c.NotBefore = o.o + return nil +} + +func (o withNotBeforeImpl) String() string { + name := "WithNotBefore" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithNotBefore(o *time.Time) Option { + return withNotBeforeImpl{ + o: o, + } +} + +type withSubjectImpl struct { + o *did.DID +} + +func (o withSubjectImpl) apply(c *config) error { + c.Subject = o.o + return nil +} + +func (o withSubjectImpl) String() string { + name := "WithSubject" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +// WithSubject is a did.DID representing the Subject. +func WithSubject(o *did.DID) Option { + return withSubjectImpl{ + o: o, + } +} + +type withPowerlineImpl struct { + o bool +} + +func (o withPowerlineImpl) apply(c *config) error { + c.Powerline = o.o + return nil +} + +func (o withPowerlineImpl) String() string { + name := "WithPowerline" + + // hack to avoid go vet error about passing a function to Sprintf + var value interface{} = o.o + return fmt.Sprintf("%s: %+v", name, value) +} + +func WithPowerline(o bool) Option { + return withPowerlineImpl{ + o: o, + } +} diff --git a/delegation/delegation.go b/delegation/delegation.go new file mode 100644 index 0000000..1666076 --- /dev/null +++ b/delegation/delegation.go @@ -0,0 +1,110 @@ +package delegation + +import ( + "time" + + "github.com/ipld/go-ipld-prime/datamodel" + "github.com/ipld/go-ipld-prime/node/bindnode" + "github.com/ipld/go-ipld-prime/schema" + "github.com/ucan-wg/go-ucan/v1/capability/command" + "github.com/ucan-wg/go-ucan/v1/capability/policy" + "github.com/ucan-wg/go-ucan/v1/did" + "github.com/ucan-wg/go-ucan/v1/internal/envelope" + "github.com/ucan-wg/go-ucan/v1/internal/token" +) + +const ( + Tag = "ucan/dlg@" +) + +//go:generate -command options go run github.com/launchdarkly/go-options +//go:generate options -type=config -prefix=With -output=delegatiom_options.go -cmp=false -imports=time,github.com/ucan-wg/go-ucan/v1/did + +type config struct { + Expiration *time.Time + Meta map[string]any + NoExpiration bool + NotBefore *time.Time + // is a did.DID representing the Subject. + Subject *did.DID + Powerline bool +} + +type Meta struct { + Keys []string + Values map[string]datamodel.Node +} + +func NewMeta(meta map[string]any) Meta { + keys := make([]string, len(meta)) + values := make(map[string]datamodel.Node, len(meta)) + i := 0 + + for k, v := range meta { + keys[i] = k + values[k] = bindnode.Wrap(&v, nil) + } + + return Meta{ + Keys: keys, + Values: values, + } +} + +var _ envelope.Tokener = (*Token)(nil) + +type Token struct { + // Issuer DID (sender) + Issuer did.DID + // Audience DID (receiver) + Audience did.DID + // Principal that the chain is about (the Subject) + Subject *did.DID + // The Command to eventually invoke + Command *command.Command + // The delegation policy + Policy *policy.Policy + // A unique, random nonce + Nonce []byte + // Arbitrary Metadata + Meta Meta + // "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer + NotBefore *time.Time + // The timestamp at which the Invocation becomes invalid + Expiration *time.Time +} + +func New(iss did.DID, aud did.DID, prf []Token, cmd *command.Command, pol *policy.Policy, exp *time.Time, nonce []byte, opts ...Option) (*Token, error) { + cfg, err := newConfig(opts...) + if err != nil { + return nil, err + } + + tkn := &Token{ + Issuer: iss, + Audience: aud, + Subject: cfg.Subject, + Command: cmd, + Policy: pol, + Nonce: nonce, + NotBefore: cfg.NotBefore, + } + + if len(cfg.Meta) > 0 { + tkn.Meta = NewMeta(cfg.Meta) + } + + if exp != nil && !cfg.NoExpiration { + tkn.Expiration = exp + } + + return tkn, nil +} + +func (d *Token) Tag() string { + return Tag +} + +func (d *Token) Prototype() schema.TypedPrototype { + return bindnode.Prototype((*Token)(nil), mustLoadSchema().TypeByName("Delegation"), token.BindnodeOptions()...) +} diff --git a/delegation/delegation.ipldsch b/delegation/delegation.ipldsch index c65988a..af1953e 100644 --- a/delegation/delegation.ipldsch +++ b/delegation/delegation.ipldsch @@ -27,3 +27,34 @@ type Payload struct { # The timestamp at which the Invocation becomes invalid exp nullable Int } + +type Delegation struct { + # Issuer DID (sender) + issuer DID (rename "iss") + # Audience DID (receiver) + audience DID (rename "aud") + # Principal that the chain is about (the Subject) + subject optional DID (rename "sub") + + # The Command to eventually invoke + command String (rename "cmd") + + # The delegation policy + # It doesn't seem possible to represent it with a schema. + policy Any (rename "pol") + + # A unique, random nonce + nonce Bytes + + # Arbitrary Metadata + meta {String : Any} + + # "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer + notBefore optional Int (rename "nbf") + # The timestamp at which the Invocation becomes invalid + expiration nullable Int (rename "exp") +} + +type Save struct { + +} \ No newline at end of file diff --git a/delegation/delegation_test.go b/delegation/delegation_test.go new file mode 100644 index 0000000..32c5b4f --- /dev/null +++ b/delegation/delegation_test.go @@ -0,0 +1,87 @@ +package delegation_test + +import ( + "testing" + + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/codec/dagjson" + "github.com/ipld/go-ipld-prime/node/bindnode" + "github.com/ipld/go-ipld-prime/schema" + "github.com/stretchr/testify/require" + "github.com/ucan-wg/go-ucan/v1/delegation" + "github.com/ucan-wg/go-ucan/v1/internal/token" +) + +func TestToken_Proto(t *testing.T) { + t.Parallel() + + const delegationJson = ` +{ + "aud":"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK", + "cmd":"/foo/bar", + "exp":123456, + "iss":"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK", + "meta":{ + "bar":"baaar", + "foo":"fooo" + }, + "nbf":123456, + "nonce":{ + "/":{ + "bytes":"c3VwZXItcmFuZG9t" + } + }, + "pol":[ + ["==", ".status", "draft"], + ["all", ".reviewer", [ + ["like", ".email", "*@example.com"]] + ], + ["any", ".tags", [ + ["or", [ + ["==", ".", "news"], + ["==", ".", "press"]] + ]] + ] + ], + "sub":"did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK" +} +` + + proto := (*delegation.Token)(nil).Prototype() + + node, err := ipld.DecodeUsingPrototype([]byte(delegationJson), dagjson.Decode, proto) + require.NoError(t, err) + + tkn, ok := bindnode.Unwrap(node).(*delegation.Token) + require.True(t, ok) + + t.Log("Token:") + t.Log(" Audience:", tkn.Audience) + t.Log(" Command: ", tkn.Command) + // t.Log(" Expiration: ", token.Expiration) + t.Log(" Issuer:", tkn.Issuer) + // t.Log(" Meta:", token.Meta) + // t.Log(" NotBefore", token.NotBefore) + // t.Log(" Nonce:", token.Nonce) + // t.Log(" Policy:", token.Policy) + t.Log(" Subject:", tkn.Subject) + + // token.Command = nil + // token.Meta = nil + // token.Policy = nil + // token.Expiration = nil + // token.NotBefore = nil + + _ = bindnode.Wrap(tkn, proto.Type(), token.BindnodeOptions()...) + + typed, ok := node.(schema.TypedNode) + require.True(t, ok) + + json, err := ipld.Encode(typed.Representation(), dagjson.Encode) + require.NoError(t, err) + + require.JSONEq(t, delegationJson, string(json)) + + t.Log(string(json)) + t.Fail() +} diff --git a/delegation/encoding.go b/delegation/encoding.go deleted file mode 100644 index e993d46..0000000 --- a/delegation/encoding.go +++ /dev/null @@ -1,33 +0,0 @@ -package delegation - -import ( - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/codec/dagcbor" - "github.com/ipld/go-ipld-prime/codec/dagjson" -) - -func (p *PayloadModel) EncodeDagCbor() ([]byte, error) { - return ipld.Marshal(dagcbor.Encode, p, PayloadType()) -} - -func (p *PayloadModel) EncodeDagJson() ([]byte, error) { - return ipld.Marshal(dagjson.Encode, p, PayloadType()) -} - -func DecodeDagCbor(data []byte) (*PayloadModel, error) { - var p PayloadModel - _, err := ipld.Unmarshal(data, dagcbor.Decode, &p, PayloadType()) - if err != nil { - return nil, err - } - return &p, nil -} - -func DecodeDagJson(data []byte) (*PayloadModel, error) { - var p PayloadModel - _, err := ipld.Unmarshal(data, dagjson.Decode, &p, PayloadType()) - if err != nil { - return nil, err - } - return &p, nil -} diff --git a/delegation/junk.json b/delegation/junk.json new file mode 100644 index 0000000..e69de29 diff --git a/delegation/schema.go b/delegation/schema.go index 4615c6b..4f6ede9 100644 --- a/delegation/schema.go +++ b/delegation/schema.go @@ -6,7 +6,6 @@ import ( "sync" "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/datamodel" "github.com/ipld/go-ipld-prime/schema" ) @@ -32,38 +31,3 @@ func mustLoadSchema() *schema.TypeSystem { func PayloadType() schema.Type { return mustLoadSchema().TypeByName("Payload") } - -type PayloadModel struct { - // Issuer DID (sender) - Iss string - // Audience DID (receiver) - Aud string - // Principal that the chain is about (the Subject) - // optional: can be nil - Sub *string - - // The Command to eventually invoke - Cmd string - - // The delegation policy - Pol datamodel.Node - - // A unique, random nonce - Nonce []byte - - // Arbitrary Metadata - // optional: can be nil - Meta MetaModel - - // "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer - // optional: can be nil - Nbf *int64 - // The timestamp at which the Invocation becomes invalid - // optional: can be nil - Exp *int64 -} - -type MetaModel struct { - Keys []string - Values map[string]datamodel.Node -} diff --git a/delegation/schema_test.go b/delegation/schema_test.go index bb7daed..1c81c6e 100644 --- a/delegation/schema_test.go +++ b/delegation/schema_test.go @@ -1,68 +1,11 @@ package delegation import ( - "fmt" "testing" "github.com/ipld/go-ipld-prime" - "github.com/stretchr/testify/require" ) -func TestSchemaRoundTrip(t *testing.T) { - const delegationJson = ` -{ - "aud":"did:key:def456", - "cmd":"/foo/bar", - "exp":123456, - "iss":"did:key:abc123", - "meta":{ - "bar":"baaar", - "foo":"fooo" - }, - "nbf":123456, - "nonce":{ - "/":{ - "bytes":"c3VwZXItcmFuZG9t" - } - }, - "pol":[ - ["==", ".status", "draft"], - ["all", ".reviewer", [ - ["like", ".email", "*@example.com"]] - ], - ["any", ".tags", [ - ["or", [ - ["==", ".", "news"], - ["==", ".", "press"]] - ]] - ] - ], - "sub":"" -} -` - // format: dagJson --> PayloadModel --> dagCbor --> PayloadModel --> dagJson - // function: DecodeDagJson() EncodeDagCbor() DecodeDagCbor() EncodeDagJson() - - p1, err := DecodeDagJson([]byte(delegationJson)) - require.NoError(t, err) - - cborBytes, err := p1.EncodeDagCbor() - require.NoError(t, err) - fmt.Println("cborBytes length", len(cborBytes)) - fmt.Println("cbor", string(cborBytes)) - - p2, err := DecodeDagCbor(cborBytes) - require.NoError(t, err) - fmt.Println("read Cbor", p2) - - readJson, err := p2.EncodeDagJson() - require.NoError(t, err) - fmt.Println("readJson length", len(readJson)) - fmt.Println("json: ", string(readJson)) - - require.JSONEq(t, delegationJson, string(readJson)) -} - func BenchmarkSchemaLoad(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/delegation/view.go b/delegation/view.go deleted file mode 100644 index 0c6dcd5..0000000 --- a/delegation/view.go +++ /dev/null @@ -1,87 +0,0 @@ -package delegation - -import ( - "fmt" - "time" - - "github.com/ipld/go-ipld-prime/datamodel" - - "github.com/ucan-wg/go-ucan/v1/capability/command" - "github.com/ucan-wg/go-ucan/v1/capability/policy" - "github.com/ucan-wg/go-ucan/v1/did" -) - -type View struct { - // Issuer DID (sender) - Issuer did.DID - // Audience DID (receiver) - Audience did.DID - // Principal that the chain is about (the Subject) - Subject did.DID - // The Command to eventually invoke - Command *command.Command - // The delegation policy - Policy policy.Policy - // A unique, random nonce - Nonce []byte - // Arbitrary Metadata - Meta map[string]datamodel.Node - // "Not before" UTC Unix Timestamp in seconds (valid from), 53-bits integer - NotBefore time.Time - // The timestamp at which the Invocation becomes invalid - Expiration time.Time -} - -// ViewFromModel build a decoded view of the raw IPLD data. -// This function also serves as validation. -func ViewFromModel(m PayloadModel) (*View, error) { - var view View - var err error - - view.Issuer, err = did.Parse(m.Iss) - if err != nil { - return nil, fmt.Errorf("parse iss: %w", err) - } - - view.Audience, err = did.Parse(m.Aud) - if err != nil { - return nil, fmt.Errorf("parse audience: %w", err) - } - - if m.Sub != nil { - view.Subject, err = did.Parse(*m.Sub) - if err != nil { - return nil, fmt.Errorf("parse subject: %w", err) - } - } else { - view.Subject = did.Undef - } - - view.Command, err = command.Parse(m.Cmd) - if err != nil { - return nil, fmt.Errorf("parse command: %w", err) - } - - view.Policy, err = policy.FromIPLD(m.Pol) - if err != nil { - return nil, fmt.Errorf("parse policy: %w", err) - } - - if len(m.Nonce) == 0 { - return nil, fmt.Errorf("nonce is required") - } - view.Nonce = m.Nonce - - // TODO: copy? - view.Meta = m.Meta.Values - - if m.Nbf != nil { - view.NotBefore = time.Unix(*m.Nbf, 0) - } - - if m.Exp != nil { - view.Expiration = time.Unix(*m.Exp, 0) - } - - return &view, nil -} diff --git a/go.mod b/go.mod index 8ec9951..b055849 100644 --- a/go.mod +++ b/go.mod @@ -8,16 +8,20 @@ require ( github.com/gobwas/glob v0.2.3 github.com/ipfs/go-cid v0.4.1 github.com/ipld/go-ipld-prime v0.21.0 + github.com/launchdarkly/go-options v1.3.0 github.com/libp2p/go-libp2p v0.36.2 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 github.com/multiformats/go-varint v0.0.7 github.com/stretchr/testify v1.9.0 + gotest.tools/v3 v3.5.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/fatih/structtag v1.0.0 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect @@ -28,7 +32,10 @@ require ( github.com/polydawn/refmt v0.89.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect golang.org/x/crypto v0.25.0 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect + golang.org/x/tools v0.23.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect diff --git a/go.sum b/go.sum index dc08715..52b874d 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,41 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc= +github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= @@ -27,6 +48,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/launchdarkly/go-options v1.3.0 h1:djG7Jnq5Ypixj4oqPlQOaZZMM54R9DhESyUheNl7Fow= +github.com/launchdarkly/go-options v1.3.0/go.mod h1:M4XaM6jqyeCwQFRKtU4OGepTeWvUF9rDhcggjLLTPvE= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-libp2p v0.36.2 h1:BbqRkDaGC3/5xfaJakLV/BrpjlAuYqSB0lRvtzL3B/U= @@ -49,6 +72,14 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= @@ -63,31 +94,93 @@ github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hg github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/internal/token/converter.go b/internal/token/converter.go new file mode 100644 index 0000000..959628e --- /dev/null +++ b/internal/token/converter.go @@ -0,0 +1,128 @@ +package token + +import ( + "errors" + "fmt" + "time" + + "github.com/ipld/go-ipld-prime/datamodel" + "github.com/ipld/go-ipld-prime/node/bindnode" + "github.com/ucan-wg/go-ucan/v1/capability/command" + "github.com/ucan-wg/go-ucan/v1/capability/policy" + "github.com/ucan-wg/go-ucan/v1/did" +) + +func BindnodeOptions() []bindnode.Option { + return []bindnode.Option{ + CommandConverter(), + DIDConverter(), + MetaConverter(), + PolicyConverter(), + TimeConverter(), + } +} + +var ErrTypeAssertion = errors.New("failed to assert type") + +func newErrTypeAssertion(where string) error { + return fmt.Errorf("%w: %s", ErrTypeAssertion, where) +} + +func CommandConverter() bindnode.Option { + return bindnode.TypedStringConverter( + (*command.Command)(nil), + func(s string) (interface{}, error) { + return command.Parse(s) + }, + func(i interface{}) (string, error) { + cmd, ok := i.(*command.Command) + if !ok { + return "", newErrTypeAssertion("CommandConverter") + } + + return cmd.String(), nil + }, + ) +} + +func DIDConverter() bindnode.Option { + return bindnode.TypedStringConverter( + (*did.DID)(nil), + func(s string) (interface{}, error) { + return did.Parse(s) + }, + func(i interface{}) (string, error) { + return i.(*did.DID).String(), nil + }, + ) +} + +type Meta struct { + Keys []string + Values map[string]any +} + +func MetaConverter() bindnode.Option { + return bindnode.TypedAnyConverter( + (map[string]any)(nil), + func(n datamodel.Node) (interface{}, error) { + return Meta{}, nil // TODO + }, + func(i interface{}) (datamodel.Node, error) { + if i == nil { + return datamodel.Null, nil + } + + meta, ok := i.(Meta) + if !ok { + return nil, newErrTypeAssertion("MetaConverter") + } + + _ = meta + + return datamodel.Null, nil // TODO + }, + ) +} + +func PolicyConverter() bindnode.Option { + return bindnode.TypedAnyConverter( + (*policy.Policy)(nil), + func(n datamodel.Node) (interface{}, error) { + return policy.FromIPLD(n) + }, + func(i interface{}) (datamodel.Node, error) { + if i == nil { + return datamodel.Null, nil + } + + pol, ok := i.(*policy.Policy) + if !ok { + return nil, newErrTypeAssertion("PolicyConverter") + } + + return pol.ToIPLD() + }, + ) +} + +func TimeConverter() bindnode.Option { + return bindnode.TypedIntConverter( + (*time.Time)(nil), + func(i int64) (interface{}, error) { + return time.Unix(i, 0), nil + }, + func(i interface{}) (int64, error) { + if i == nil { + return 0, nil + } + + t, ok := i.(*time.Time) + if !ok { + return 0, newErrTypeAssertion("TimeConverter") + } + + return t.Unix(), nil + }, + ) +} diff --git a/internal/token/converter_test.go b/internal/token/converter_test.go new file mode 100644 index 0000000..941b99c --- /dev/null +++ b/internal/token/converter_test.go @@ -0,0 +1 @@ +package token_test diff --git a/internal/tools/tools.go b/internal/tools/tools.go new file mode 100644 index 0000000..eaeb0e9 --- /dev/null +++ b/internal/tools/tools.go @@ -0,0 +1,7 @@ +//go:build tools + +package tools + +import ( + _ "github.com/launchdarkly/go-options" +)