container

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2025 License: Apache-2.0, MIT Imports: 21 Imported by: 0

README

Token container

Why do I need that?

Some common situation asks to package multiple tokens together:

  • calling a service requires sending an invocation, alongside the matching delegations
  • sending a series of revocations
  • <insert your application specific scenario here>

The UCAN specification defines how a single token is serialized (envelope with signature, IPLD encoded as Dag-cbor), but it's entirely left open how to package multiple tokens together. To be clear, this is a correct thing to do for a specification, as different ways equally valid to solve that problem exists and can coexist. Any wire format holding a list of bytes would do (cbor, json, csv ...).

go-ucan however, provide an opinionated implementation, which may or may not work in your situation.

Some experiment has been done over which format is appropriate, and two have been selected:

  • DAG-CBOR of a list of bytes, as a low overhead option
  • CAR file, as a somewhat common ways to cary arbitrary blocks of data

Notably, compression is not included, even though it does work reasonably well. This is because your transport medium might already do it, or should.

Wire format consideration

Several possible formats have been explored:

  • CAR files (binary or base64)
  • DAG-CBOR (binary or base64)

Additionally, gzip and deflate compression has been experimented with.

Below are the results in terms of storage used, as percentage and byte overhead over the raw tokens:

Token count car carBase64 carGzip carGzipBase64 cbor cborBase64 cborGzip cborGzipBase64 cborFlate cborFlateBase64
1 15 54 7 42 0 35 -8 22 -12 16
2 12 49 -12 15 0 34 -25 0 -28 -3
3 11 48 -21 4 0 34 -32 -10 -34 -11
4 10 47 -26 -1 0 34 -36 -15 -37 -17
5 10 47 -28 -4 0 34 -38 -18 -40 -20
6 10 47 -30 -7 0 34 -40 -20 -40 -20
7 10 46 -31 -8 0 34 -41 -21 -42 -22
8 9 46 -32 -10 0 34 -42 -22 -42 -23
9 9 46 -33 -11 0 34 -43 -23 -43 -24
10 9 46 -34 -12 0 34 -43 -25 -44 -25

Token count car carBase64 carGzip carGzipBase64 cbor cborBase64 cborGzip cborGzipBase64 cborFlate cborFlateBase64
1 64 226 29 178 4 146 -35 94 -52 70
2 102 412 -107 128 7 288 -211 0 -234 -32
3 140 602 -270 58 10 430 -405 -126 -429 -146
4 178 792 -432 -28 13 572 -602 -252 -617 -288
5 216 978 -582 -94 16 714 -805 -386 -839 -418
6 254 1168 -759 -176 19 856 -1001 -508 -1018 -520
7 292 1358 -908 -246 22 998 -1204 -634 -1229 -650
8 330 1544 -1085 -332 25 1140 -1398 -756 -1423 -792
9 368 1734 -1257 -414 28 1282 -1614 -894 -1625 -930
10 406 1924 -1408 -508 31 1424 -1804 -1040 -1826 -1060

img.png

Following is the performance aspect, with CPU usage and memory allocation:

Write ns/op Read ns/op Write B/op Read B/op Write allocs/op Read allocs/op
car 8451 1474630 17928 149437 59 2631
carBase64 16750 1437678 24232 151502 61 2633
carGzip 320253 1581412 823887 192272 76 2665
carGzipBase64 343305 1486269 828782 198543 77 2669
cbor 6419 1301554 16368 138891 25 2534
cborBase64 12860 1386728 20720 140962 26 2536
cborGzip 310106 1379146 822742 182003 42 2585
cborGzipBase64 317001 1462548 827640 189283 43 2594
cborFlate 327112 1555007 822473 181537 40 2591
cborFlateBase64 311276 1456562 826042 188665 41 2596

(BEWARE: logarithmic scale)

img.png img_1.png img_2.png

Conclusion:

  • CAR files are heavy for this usage, notably because they carry the CIDs of the tokens
  • compression works quite well and warrants its usage even with a single token
  • DAG-CBOR outperform CAR files everywhere, and comes with a tiny ~3 bytes per token overhead.

Formats beside DAG-CBOR and CAR, with or without base64, have been removed. They are in the git history though.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var EmptyCid = cid.MustParse([]byte{01, 55, 00, 00})

EmptyCid is a "zero" Cid: zero-length "identity" multihash with "raw" codec It can be used to have at least one root in a CARv1 file (making it legal), yet denote that it can be ignored.

