From 40639b67152cc1c6c8b564b700838e2af78b6f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Mon, 7 Oct 2024 18:46:19 +0200 Subject: [PATCH] container: add readme, remove extra formats, remove go-ipld-cbor dependency --- go.mod | 9 --- go.sum | 28 -------- pkg/container/Readme.md | 86 +++++++++++++++++++++++++ pkg/container/car.go | 81 ++++++++++++++++++++--- pkg/container/car_test.go | 12 ++++ pkg/container/img/alloc_byte.png | Bin 0 -> 25480 bytes pkg/container/img/alloc_count.png | Bin 0 -> 23499 bytes pkg/container/img/cpu.png | Bin 0 -> 25156 bytes pkg/container/img/overhead_bytes.png | Bin 0 -> 31737 bytes pkg/container/img/overhead_percent.png | Bin 0 -> 29578 bytes pkg/container/reader.go | 63 ++---------------- pkg/container/serial_test.go | 23 +++---- pkg/container/writer.go | 56 ++-------------- 13 files changed, 191 insertions(+), 167 deletions(-) create mode 100644 pkg/container/Readme.md create mode 100644 pkg/container/img/alloc_byte.png create mode 100644 pkg/container/img/alloc_count.png create mode 100644 pkg/container/img/cpu.png create mode 100644 pkg/container/img/overhead_bytes.png create mode 100644 pkg/container/img/overhead_percent.png diff --git a/go.mod b/go.mod index ce6e58c..28cd9c6 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,8 @@ module github.com/ucan-wg/go-ucan go 1.23 -// https://github.com/ipfs/go-ipld-cbor/pull/102 -replace github.com/ipfs/go-ipld-cbor => github.com/MichaelMure/go-ipld-cbor v0.0.0-20240918161052-74fa05e9e786 - require ( github.com/ipfs/go-cid v0.4.1 - github.com/ipfs/go-ipld-cbor v0.1.0 github.com/ipld/go-ipld-prime v0.21.0 github.com/libp2p/go-libp2p v0.36.3 github.com/multiformats/go-multibase v0.2.0 @@ -22,9 +18,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/ipfs/go-block-format v0.1.2 // indirect - github.com/ipfs/go-ipfs-util v0.0.2 // indirect - github.com/ipfs/go-ipld-format v0.5.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 @@ -33,10 +26,8 @@ require ( 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 - github.com/whyrusleeping/cbor-gen v0.0.0-20230818171029-f91ae536ca25 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/sys v0.22.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 78f2e82..1d69a3a 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/MichaelMure/go-ipld-cbor v0.0.0-20240918161052-74fa05e9e786 h1:zKLMs9f7nmgEhu/JgIvcQ4zDRKczbTj3KXrVfOIQFd0= -github.com/MichaelMure/go-ipld-cbor v0.0.0-20240918161052-74fa05e9e786/go.mod h1:Cp8T7w1NKcu4AQJLqK0tWpd1nkgTxEVB5C6kVpLW6/0= 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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -11,21 +9,12 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3 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/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/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/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo= -github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE= -github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 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/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= -github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= -github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk= -github.com/ipfs/go-ipld-format v0.5.0 h1:WyEle9K96MSrvr47zZHKKcDxJ/vlpET6PSiQsAFO+Ds= -github.com/ipfs/go-ipld-format v0.5.0/go.mod h1:ImdZqJQaEouMjCvqCe0ORUS+uoBmf7Hf+EO/jh+nk3M= github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -40,31 +29,22 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-libp2p v0.36.3 h1:NHz30+G7D8Y8YmznrVZZla0ofVANrvBl2c+oARfMeDQ= github.com/libp2p/go-libp2p v0.36.3/go.mod h1:4Y5vFyCUiJuluEPmpnKYf6WFx5ViKPUYs/ixe9ANFZ8= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.13.0 h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ= github.com/multiformats/go-multiaddr v0.13.0/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= -github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -86,26 +66,18 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 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/whyrusleeping/cbor-gen v0.0.0-20230818171029-f91ae536ca25 h1:yVYDLoN2gmB3OdBXFW8e1UwgVbmCvNlnAKhvHPaNARI= -github.com/whyrusleeping/cbor-gen v0.0.0-20230818171029-f91ae536ca25/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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/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/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.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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/container/Readme.md b/pkg/container/Readme.md new file mode 100644 index 0000000..176358b --- /dev/null +++ b/pkg/container/Readme.md @@ -0,0 +1,86 @@ +# 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 +- \ + +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 | + +![Overhead %](img/overhead_percent.png) + +| 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](img/overhead_bytes.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/cpu.png) +![img_1.png](img/alloc_byte.png) +![img_2.png](img/alloc_count.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.** \ No newline at end of file diff --git a/pkg/container/car.go b/pkg/container/car.go index dcdd589..ee6d18c 100644 --- a/pkg/container/car.go +++ b/pkg/container/car.go @@ -9,7 +9,12 @@ import ( "iter" "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/codec/dagcbor" + "github.com/ipld/go-ipld-prime/datamodel" + "github.com/ipld/go-ipld-prime/fluent/qp" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/ipld/go-ipld-prime/node/basicnode" ) /* @@ -40,7 +45,7 @@ func writeCar(w io.Writer, roots []cid.Cid, blocks iter.Seq[carBlock]) error { Roots: roots, Version: 1, } - hb, err := cbor.DumpObject(h) + hb, err := h.Write() if err != nil { return err } @@ -67,11 +72,10 @@ func readCar(r io.Reader) (roots []cid.Cid, blocks iter.Seq2[carBlock, error], e if err != nil { return nil, nil, err } - var h carHeader - if err := cbor.DecodeInto(hb, &h); err != nil { - return nil, nil, fmt.Errorf("invalid header: %v", err) + h, err := readHeader(hb) + if err != nil { + return nil, nil, err } - if h.Version != 1 { return nil, nil, fmt.Errorf("invalid car version: %d", h.Version) } @@ -183,6 +187,67 @@ type carHeader struct { Version uint64 } -func init() { - cbor.RegisterCborType(carHeader{}) +const rootsKey = "roots" +const versionKey = "version" + +func readHeader(data []byte) (*carHeader, error) { + var header carHeader + + nd, err := ipld.Decode(data, dagcbor.Decode) + if err != nil { + return nil, err + } + if nd.Length() != 2 { + return nil, fmt.Errorf("malformed car header") + } + rootsNd, err := nd.LookupByString(rootsKey) + if err != nil { + return nil, fmt.Errorf("malformed car header") + } + it := rootsNd.ListIterator() + if it == nil { + return nil, fmt.Errorf("malformed car header") + } + header.Roots = make([]cid.Cid, 0, rootsNd.Length()) + for !it.Done() { + _, nd, err := it.Next() + if err != nil { + return nil, err + } + lk, err := nd.AsLink() + if err != nil { + return nil, err + } + switch lk := lk.(type) { + case cidlink.Link: + header.Roots = append(header.Roots, lk.Cid) + default: + return nil, fmt.Errorf("malformed car header") + } + } + versionNd, err := nd.LookupByString(versionKey) + if err != nil { + return nil, fmt.Errorf("malformed car header") + } + version, err := versionNd.AsInt() + if err != nil { + return nil, fmt.Errorf("malformed car header") + } + header.Version = uint64(version) + return &header, nil +} + +func (ch *carHeader) Write() ([]byte, error) { + nd, err := qp.BuildMap(basicnode.Prototype.Any, 2, func(ma datamodel.MapAssembler) { + qp.MapEntry(ma, rootsKey, qp.List(int64(len(ch.Roots)), func(la datamodel.ListAssembler) { + for _, root := range ch.Roots { + qp.ListEntry(la, qp.Link(cidlink.Link{Cid: root})) + } + })) + qp.MapEntry(ma, versionKey, qp.Int(1)) + }) + if err != nil { + return nil, err + } + return ipld.Encode(nd, dagcbor.Encode) } diff --git a/pkg/container/car_test.go b/pkg/container/car_test.go index 711fc86..9b0ef31 100644 --- a/pkg/container/car_test.go +++ b/pkg/container/car_test.go @@ -38,3 +38,15 @@ func TestCarRoundTrip(t *testing.T) { // Bytes equal after the round-trip require.Equal(t, original, buf.Bytes()) } + +func FuzzCarRead(f *testing.F) { + example, err := os.ReadFile("testdata/sample-v1.car") + require.NoError(f, err) + + f.Add(example) + + f.Fuzz(func(t *testing.T, data []byte) { + _, _, _ = readCar(bytes.NewReader(data)) + // only looking for panics + }) +} diff --git a/pkg/container/img/alloc_byte.png b/pkg/container/img/alloc_byte.png new file mode 100644 index 0000000000000000000000000000000000000000..ad4b54d676dd52a88d629f7ee099437ec21602e5 GIT binary patch literal 25480 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 B6s`aO literal 0 HcmV?d00001 diff --git a/pkg/container/img/alloc_count.png b/pkg/container/img/alloc_count.png new file mode 100644 index 0000000000000000000000000000000000000000..5f4e1b17e96f25aa5c7d7a367df82ad9811155ed GIT binary patch literal 23499 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
8FM`BK1|u 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 literal 0 HcmV?d00001 diff --git a/pkg/container/img/cpu.png b/pkg/container/img/cpu.png new file mode 100644 index 0000000000000000000000000000000000000000..4b2c293732bb1676b125485aa7505135c988f178 GIT binary patch literal 25156 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 literal 0 HcmV?d00001 diff --git a/pkg/container/img/overhead_bytes.png b/pkg/container/img/overhead_bytes.png new file mode 100644 index 0000000000000000000000000000000000000000..c8497876a4b8d34dd9a04bde2c388e9c4052bc32 GIT binary patch literal 31737 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 literal 0 HcmV?d00001 diff --git a/pkg/container/img/overhead_percent.png b/pkg/container/img/overhead_percent.png new file mode 100644 index 0000000000000000000000000000000000000000..fa9dfc4b7a8ed69ce12518bfc6ed386daa7f513d GIT binary patch literal 29578 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 literal 0 HcmV?d00001 diff --git a/pkg/container/reader.go b/pkg/container/reader.go index 15f47b5..61402e4 100644 --- a/pkg/container/reader.go +++ b/pkg/container/reader.go @@ -1,14 +1,11 @@ package container import ( - "compress/flate" - "compress/gzip" "encoding/base64" "fmt" "io" "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/ipld/go-ipld-prime/datamodel" @@ -20,8 +17,11 @@ import ( var ErrNotFound = fmt.Errorf("not found") +// Reader is a token container reader. It exposes the tokens conveniently decoded. type Reader map[cid.Cid]token.Token +// GetToken returns an arbitrary decoded token, from its CID. +// If not found, ErrNotFound is returned. func (ctn Reader) GetToken(cid cid.Cid) (token.Token, error) { tkn, ok := ctn[cid] if !ok { @@ -30,6 +30,7 @@ func (ctn Reader) GetToken(cid cid.Cid) (token.Token, error) { return tkn, nil } +// GetDelegation is the same as GetToken but only return a delegation.Token, with the right type. func (ctn Reader) GetDelegation(cid cid.Cid) (*delegation.Token, error) { tkn, err := ctn.GetToken(cid) if err != nil { @@ -41,6 +42,8 @@ func (ctn Reader) GetDelegation(cid cid.Cid) (*delegation.Token, error) { return nil, fmt.Errorf("not a delegation token") } +// GetInvocation returns the first found invocation.Token. +// If none are found, ErrNotFound is returned. func (ctn Reader) GetInvocation() (*invocation.Token, error) { for _, t := range ctn { if inv, ok := t.(*invocation.Token); ok { @@ -76,38 +79,7 @@ func FromCarBase64(r io.Reader) (Reader, error) { return FromCar(base64.NewDecoder(base64.StdEncoding, r)) } -func FromCarGzip(r io.Reader) (Reader, error) { - r2, err := gzip.NewReader(r) - if err != nil { - return nil, err - } - defer r2.Close() - return FromCar(r2) -} - -func FromCarGzipBase64(r io.Reader) (Reader, error) { - return FromCarGzip(base64.NewDecoder(base64.StdEncoding, r)) -} - func FromCbor(r io.Reader) (Reader, error) { - var raw [][]byte - err := cbor.DecodeReader(r, &raw) - if err != nil { - return nil, err - } - - ctn := make(Reader, len(raw)) - for _, data := range raw { - err = ctn.addToken(data) - if err != nil { - return nil, err - } - } - - return ctn, nil -} - -func FromCbor2(r io.Reader) (Reader, error) { n, err := ipld.DecodeStreaming(r, dagcbor.Decode) if err != nil { return nil, err @@ -140,29 +112,6 @@ func FromCborBase64(r io.Reader) (Reader, error) { return FromCbor(base64.NewDecoder(base64.StdEncoding, r)) } -func FromCborGzip(r io.Reader) (Reader, error) { - r2, err := gzip.NewReader(r) - if err != nil { - return nil, err - } - defer r2.Close() - return FromCbor(r2) -} - -func FromCborGzipBase64(r io.Reader) (Reader, error) { - return FromCborGzip(base64.NewDecoder(base64.StdEncoding, r)) -} - -func FromCborFlate(r io.Reader) (Reader, error) { - r2 := flate.NewReader(r) - defer r2.Close() - return FromCbor(r2) -} - -func FromCborFlateBase64(r io.Reader) (Reader, error) { - return FromCborFlate(base64.NewDecoder(base64.StdEncoding, r)) -} - func (ctn Reader) addToken(data []byte) error { tkn, c, err := token.FromSealed(data) if err != nil { diff --git a/pkg/container/serial_test.go b/pkg/container/serial_test.go index 76e8d74..6552f88 100644 --- a/pkg/container/serial_test.go +++ b/pkg/container/serial_test.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "fmt" "io" + "strings" "testing" "time" @@ -28,15 +29,8 @@ func TestContainerRoundTrip(t *testing.T) { }{ {"car", Writer.ToCar, FromCar}, {"carBase64", Writer.ToCarBase64, FromCarBase64}, - {"carGzip", Writer.ToCarGzip, FromCarGzip}, - {"carGzipBase64", Writer.ToCarGzipBase64, FromCarGzipBase64}, {"cbor", Writer.ToCbor, FromCbor}, {"cborBase64", Writer.ToCborBase64, FromCborBase64}, - {"cborGzip", Writer.ToCborGzip, FromCborGzip}, - {"cborGzipBase64", Writer.ToCborGzipBase64, FromCborGzipBase64}, - {"cborFlate", Writer.ToCborFlate, FromCborFlate}, - {"cborFlateBase64", Writer.ToCborFlateBase64, FromCborFlateBase64}, - {"cbor2", Writer.ToCbor2, FromCbor2}, } { t.Run(tc.name, func(t *testing.T) { tokens := make(map[cid.Cid]*delegation.Token) @@ -92,6 +86,14 @@ func TestContainerRoundTrip(t *testing.T) { } func BenchmarkContainerSerialisation(b *testing.B) { + var duration strings.Builder + var allocByte strings.Builder + var allocCount strings.Builder + + for _, builder := range []strings.Builder{duration, allocByte, allocCount} { + builder.WriteString("car\tcarBase64\tcarGzip\tcarGzipBase64\tcbor\tcborBase64\tcborGzip\tcborGzipBase64\tcborFlate\tcborFlateBase64\n") + } + for _, tc := range []struct { name string writer func(ctn Writer, w io.Writer) error @@ -99,15 +101,8 @@ func BenchmarkContainerSerialisation(b *testing.B) { }{ {"car", Writer.ToCar, FromCar}, {"carBase64", Writer.ToCarBase64, FromCarBase64}, - {"carGzip", Writer.ToCarGzip, FromCarGzip}, - {"carGzipBase64", Writer.ToCarGzipBase64, FromCarGzipBase64}, {"cbor", Writer.ToCbor, FromCbor}, {"cborBase64", Writer.ToCborBase64, FromCborBase64}, - {"cborGzip", Writer.ToCborGzip, FromCborGzip}, - {"cborGzipBase64", Writer.ToCborGzipBase64, FromCborGzipBase64}, - {"cborFlate", Writer.ToCborFlate, FromCborFlate}, - {"cborFlateBase64", Writer.ToCborFlateBase64, FromCborFlateBase64}, - {"cbor2", Writer.ToCbor2, FromCbor2}, } { writer := NewWriter() diff --git a/pkg/container/writer.go b/pkg/container/writer.go index 28a9dc1..cec6675 100644 --- a/pkg/container/writer.go +++ b/pkg/container/writer.go @@ -1,13 +1,10 @@ package container import ( - "compress/flate" - "compress/gzip" "encoding/base64" "io" "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec/dagcbor" "github.com/ipld/go-ipld-prime/datamodel" @@ -15,12 +12,16 @@ import ( "github.com/ipld/go-ipld-prime/node/basicnode" ) +// TODO: should we have a multibase to wrap the cbor? but there is no reader/write in go-multibase :-( + +// Writer is a token container writer. It provides a convenient way to aggregate and serialize tokens together. type Writer map[cid.Cid][]byte func NewWriter() Writer { return make(Writer) } +// AddSealed includes a "sealed" token (serialized with a ToSealed* function) in the container. func (ctn Writer) AddSealed(cid cid.Cid, data []byte) { ctn[cid] = data } @@ -41,19 +42,7 @@ func (ctn Writer) ToCarBase64(w io.Writer) error { return ctn.ToCar(w2) } -func (ctn Writer) ToCarGzip(w io.Writer) error { - w2 := gzip.NewWriter(w) - defer w2.Close() - return ctn.ToCar(w2) -} - -func (ctn Writer) ToCarGzipBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCarGzip(w2) -} - -func (ctn Writer) ToCbor2(w io.Writer) error { +func (ctn Writer) ToCbor(w io.Writer) error { node, err := qp.BuildList(basicnode.Prototype.Any, int64(len(ctn)), func(la datamodel.ListAssembler) { for _, bytes := range ctn { qp.ListEntry(la, qp.Bytes(bytes)) @@ -65,43 +54,8 @@ func (ctn Writer) ToCbor2(w io.Writer) error { return ipld.EncodeStreaming(w, node, dagcbor.Encode) } -func (ctn Writer) ToCbor(w io.Writer) error { - raw := make([][]byte, 0, len(ctn)) - for _, bytes := range ctn { - raw = append(raw, bytes) - } - return cbor.EncodeWriter(raw, w) -} - func (ctn Writer) ToCborBase64(w io.Writer) error { w2 := base64.NewEncoder(base64.StdEncoding, w) defer w2.Close() return ctn.ToCbor(w2) } - -func (ctn Writer) ToCborGzip(w io.Writer) error { - w2 := gzip.NewWriter(w) - defer w2.Close() - return ctn.ToCbor(w2) -} - -func (ctn Writer) ToCborGzipBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCborGzip(w2) -} - -func (ctn Writer) ToCborFlate(w io.Writer) error { - w2, err := flate.NewWriter(w, flate.DefaultCompression) - if err != nil { - return err - } - defer w2.Close() - return ctn.ToCbor(w2) -} - -func (ctn Writer) ToCborFlateBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCborFlate(w2) -}