From b14671009cd8376b3e378440ae3a60a313b27d97 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Tue, 24 Sep 2024 06:46:48 -0400 Subject: [PATCH] refactor(delegate): calculate CID in methods that explicitly state that they include that function --- delegation/ipld.go | 223 +++++++++++++++++++++------------ delegation/schema_test.go | 71 ++++++++--- go.mod | 2 +- internal/envelope/cid.go | 95 ++++++++++++-- internal/envelope/cid_test.go | 57 +++++++++ internal/envelope/ipld.go | 42 +++---- internal/envelope/ipld_test.go | 39 ++++-- 7 files changed, 384 insertions(+), 145 deletions(-) diff --git a/delegation/ipld.go b/delegation/ipld.go index c2620bd..8f4bdf6 100644 --- a/delegation/ipld.go +++ b/delegation/ipld.go @@ -15,10 +15,77 @@ import ( "github.com/ucan-wg/go-ucan/internal/envelope" ) +// Seal wraps the delegation token in an envelope, generates the signature, +// encodes the result to DAG-CBOR and calculates the CID of the resulting +// binary data. +func (t *Token) Seal(privKey crypto.PrivKey) ([]byte, cid.Cid, error) { + data, err := t.ToDagCbor(privKey) + if err != nil { + return nil, cid.Undef, err + } + + id, err := envelope.CIDFromBytes(data) + if err != nil { + return nil, cid.Undef, err + } + + return data, id, nil +} + +// SealWriter is the same as Seal but accepts an io.Writer. +func (t *Token) SealWriter(w io.Writer, privKey crypto.PrivKey) (cid.Cid, error) { + cidWriter := envelope.NewCIDWriter(w) + + if err := t.ToDagCborWriter(cidWriter, privKey); err != nil { + return cid.Undef, err + } + + return cidWriter.CID() +} + +// Unseal decodes the provided binary data from the DAG-CBOR format, +// verifies that the envelope's signature is correct based on the public +// key taken from the issuer (iss) field and calculates the CID of the +// incoming data. +func Unseal(data []byte) (*Token, error) { + tkn, err := FromDagCbor(data) + if err != nil { + return nil, err + } + + id, err := envelope.CIDFromBytes(data) + if err != nil { + return nil, err + } + + tkn.cid = id + + return tkn, nil +} + +// UnsealReader is the same as Unseal but accepts an io.Reader. +func UnsealReader(r io.Reader) (*Token, error) { + cidReader := envelope.NewCIDReader(r) + + tkn, err := FromDagCborReader(cidReader) + if err != nil { + return nil, err + } + + id, err := cidReader.CID() + if err != nil { + return nil, err + } + + tkn.cid = id + + return tkn, nil +} + // Encode marshals a View to the format specified by the provided // codec.Encoder. func (t *Token) Encode(privKey crypto.PrivKey, encFn codec.Encoder) ([]byte, error) { - node, err := t.ToIPLD(privKey) + node, err := t.toIPLD(privKey) if err != nil { return nil, err } @@ -28,7 +95,7 @@ func (t *Token) Encode(privKey crypto.PrivKey, encFn codec.Encoder) ([]byte, err // EncodeWriter is the same as Encode but accepts an io.Writer. func (t *Token) EncodeWriter(w io.Writer, privKey crypto.PrivKey, encFn codec.Encoder) error { - node, err := t.ToIPLD(privKey) + node, err := t.toIPLD(privKey) if err != nil { return err } @@ -56,9 +123,81 @@ func (t *Token) ToDagJsonWriter(w io.Writer, privKey crypto.PrivKey) error { return t.EncodeWriter(w, privKey, dagjson.Encode) } -// ToIPLD wraps the View in an IPLD datamodel.Node. -func (t *Token) ToIPLD(privKey crypto.PrivKey) (datamodel.Node, error) { +// Decode unmarshals the input data using the format specified by the +// provided codec.Decoder into a View. +// +// An error is returned if the conversion fails, or if the resulting +// View is invalid. +func Decode(b []byte, decFn codec.Decoder) (*Token, error) { + node, err := ipld.Decode(b, decFn) + if err != nil { + return nil, err + } + return fromIPLD(node) +} + +// DecodeReader is the same as Decode, but accept an io.Reader. +func DecodeReader(r io.Reader, decFn codec.Decoder) (*Token, error) { + node, err := ipld.DecodeStreaming(r, decFn) + if err != nil { + return nil, err + } + return fromIPLD(node) +} + +// FromDagCbor unmarshals the input data into a View. +// +// An error is returned if the conversion fails, or if the resulting +// View is invalid. +func FromDagCbor(data []byte) (*Token, error) { + pay, err := envelope.FromDagCbor[*tokenPayloadModel](data) + if err != nil { + return nil, err + } + + tkn, err := tokenFromModel(*pay) + if err != nil { + return nil, err + } + + return tkn, err +} + +// FromDagCborReader is the same as FromDagCbor, but accept an io.Reader. +func FromDagCborReader(r io.Reader) (*Token, error) { + return DecodeReader(r, dagcbor.Decode) +} + +// FromDagJson unmarshals the input data into a View. +// +// An error is returned if the conversion fails, or if the resulting +// View is invalid. +func FromDagJson(data []byte) (*Token, error) { + return Decode(data, dagjson.Decode) +} + +// FromDagJsonReader is the same as FromDagJson, but accept an io.Reader. +func FromDagJsonReader(r io.Reader) (*Token, error) { + return DecodeReader(r, dagjson.Decode) +} + +func fromIPLD(node datamodel.Node) (*Token, error) { + pay, err := envelope.FromIPLD[*tokenPayloadModel](node) + if err != nil { + return nil, err + } + + tkn, err := tokenFromModel(*pay) + if err != nil { + return nil, err + } + + return tkn, err +} + +func (t *Token) toIPLD(privKey crypto.PrivKey) (datamodel.Node, error) { var sub *string + if t.subject != did.Undef { s := t.subject.String() sub = &s @@ -95,79 +234,3 @@ func (t *Token) ToIPLD(privKey crypto.PrivKey) (datamodel.Node, error) { return envelope.ToIPLD(privKey, model) } - -// Decode unmarshals the input data using the format specified by the -// provided codec.Decoder into a View. -// -// An error is returned if the conversion fails, or if the resulting -// View is invalid. -func Decode(b []byte, decFn codec.Decoder) (*Token, cid.Cid, error) { - node, err := ipld.Decode(b, decFn) - if err != nil { - return nil, cid.Undef, err - } - return FromIPLD(node) -} - -// DecodeReader is the same as Decode, but accept an io.Reader. -func DecodeReader(r io.Reader, decFn codec.Decoder) (*Token, cid.Cid, error) { - node, err := ipld.DecodeStreaming(r, decFn) - if err != nil { - return nil, cid.Undef, err - } - return FromIPLD(node) -} - -// FromDagCbor unmarshals the input data into a View. -// -// An error is returned if the conversion fails, or if the resulting -// View is invalid. -func FromDagCbor(data []byte) (*Token, cid.Cid, error) { - pay, id, err := envelope.FromDagCbor[*tokenPayloadModel](data) - if err != nil { - return nil, cid.Undef, err - } - - tkn, err := tokenFromModel(*pay) - if err != nil { - return nil, cid.Undef, err - } - - return tkn, id, err -} - -// FromDagCborReader is the same as FromDagCbor, but accept an io.Reader. -func FromDagCborReader(r io.Reader) (*Token, cid.Cid, error) { - return DecodeReader(r, dagcbor.Decode) -} - -// FromDagJson unmarshals the input data into a View. -// -// An error is returned if the conversion fails, or if the resulting -// View is invalid. -func FromDagJson(data []byte) (*Token, cid.Cid, error) { - return Decode(data, dagjson.Decode) -} - -// FromDagJsonReader is the same as FromDagJson, but accept an io.Reader. -func FromDagJsonReader(r io.Reader) (*Token, cid.Cid, error) { - return DecodeReader(r, dagjson.Decode) -} - -// FromIPLD unwraps a View from the provided IPLD datamodel.Node -// -// An error is returned if the conversion fails, or if the resulting -// View is invalid. -func FromIPLD(node datamodel.Node) (*Token, cid.Cid, error) { - pay, id, err := envelope.FromIPLD[*tokenPayloadModel](node) // TODO add CID to view - if err != nil { - return nil, cid.Undef, err - } - - tkn, err := tokenFromModel(*pay) - if err != nil { - return nil, cid.Undef, err - } - - return tkn, id, err -} diff --git a/delegation/schema_test.go b/delegation/schema_test.go index f63a968..62274c5 100644 --- a/delegation/schema_test.go +++ b/delegation/schema_test.go @@ -1,11 +1,13 @@ package delegation_test import ( + "bytes" _ "embed" "fmt" "testing" "github.com/ipld/go-ipld-prime" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gotest.tools/v3/golden" @@ -22,29 +24,62 @@ func TestSchemaRoundTrip(t *testing.T) { delegationJson := golden.Get(t, "new.dagjson") privKey := privKey(t, issuerPrivKeyCfg) - // format: dagJson --> PayloadModel --> dagCbor --> PayloadModel --> dagJson - // function: DecodeDagJson() EncodeDagCbor() DecodeDagCbor() EncodeDagJson() + t.Run("via buffers", func(t *testing.T) { + t.Parallel() - p1, id1, err := delegation.FromDagJson([]byte(delegationJson)) - require.NoError(t, err) - require.Equal(t, newCID, envelope.CIDToBase58BTC(id1)) + // format: dagJson --> PayloadModel --> dagCbor --> PayloadModel --> dagJson + // function: DecodeDagJson() Seal() Unseal() EncodeDagJson() - cborBytes, err := p1.ToDagCbor(privKey) - require.NoError(t, err) - fmt.Println("cborBytes length", len(cborBytes)) - fmt.Println("cbor", string(cborBytes)) + p1, err := delegation.FromDagJson([]byte(delegationJson)) + require.NoError(t, err) - p2, id2, err := delegation.FromDagCbor(cborBytes) - require.NoError(t, err) - fmt.Println("read Cbor", p2) + cborBytes, id, err := p1.Seal(privKey) + require.NoError(t, err) + assert.Equal(t, newCID, envelope.CIDToBase58BTC(id)) + fmt.Println("cborBytes length", len(cborBytes)) + fmt.Println("cbor", string(cborBytes)) - readJson, err := p2.ToDagJson(privKey) - require.NoError(t, err) - require.Equal(t, newCID, envelope.CIDToBase58BTC(id2)) - fmt.Println("readJson length", len(readJson)) - fmt.Println("json: ", string(readJson)) + p2, err := delegation.Unseal(cborBytes) + require.NoError(t, err) + assert.Equal(t, id, p2.CID()) + fmt.Println("read Cbor", p2) - require.JSONEq(t, string(delegationJson), string(readJson)) + readJson, err := p2.ToDagJson(privKey) + require.NoError(t, err) + fmt.Println("readJson length", len(readJson)) + fmt.Println("json: ", string(readJson)) + + assert.JSONEq(t, string(delegationJson), string(readJson)) + }) + + t.Run("via streaming", func(t *testing.T) { + t.Parallel() + + buf := bytes.NewBuffer(delegationJson) + + // format: dagJson --> PayloadModel --> dagCbor --> PayloadModel --> dagJson + // function: DecodeDagJson() Seal() Unseal() EncodeDagJson() + + p1, err := delegation.FromDagJsonReader(buf) + require.NoError(t, err) + + cborBytes := &bytes.Buffer{} + id, err := p1.SealWriter(cborBytes, privKey) + t.Log(len(id.Bytes()), id.Bytes()) + require.NoError(t, err) + assert.Equal(t, newCID, envelope.CIDToBase58BTC(id)) + + // buf = bytes.NewBuffer(cborBytes.Bytes()) + p2, err := delegation.UnsealReader(cborBytes) + require.NoError(t, err) + t.Log(len(p2.CID().Bytes()), p2.CID().Bytes()) + assert.Equal(t, envelope.CIDToBase58BTC(id), envelope.CIDToBase58BTC(p2.CID())) + + readJson := &bytes.Buffer{} + require.NoError(t, p2.ToDagJsonWriter(readJson, privKey)) + + assert.JSONEq(t, string(delegationJson), readJson.String()) + }) } func BenchmarkSchemaLoad(b *testing.B) { diff --git a/go.mod b/go.mod index 30dee27..02f05fc 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/libp2p/go-libp2p v0.36.3 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 + github.com/multiformats/go-multihash v0.2.3 github.com/multiformats/go-varint v0.0.7 github.com/stretchr/testify v1.9.0 gotest.tools/v3 v3.5.1 @@ -24,7 +25,6 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multihash v0.2.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polydawn/refmt v0.89.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect diff --git a/internal/envelope/cid.go b/internal/envelope/cid.go index 169d7c7..2f8c7cf 100644 --- a/internal/envelope/cid.go +++ b/internal/envelope/cid.go @@ -1,9 +1,11 @@ package envelope import ( + "crypto/sha256" + "hash" + "io" + "github.com/ipfs/go-cid" - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/libp2p/go-libp2p/core/crypto" "github.com/multiformats/go-multibase" "github.com/multiformats/go-multicodec" @@ -38,12 +40,89 @@ func CIDFromBytes(b []byte) (cid.Cid, error) { }.Sum(b) } -// CIDFromIPLD returns the UCAN content identifier for an ipld.Node. -func CIDFromIPLD(node ipld.Node) (cid.Cid, error) { - data, err := ipld.Encode(node, dagcbor.Encode) - if err != nil { - return cid.Undef, nil +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. +type CIDReader struct { + hash hash.Hash + r io.Reader + err error +} + +// NewCIDReader initializes a hash.Hash to calculate the CID's hash and +// and returns a wrapped io.Reader. +func NewCIDReader(r io.Reader) *CIDReader { + hash := sha256.New() + hash.Reset() + + return &CIDReader{ + hash: hash, + r: r, + } +} + +// CID returns the UCAN-formatted cid.Cid created from the hash calculated +// as bytes are 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? } - return CIDFromBytes(data) + return cidFromHash(r.hash) +} + +// Read implements io.Reader. +func (r *CIDReader) Read(p []byte) (n int, err error) { + n, err = r.r.Read(p) + if err != nil && err != io.EOF { + r.err = err + + return + } + + _, _ = r.hash.Write(p[:n]) + + return +} + +var _ io.Writer = (*CIDWriter)(nil) + +type CIDWriter struct { + hash hash.Hash + w io.Writer + err error +} + +func NewCIDWriter(w io.Writer) *CIDWriter { + hash := sha256.New() + hash.Reset() + + return &CIDWriter{ + hash: hash, + w: w, + } +} + +func (w *CIDWriter) CID() (cid.Cid, error) { + return cidFromHash(w.hash) +} + +func (w *CIDWriter) Write(p []byte) (n int, err error) { + if _, err = w.hash.Write(p); err != nil { + w.err = err + + return + } + + return w.w.Write(p) +} + +func cidFromHash(hash hash.Hash) (cid.Cid, error) { + mh, err := multihash.Encode(hash.Sum(nil), multihash.SHA2_256) + if err != nil { + return cid.Undef, err + } + + return cid.NewCidV1(uint64(multicodec.DagCbor), mh), nil } diff --git a/internal/envelope/cid_test.go b/internal/envelope/cid_test.go index 3ff9d13..449477d 100644 --- a/internal/envelope/cid_test.go +++ b/internal/envelope/cid_test.go @@ -1,8 +1,10 @@ package envelope_test import ( + "io" "testing" + "github.com/ipfs/go-cid" "github.com/multiformats/go-multicodec" "github.com/multiformats/go-multihash" "github.com/stretchr/testify/assert" @@ -23,3 +25,58 @@ func TestCid(t *testing.T) { assert.Equal(t, exampleCID, envelope.CIDToBase58BTC(id)) assert.Equal(t, expHash, id.Hash()) } + +func TestStreaming(t *testing.T) { + t.Parallel() + + expData := []byte("this is a test") + + expCID, err := cid.V1Builder{ + Codec: uint64(multicodec.DagCbor), + MhType: multihash.SHA2_256, + MhLength: 0, + }.Sum(expData) + require.NoError(t, err) + + t.Run("CIDReader()", func(t *testing.T) { + t.Parallel() + + r, w := io.Pipe() //nolint:varnamelen + cidReader := envelope.NewCIDReader(r) + + go func() { + _, err := w.Write(expData) + assert.NoError(t, err) + assert.NoError(t, w.Close()) + }() + + actData, err := io.ReadAll(cidReader) + require.NoError(t, err) + assert.Equal(t, expData, actData) + + actCID, err := cidReader.CID() + require.NoError(t, err) + assert.Equal(t, expCID, actCID) + }) + + t.Run("CIDWriter", func(t *testing.T) { + t.Parallel() + + r, w := io.Pipe() //nolint:varnamelen + cidWriter := envelope.NewCIDWriter(w) + + go func() { + _, err := cidWriter.Write(expData) + assert.NoError(t, err) + assert.NoError(t, w.Close()) + }() + + actData, err := io.ReadAll(r) + require.NoError(t, err) + assert.Equal(t, expData, actData) + + actCID, err := cidWriter.CID() + require.NoError(t, err) + assert.Equal(t, expCID, actCID) + }) +} diff --git a/internal/envelope/ipld.go b/internal/envelope/ipld.go index 6aa3a2d..8514174 100644 --- a/internal/envelope/ipld.go +++ b/internal/envelope/ipld.go @@ -8,8 +8,7 @@ // // Decoding functions in this package likewise perform the signature // verification using a public key extracted from the TokenPayload as -// described by requirement two below. Additionally, the decode functions -// also return the CID for the verified Envelope. +// described by requirement two below. // // Types that wish to be marshaled and unmarshaled from the using // is package have two requirements. @@ -30,7 +29,6 @@ import ( "errors" "io" - "github.com/ipfs/go-cid" "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec" "github.com/ipld/go-ipld-prime/codec/dagcbor" @@ -66,20 +64,20 @@ type Tokener interface { // // An error is returned if the conversion fails, or if the resulting // Tokener is invalid. -func Decode[T Tokener](b []byte, decFn codec.Decoder) (T, cid.Cid, error) { +func Decode[T Tokener](b []byte, decFn codec.Decoder) (T, error) { node, err := ipld.Decode(b, decFn) if err != nil { - return *new(T), cid.Undef, err + return *new(T), err } return FromIPLD[T](node) } // DecodeReader is the same as Decode, but accept an io.Reader. -func DecodeReader[T Tokener](r io.Reader, decFn codec.Decoder) (T, cid.Cid, error) { +func DecodeReader[T Tokener](r io.Reader, decFn codec.Decoder) (T, error) { node, err := ipld.DecodeStreaming(r, decFn) if err != nil { - return *new(T), cid.Undef, err + return *new(T), err } return FromIPLD[T](node) @@ -89,29 +87,24 @@ func DecodeReader[T Tokener](r io.Reader, decFn codec.Decoder) (T, cid.Cid, erro // // An error is returned if the conversion fails, or if the resulting // Tokener is invalid. -func FromDagCbor[T Tokener](b []byte) (T, cid.Cid, error) { +func FromDagCbor[T Tokener](b []byte) (T, error) { undef := *new(T) node, err := ipld.Decode(b, dagcbor.Decode) if err != nil { - return undef, cid.Undef, err - } - - id, err := CIDFromBytes(b) - if err != nil { - return undef, cid.Undef, err + return undef, err } tkn, err := fromIPLD[T](node) if err != nil { - return undef, cid.Undef, err + return undef, err } - return tkn, id, nil + return tkn, nil } // FromDagCborReader is the same as FromDagCbor, but accept an io.Reader. -func FromDagCborReader[T Tokener](r io.Reader) (T, cid.Cid, error) { +func FromDagCborReader[T Tokener](r io.Reader) (T, error) { return DecodeReader[T](r, dagcbor.Decode) } @@ -119,12 +112,12 @@ func FromDagCborReader[T Tokener](r io.Reader) (T, cid.Cid, error) { // // An error is returned if the conversion fails, or if the resulting // Tokener is invalid. -func FromDagJson[T Tokener](b []byte) (T, cid.Cid, error) { +func FromDagJson[T Tokener](b []byte) (T, error) { return Decode[T](b, dagjson.Decode) } // FromDagJsonReader is the same as FromDagJson, but accept an io.Reader. -func FromDagJsonReader[T Tokener](r io.Reader) (T, cid.Cid, error) { +func FromDagJsonReader[T Tokener](r io.Reader) (T, error) { return DecodeReader[T](r, dagjson.Decode) } @@ -132,20 +125,15 @@ func FromDagJsonReader[T Tokener](r io.Reader) (T, cid.Cid, error) { // // An error is returned if the conversion fails, or if the resulting // Tokener is invalid. -func FromIPLD[T Tokener](node datamodel.Node) (T, cid.Cid, error) { +func FromIPLD[T Tokener](node datamodel.Node) (T, error) { undef := *new(T) - id, err := CIDFromIPLD(node) - if err != nil { - return undef, cid.Undef, err - } - tkn, err := fromIPLD[T](node) if err != nil { - return undef, cid.Undef, err + return undef, err } - return tkn, id, nil + return tkn, nil } func fromIPLD[T Tokener](node datamodel.Node) (T, error) { diff --git a/internal/envelope/ipld_test.go b/internal/envelope/ipld_test.go index 24001a8..12d7d73 100644 --- a/internal/envelope/ipld_test.go +++ b/internal/envelope/ipld_test.go @@ -2,6 +2,7 @@ package envelope_test import ( "bytes" + "crypto/sha256" "testing" "github.com/stretchr/testify/assert" @@ -18,7 +19,7 @@ func TestDecode(t *testing.T) { data := golden.Get(t, "example.dagcbor") - tkn, _, err := envelope.FromDagCbor[*Example](data) + tkn, err := envelope.FromDagCbor[*Example](data) require.NoError(t, err) assert.Equal(t, exampleGreeting, tkn.Hello) assert.Equal(t, exampleDID, tkn.Issuer) @@ -29,7 +30,7 @@ func TestDecode(t *testing.T) { data := golden.Get(t, "example.dagjson") - tkn, _, err := envelope.FromDagJson[*Example](data) + tkn, err := envelope.FromDagJson[*Example](data) require.NoError(t, err) assert.Equal(t, exampleGreeting, tkn.Hello) assert.Equal(t, exampleDID, tkn.Issuer) @@ -64,11 +65,10 @@ func TestRoundtrip(t *testing.T) { dataIn := golden.Get(t, exampleDAGCBORFilename) - tkn, id, err := envelope.FromDagCbor[*Example](dataIn) + tkn, err := envelope.FromDagCbor[*Example](dataIn) require.NoError(t, err) assert.Equal(t, exampleGreeting, tkn.Hello) assert.Equal(t, exampleDID, tkn.Issuer) - assert.Equal(t, exampleCID, envelope.CIDToBase58BTC(id)) dataOut, err := envelope.ToDagCbor(examplePrivKey(t), newExample(t)) require.NoError(t, err) @@ -80,11 +80,10 @@ func TestRoundtrip(t *testing.T) { data := golden.Get(t, exampleDAGCBORFilename) - tkn, id, err := envelope.FromDagCborReader[*Example](bytes.NewReader(data)) + tkn, err := envelope.FromDagCborReader[*Example](bytes.NewReader(data)) require.NoError(t, err) assert.Equal(t, exampleGreeting, tkn.Hello) assert.Equal(t, exampleDID, tkn.Issuer) - assert.Equal(t, exampleCID, envelope.CIDToBase58BTC(id)) w := &bytes.Buffer{} require.NoError(t, envelope.ToDagCborWriter(w, examplePrivKey(t), newExample(t))) @@ -96,11 +95,10 @@ func TestRoundtrip(t *testing.T) { dataIn := golden.Get(t, exampleDAGJSONFilename) - tkn, id, err := envelope.FromDagJson[*Example](dataIn) + tkn, err := envelope.FromDagJson[*Example](dataIn) require.NoError(t, err) assert.Equal(t, exampleGreeting, tkn.Hello) assert.Equal(t, exampleDID, tkn.Issuer) - assert.Equal(t, exampleCID, envelope.CIDToBase58BTC(id)) dataOut, err := envelope.ToDagJson(examplePrivKey(t), newExample(t)) require.NoError(t, err) @@ -112,11 +110,10 @@ func TestRoundtrip(t *testing.T) { data := golden.Get(t, exampleDAGJSONFilename) - tkn, id, err := envelope.FromDagJsonReader[*Example](bytes.NewReader(data)) + tkn, err := envelope.FromDagJsonReader[*Example](bytes.NewReader(data)) require.NoError(t, err) assert.Equal(t, exampleGreeting, tkn.Hello) assert.Equal(t, exampleDID, tkn.Issuer) - assert.Equal(t, exampleCID, envelope.CIDToBase58BTC(id)) w := &bytes.Buffer{} require.NoError(t, envelope.ToDagJsonWriter(w, examplePrivKey(t), newExample(t))) @@ -128,7 +125,27 @@ func TestFromIPLD_with_invalid_signature(t *testing.T) { t.Parallel() node := invalidNodeFromGolden(t) - tkn, _, err := envelope.FromIPLD[*Example](node) + tkn, err := envelope.FromIPLD[*Example](node) assert.Nil(t, tkn) require.EqualError(t, err, "failed to verify the token's signature") } + +func TestHash(t *testing.T) { + t.Parallel() + + msg := []byte("this is a test") + + hash1 := sha256.Sum256(msg) + + hasher := sha256.New() + + for _, b := range msg { + hasher.Write([]byte{b}) + } + + hash2 := hasher.Sum(nil) + hash3 := hasher.Sum(nil) + + require.Equal(t, hash1[:], hash2) + require.Equal(t, hash1[:], hash3) +}