refactor(delegate): calculate CID in methods that explicitly state that they include that function
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
2
go.mod
2
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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user