View Source
var ErrMultipleInvocations = fmt.Errorf("multiple invocations")
View Source
var ErrNotFound = fmt.Errorf("not found")

Functions

This section is empty.

Types

type Reader

type Reader map[cid.Cid]token.Token

Reader is a token container reader. It exposes the tokens conveniently decoded.

func FromBytes

func FromBytes(data []byte) (Reader, error)

FromBytes decodes a container from a []byte

func FromReader

func FromReader(r io.Reader) (Reader, error)

FromReader decodes a container from an io.Reader.

func FromString

func FromString(s string) (Reader, error)

FromString decodes a container from a string

func (Reader) GetAllDelegations

func (ctn Reader) GetAllDelegations() iter.Seq2[cid.Cid, *delegation.Token]

GetAllDelegations returns all the delegation.Token in the container.

func (Reader) GetAllInvocations

func (ctn Reader) GetAllInvocations() iter.Seq2[cid.Cid, *invocation.Token]

GetAllInvocations returns all the invocation.Token in the container.

func (Reader) GetDelegation

func (ctn Reader) GetDelegation(cid cid.Cid) (*delegation.Token, error)

GetDelegation is the same as GetToken but only return a delegation.Token, with the right type. If not found, delegation.ErrDelegationNotFound is returned.

func (Reader) GetInvocation

func (ctn Reader) GetInvocation() (*invocation.Token, error)

GetInvocation returns a single invocation.Token. If none are found, ErrNotFound is returned. If more than one invocation exists, ErrMultipleInvocations is returned.

func (Reader) GetToken

func (ctn Reader) GetToken(cid cid.Cid) (token.Token, error)

GetToken returns an arbitrary decoded token, from its CID. If not found, ErrNotFound is returned.

type Writer

type Writer map[string]struct{}

Writer is a token container writer. It provides a convenient way to aggregate and serialize tokens together.

func NewWriter

func NewWriter() Writer

func (Writer) AddSealed

func (ctn Writer) AddSealed(data []byte)

AddSealed includes a "sealed" token (serialized with a ToSealed* function) in the container.

func (Writer) ToBase64StdPadding

func (ctn Writer) ToBase64StdPadding() (string, error)

ToBase64StdPadding encode the container into a base64 string, with standard encoding and padding.

func (Writer) ToBase64StdPaddingGzipped

func (ctn Writer) ToBase64StdPaddingGzipped() (string, error)

ToBase64StdPaddingGzipped encode the container into a pre-gzipped base64 string, with standard encoding and padding.

func (Writer) ToBase64StdPaddingGzippedWriter

func (ctn Writer) ToBase64StdPaddingGzippedWriter(w io.Writer) error

ToBase64StdPaddingGzippedWriter is the same as ToBase64StdPaddingGzipped, but with an io.Writer.

func (Writer) ToBase64StdPaddingWriter

func (ctn Writer) ToBase64StdPaddingWriter(w io.Writer) error

ToBase64StdPaddingWriter is the same as ToBase64StdPadding, but with an io.Writer.

func (Writer) ToBase64URL

func (ctn Writer) ToBase64URL() (string, error)

ToBase64URL encode the container into base64 string, with URL-safe encoding and no padding.

func (Writer) ToBase64URLGzip

func (ctn Writer) ToBase64URLGzip() (string, error)

ToBase64URL encode the container into pre-gzipped base64 string, with URL-safe encoding and no padding.

func (Writer) ToBase64URLGzipWriter

func (ctn Writer) ToBase64URLGzipWriter(w io.Writer) error

ToBase64URLWriter is the same as ToBase64URL, but with an io.Writer.

func (Writer) ToBase64URLWriter

func (ctn Writer) ToBase64URLWriter(w io.Writer) error

ToBase64URLWriter is the same as ToBase64URL, but with an io.Writer.

func (Writer) ToBytes

func (ctn Writer) ToBytes() ([]byte, error)

ToBytes encode the container into raw bytes.

func (Writer) ToBytesGzipped

func (ctn Writer) ToBytesGzipped() ([]byte, error)

ToBytesGzipped encode the container into gzipped bytes.

func (Writer) ToBytesGzippedWriter

func (ctn Writer) ToBytesGzippedWriter(w io.Writer) error

ToBytesGzippedWriter is the same as ToBytesGzipped, but with an io.Writer.

func (Writer) ToBytesWriter

func (ctn Writer) ToBytesWriter(w io.Writer) error

ToBytesWriter is the same as ToBytes, but with an io.Writer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL