diff --git a/delegation/delegation.go b/delegation/delegation.go index fad627a..df45491 100644 --- a/delegation/delegation.go +++ b/delegation/delegation.go @@ -1,5 +1,14 @@ +// Package delegation implements the UCAN [delegation] specification with +// an immutable Token type as well as methods to convert the Token to and +// from the [envelope]-enclosed, signed and DAG-CBOR-encoded form that +// should most commonly be used for transport and storage. +// +// [delegation]: https://github.com/ucan-wg/delegation/tree/v1_ipld +// [envelope]: https://github.com/ucan-wg/spec#envelope package delegation +// TODO: change the "delegation" link above when the specification is merged + import ( "crypto/rand" "errors" @@ -15,6 +24,7 @@ import ( "github.com/ucan-wg/go-ucan/pkg/meta" ) +// Token is an immutable type that holds the fields of a UCAN delegation. type Token struct { // Issuer DID (sender) issuer did.DID @@ -162,6 +172,8 @@ func (t *Token) validate() error { return errs } +// Option is a type that allows optional fields to be set during the +// creation of a Token. type Option func(*Token) error // WithExpiration set's the Token's optional "expiration" field to the @@ -179,6 +191,7 @@ func WithExpiration(exp time.Time) Option { } // WithMeta adds a key/value pair in the "meta" field. +// // WithMeta can be used multiple times in the same call. // Accepted types for the value are: bool, string, int, int32, int64, []byte, // and ipld.Node. diff --git a/delegation/delegation_test.go b/delegation/delegation_test.go index 9a2a6ad..7d05f10 100644 --- a/delegation/delegation_test.go +++ b/delegation/delegation_test.go @@ -1,12 +1,10 @@ package delegation_test import ( - "crypto/rand" "testing" "time" "github.com/libp2p/go-libp2p/core/crypto" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gotest.tools/v3/golden" @@ -14,7 +12,6 @@ import ( "github.com/ucan-wg/go-ucan/capability/policy" "github.com/ucan-wg/go-ucan/delegation" "github.com/ucan-wg/go-ucan/did" - "github.com/ucan-wg/go-ucan/internal/envelope" ) const ( @@ -91,7 +88,7 @@ func TestConstructors(t *testing.T) { require.NoError(t, err) t.Run("New", func(t *testing.T) { - dlg, err := delegation.New(privKey, aud, cmd, pol, + tkn, err := delegation.New(privKey, aud, cmd, pol, delegation.WithNonce([]byte(nonce)), delegation.WithSubject(sub), delegation.WithExpiration(exp), @@ -100,19 +97,18 @@ func TestConstructors(t *testing.T) { ) require.NoError(t, err) - data, err := dlg.ToDagJson(privKey) + data, err := tkn.ToDagJson(privKey) require.NoError(t, err) t.Log(string(data)) golden.Assert(t, string(data), "new.dagjson") - assert.Equal(t, newCID, envelope.CIDToBase58BTC(dlg.CID())) }) t.Run("Root", func(t *testing.T) { t.Parallel() - dlg, err := delegation.Root(privKey, aud, cmd, pol, + tkn, err := delegation.Root(privKey, aud, cmd, pol, delegation.WithNonce([]byte(nonce)), delegation.WithExpiration(exp), delegation.WithMeta("foo", "fooo"), @@ -120,13 +116,12 @@ func TestConstructors(t *testing.T) { ) require.NoError(t, err) - data, err := dlg.ToDagJson(privKey) + data, err := tkn.ToDagJson(privKey) require.NoError(t, err) t.Log(string(data)) golden.Assert(t, string(data), "root.dagjson") - assert.Equal(t, rootCID, envelope.CIDToBase58BTC(dlg.CID())) }) } @@ -141,23 +136,3 @@ func privKey(t *testing.T, privKeyCfg string) crypto.PrivKey { return privKey } - -func TestKey(t *testing.T) { - // TODO: why is this broken? - t.Skip("TODO: why is this broken?") - - priv, _, err := crypto.GenerateEd25519Key(rand.Reader) - require.NoError(t, err) - - privMar, err := crypto.MarshalPrivateKey(priv) - require.NoError(t, err) - - privCfg := crypto.ConfigEncodeKey(privMar) - t.Log(privCfg) - - id, err := did.FromPubKey(priv.GetPublic()) - require.NoError(t, err) - t.Log(id) - - t.Fail() -} diff --git a/internal/envelope/cid.go b/internal/envelope/cid.go index f127459..74ac583 100644 --- a/internal/envelope/cid.go +++ b/internal/envelope/cid.go @@ -43,8 +43,8 @@ func CIDFromBytes(b []byte) (cid.Cid, error) { var _ io.Reader = (*CIDReader)(nil) -// CIDReader wraps an io.Reader and includes a hash.Hash that is updated -// as data is read from the child io.Reader. +// CIDReader wraps an io.Reader and includes a hash.Hash that is +// incrementally updated as data is read from the child io.Reader. type CIDReader struct { hash hash.Hash r io.Reader @@ -52,7 +52,7 @@ type CIDReader struct { } // NewCIDReader initializes a hash.Hash to calculate the CID's hash and -// and returns a wrapped io.Reader. +// returns the wrapped io.Reader. func NewCIDReader(r io.Reader) *CIDReader { h := sha256.New() h.Reset() @@ -64,7 +64,7 @@ func NewCIDReader(r io.Reader) *CIDReader { } // CID returns the UCAN-formatted cid.Cid created from the hash calculated -// as bytes are read from the inner io.Reader. +// as bytes were read from the inner io.Reader. func (r *CIDReader) CID() (cid.Cid, error) { if r.err != nil { return cid.Undef, r.err // TODO: Wrap to say it's an error during streaming? @@ -89,12 +89,16 @@ func (r *CIDReader) Read(p []byte) (n int, err error) { var _ io.Writer = (*CIDWriter)(nil) +// CIDWriter wraps an io.Writer and includes a hash.Hash that is +// incrementally updated as data is written to the child io.Writer. type CIDWriter struct { hash hash.Hash w io.Writer err error } +// NewCIDWriter initializes a hash.Hash to calculate the CID's hash and +// returns the wrapped io.Writer. func NewCIDWriter(w io.Writer) *CIDWriter { h := sha256.New() h.Reset() @@ -105,10 +109,13 @@ func NewCIDWriter(w io.Writer) *CIDWriter { } } +// CID returns the UCAN-formatted cid.Cid created from the hash calculated +// as bytes were written from the inner io.Reader. func (w *CIDWriter) CID() (cid.Cid, error) { return cidFromHash(w.hash) } +// Write implements io.Writer. func (w *CIDWriter) Write(p []byte) (n int, err error) { if _, err = w.hash.Write(p); err != nil { w.err = err