From df9beadf9cf003dc64f91c40e24fe2243d11023d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Wed, 18 Sep 2024 12:53:31 +0200 Subject: [PATCH 1/5] add a token container with serialization as CARv1 file --- go.mod | 11 +- go.sum | 30 ++++- pkg/container/car.go | 186 +++++++++++++++++++++++++++ pkg/container/car_test.go | 40 ++++++ pkg/container/container.go | 63 +++++++++ pkg/container/container_test.go | 52 ++++++++ pkg/container/testdata/sample-v1.car | Bin 0 -> 479907 bytes 7 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 pkg/container/car.go create mode 100644 pkg/container/car_test.go create mode 100644 pkg/container/container.go create mode 100644 pkg/container/container_test.go create mode 100644 pkg/container/testdata/sample-v1.car diff --git a/go.mod b/go.mod index 02f05fc..7059979 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,10 @@ module github.com/ucan-wg/go-ucan -go 1.22 - -toolchain go1.22.4 +go 1.23 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 @@ -20,6 +19,9 @@ 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 @@ -28,9 +30,12 @@ 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 lukechampine.com/blake3 v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 9047c44..a2ea228 100644 --- a/go.sum +++ b/go.sum @@ -9,12 +9,22 @@ 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 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs= +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= @@ -29,22 +39,31 @@ 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= @@ -66,22 +85,31 @@ 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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/pkg/container/car.go b/pkg/container/car.go new file mode 100644 index 0000000..677fe7d --- /dev/null +++ b/pkg/container/car.go @@ -0,0 +1,186 @@ +package container + +import ( + "bufio" + "bytes" + "encoding/binary" + "fmt" + "io" + "iter" + + "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" +) + +/* + Note: below is essentially a re-implementation of the CAR file v1 read and write. + This exists here for two reasons: + - go-car's API forces to go through an IPLD getter or through a blockstore API + - generally, go-car is a very complex and large dependency +*/ + +// 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. +var EmptyCid = cid.MustParse([]byte{01, 55, 00, 00}) + +type carBlock struct { + c cid.Cid + data []byte +} + +// writeCar writes a CARv1 file with no roots, containing the blocks from the iterator. +func writeCar(w io.Writer, roots []cid.Cid, blocks iter.Seq[carBlock]) error { + if len(roots) == 0 { + roots = []cid.Cid{EmptyCid} + } + h := carHeader{ + Roots: roots, + Version: 1, + } + hb, err := cbor.DumpObject(h) + if err != nil { + return err + } + err = ldWrite(w, hb) + if err != nil { + return err + } + + for block := range blocks { + err = ldWrite(w, block.c.Bytes(), block.data) + if err != nil { + return err + } + } + return nil +} + +// readCar reads a CARv1 file from the reader, and return a block iterator. +// Roots are ignored. +func readCar(r io.Reader) (roots []cid.Cid, blocks iter.Seq2[carBlock, error], err error) { + br := bufio.NewReader(r) + + hb, err := ldRead(br) + 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) + } + + if h.Version != 1 { + return nil, nil, fmt.Errorf("invalid car version: %d", h.Version) + } + + return h.Roots, func(yield func(block carBlock, err error) bool) { + for { + block, err := readBlock(br) + if err == io.EOF { + return + } + if err != nil { + if !yield(carBlock{}, err) { + return + } + } + if !yield(block, nil) { + return + } + } + }, nil +} + +// readBlock reads a section from the reader and decode a (cid+data) block. +func readBlock(r *bufio.Reader) (carBlock, error) { + raw, err := ldRead(r) + if err != nil { + return carBlock{}, err + } + + n, c, err := cid.CidFromReader(bytes.NewReader(raw)) + if err != nil { + return carBlock{}, err + } + data := raw[n:] + + // integrity check + hashed, err := c.Prefix().Sum(data) + if err != nil { + return carBlock{}, err + } + + if !hashed.Equals(c) { + return carBlock{}, fmt.Errorf("mismatch in content integrity, name: %s, data: %s", c, hashed) + } + + return carBlock{c: c, data: data}, nil +} + +// maxAllowedSectionSize dictates the maximum number of bytes that a CARv1 header +// or section is allowed to occupy without causing a decode to error. +// This cannot be supplied as an option, only adjusted as a global. You should +// use v2#NewReader instead since it allows for options to be passed in. +var maxAllowedSectionSize uint = 32 << 20 // 32MiB + +// ldRead performs a length-delimited read of a section from the reader. +// A section is composed of an uint length followed by the data. +func ldRead(r *bufio.Reader) ([]byte, error) { + if _, err := r.Peek(1); err != nil { // no more blocks, likely clean io.EOF + return nil, err + } + + l, err := binary.ReadUvarint(r) + if err != nil { + if err == io.EOF { + return nil, io.ErrUnexpectedEOF // don't silently pretend this is a clean EOF + } + return nil, err + } + + if l > uint64(maxAllowedSectionSize) { // Don't OOM + return nil, fmt.Errorf("malformed car; header is bigger than MaxAllowedSectionSize") + } + + buf := make([]byte, l) + if _, err := io.ReadFull(r, buf); err != nil { + return nil, err + } + + return buf, nil +} + +// ldWrite performs a length-delimited write of a section on the writer. +// A section is composed of an uint length followed by the data. +func ldWrite(w io.Writer, d ...[]byte) error { + var sum uint64 + for _, s := range d { + sum += uint64(len(s)) + } + + buf := make([]byte, 8) + n := binary.PutUvarint(buf, sum) + _, err := w.Write(buf[:n]) + if err != nil { + return err + } + + for _, s := range d { + _, err = w.Write(s) + if err != nil { + return err + } + } + + return nil +} + +type carHeader struct { + Roots []cid.Cid + Version uint64 +} + +func init() { + cbor.RegisterCborType(carHeader{}) +} diff --git a/pkg/container/car_test.go b/pkg/container/car_test.go new file mode 100644 index 0000000..711fc86 --- /dev/null +++ b/pkg/container/car_test.go @@ -0,0 +1,40 @@ +package container + +import ( + "bytes" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCarRoundTrip(t *testing.T) { + // this car file is a complex and legal CARv1 file + original, err := os.ReadFile("testdata/sample-v1.car") + require.NoError(t, err) + + roots, it, err := readCar(bytes.NewReader(original)) + require.NoError(t, err) + + var blks []carBlock + for blk, err := range it { + require.NoError(t, err) + blks = append(blks, blk) + } + + require.Len(t, blks, 1049) + + buf := bytes.NewBuffer(nil) + + err = writeCar(buf, roots, func(yield func(carBlock) bool) { + for _, blk := range blks { + if !yield(blk) { + return + } + } + }) + require.NoError(t, err) + + // Bytes equal after the round-trip + require.Equal(t, original, buf.Bytes()) +} diff --git a/pkg/container/container.go b/pkg/container/container.go new file mode 100644 index 0000000..6632a85 --- /dev/null +++ b/pkg/container/container.go @@ -0,0 +1,63 @@ +package container + +import ( + "encoding/base64" + "io" + + "github.com/ipfs/go-cid" +) + +// TODO: should the invocation being set as root in the car file? + +type Container map[cid.Cid][]byte + +func New() Container { + return make(Container) +} + +func FromCar(r io.Reader) (Container, error) { + _, it, err := readCar(r) + if err != nil { + return nil, err + } + + c := New() + + for block, err := range it { + if err != nil { + return nil, err + } + c[block.c] = block.data + } + + return c, nil +} + +func FromCarBase64(r io.Reader) (Container, error) { + return FromCar(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) ToCar(w io.Writer) error { + return writeCar(w, nil, func(yield func(carBlock) bool) { + for c, bytes := range ctn { + if !yield(carBlock{c: c, data: bytes}) { + return + } + } + }) +} + +func (ctn Container) ToCarBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCar(w2) +} + +func (ctn Container) AddBytes(cid cid.Cid, data []byte) { + ctn[cid] = data +} + +func (ctn Container) GetBytes(cid cid.Cid) ([]byte, bool) { + b, ok := ctn[cid] + return b, ok +} diff --git a/pkg/container/container_test.go b/pkg/container/container_test.go new file mode 100644 index 0000000..dfa7282 --- /dev/null +++ b/pkg/container/container_test.go @@ -0,0 +1,52 @@ +package container + +import ( + "bytes" + "crypto/rand" + "io" + "testing" + + "github.com/ipfs/go-cid" + mh "github.com/multiformats/go-multihash" + "github.com/stretchr/testify/require" +) + +func TestContainerRoundTrip(t *testing.T) { + for _, tc := range []struct { + name string + writer func(ctn Container, w io.Writer) error + reader func(io.Reader) (Container, error) + }{ + {"carBytes", Container.ToCar, FromCar}, + {"carBase64", Container.ToCarBase64, FromCarBase64}, + } { + t.Run(tc.name, func(t *testing.T) { + ctn := New() + + builder := cid.V1Builder{Codec: cid.Raw, MhType: mh.SHA2_256} + + for i := 0; i < 10; i++ { + data := randBytes(32) + c, err := builder.Sum(data) + require.NoError(t, err) + ctn.AddBytes(c, data) + } + + buf := bytes.NewBuffer(nil) + + err := tc.writer(ctn, buf) + require.NoError(t, err) + + ctn2, err := tc.reader(bytes.NewReader(buf.Bytes())) + require.NoError(t, err) + + require.Equal(t, ctn, ctn2) + }) + } +} + +func randBytes(n int) []byte { + b := make([]byte, n) + _, _ = rand.Read(b) + return b +} diff --git a/pkg/container/testdata/sample-v1.car b/pkg/container/testdata/sample-v1.car new file mode 100644 index 0000000000000000000000000000000000000000..47a61c8c2a7def9bafcc252d3a1a4d12529615f5 GIT binary patch literal 479907 zcmdSBRZtz;(yooW>%`q5XmHoy?ry=|-QC@TySuwXfZ!6`JxGAyhwQW0D%N+C|GW6B z&f>a9O{&Ly-nU1O9+NxI*xts*(ZO$tT8#n-*e+)mgz#PvS&t~k82RzAB9>MjOd+o_4OvAu(tjWzIhi2rX3qJ)6ff&J9kP7mV^XFOuvNS(Jd z{qMJ#FJ(8=_wi8BHQ}u=;<6T|Q=!iO zNagh)J~5HNCL!IMHV1)65=PfX6{g=_2mH!-7ERt++QP$L zF9`?O)_d_m#~buJ~qfQNd<{?*_Wvv1wjvydgi3JwF;2fgnvgXnOaj(8EsnL_~UKh{jg9!E! zc+84I=z?-6Rn5l;4CEwW$VA)=+TrX@(`9fOd&f&m8=xi7@U5BpuZN>~jE^d+nv==6Y~5oF#z9g3{DpJZ9+ zqM&7n$6;!v9Wh$eR%gyd5|mWF1?0UjUad|(!F~szc|(H7>(*YkZsVb5g_^aIQqtT3 z>cGB*FMJcYB@ls{NOg*`EY6~`1oxFO^caW zb9d>NuU_afcpyN=P7H`+JOPVCWllW)JZpV3eKbT#AW<(7sMAE zK>YBc_O2;aFRm35{t<7uWR;p;fkY;ifZ*EjZ&eiFk?u^mJ-f8NrxRqaYZ{?0uZ*FWo zn^7jViqYO&QbyBAS{LLQZ1W|iI(m1Vnx2`cgiq(Av18j}s$TjnE_qiMQ+b#~?rXCm zgP#zVZF#(W2tUTKZ#Jz1%C|t()+?gr1}T~=%8^=MXQNdPD%VV5#9Vk3vjC~To4a8w ztT=1gvu1Vq(a-@|4NgW5ZU7-et0g(BrkCc!`p`=dQ$|00*B$Vj_HC~%SR5x>;%sh2 z>S?S?!1XewedO68u!GBRHu3ESDGG}+NV;{%p?J3V^� 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 Tx_{@>Ah$cBb;X>)D9fct)9`U;$XV@y4$E$ z*eQTV_~wpPza$N;iF~qTt9(-U8?Ha){td4GT%5MRg*Z2duf6>MQGARCBcHJWbpUH^+{uK~fG)irF2I@#40d52k zF^uCx;189qqdV^>>5k8vtkAV&`I)V_C6xvbbYMeQLIdQ1HIAao)|W;J*~VL;vj}Yr z3BDbI4T6}j8IS+QUyKNMtbNPy}!6Jf6!jWK!#e`B3md?ulTSI1pvQVLqJ zy1?>!$rs6hNmkR#C+yOQ;1nMs2+!Li(WpM#gT~R^t&*URHe2G&zzARMh`pu4yJ)C$ zr8#R8Nu^i>m}3YEQa11np*0(Fw=uR-hn8#{x)GZV8-;By6^@d?Ud|y-@VBFCHC)oc zI%j46hO3RlpX+wR`jG34ntx=Ab>4#8VR_u+ioKt*NQ=;>l?DsypKu+)e15!5+_o#r z{kSC+FSs_&&ZI{3#AvpWpT;JaI&b|37g-Fz?j12l>%a+`3kUIO`la*}Hor1ijrqU1 z^C4_8(UHHH+&jL1i1_b=%jylTW=Gc-)3n{~A!yCbxyPNUYg1!>C&IfOC84V}2#4nI zKp#c_^&lRD1^+EEm^6S72we;?v$90->Nb9vUdRMWndUO#L!TEHCsrFnN-Hk9ASS^; zS7N>JbJ_T5MRCUK-xcJaa{m`x@y6(J0@rDR1r%Rb)U=zaTa%I4B&#S@+d#m|$2Afn z<&FKv6%0Lv-D2EIqY#Y;!C?GBUAFer44j{0@;S)}Wtr^8Y`(yl=En~f^S=z2jq@6# zV3p^{ZqsjRpX9JyzQGmd*JCEI>FCqqun^J`5n0#ySooQ<5WN-MwM3z?=xHGdJ(_Ib z=s3`VexA(*6h5rhd`9y;XEhkLWHTr`{G~Jdh}>Zg5&wyUf)GA zoQr;0SF>M<=&nzz#IA5h0J&ARs9-q=&c}Q=mC{q;o`c>yH`fv~6yI-9#K8OCN~1v3 z^y+9LM5aq%>m&S4CfJU69rZPS;wsKSrUw7~Dx^fma;)yCf(?T7iBC=PJDmi61TYj) zJat9T@GAo+t_sKxp2y<2)&o-JGnqe->rZ!xT)zv8TH$sla7^==&z$r1ftVQlAb2q_-PlLeoF8z^xwzf?>EZ9ZM*eh z$j;qF#Bo}A7kR-y!B)CUt0@Kcnpjq*^Y%<#wD-Y&My(r67;Kf`vwc=UofJ2R_q%!3 z&Rv*w1o{vy_<#t+sCf-URUYBZBQTrS^0+mh$Hkt0X)JHz%uy=vcdzwN+w>QQafqeC z>zA0q2&o&^KY`t4P}JuJmi821H8+;(kc3W^1IjS+o<`~D(?8E zVxssb@Dnq`_jI-l#S!As?}w|7OMrQ|cE+8_O!JJbkVO%0GlCS@IQX(hLF_a8392%D zm-C71YN&kZ@kbs+o0u-=VDwR`IsNKZFxL2A7BZC6wN+2Mt)+{P8G{I(%1-HqoDz9Sv z_$1LGq5T35wZ43XPPoe67>d&&2>&sK+rX)WTTPr?a{po@sGE~4@o^uT!Hn`{9!W_T zNl=YwJ5dTs`I&ReSX2?F!ghY`gF&lCR?s=>jxiQ(Z?$duS=3w=x7iwzk~-r}gG8)t zNULHRGQE6$dK-{onL5i6*DeZ@6oyX_{lOI$@WuP$fV>2v93SD8gs}Di?aAq|zqnB}uLrFLjrFw$azwR?q_;|@S z2&%1xDFa4RGKZ^SJkUzz)7?wC!cK(;bN7bE@v?3Q&p95!6TD7i)<=g;B?c%;!nW(? zEY*dM)ETLN_gY8qRPlWsMsWRhn0&{TM6(h%L`o(6gtz6WXeefKE~T*u|1*uauAtbA z_N)z18U9?V$2lj5IY7pJ%iGOSnAR!}Sce7t&t5CuqUJ$CfPhY}dX{%;O~YJ;<=H?G zGZAXrG;c$FiK+gZhztt>Y~CqDwP~Oq_!fd7Lenplo)%U#(wo;!5F&gyQsoJH?4U{B zccK425kY+u5#Mg}F+4*=2d)5RWT7749W-_R%V;nlPHbt%VcCK$zXMD=qwk@bkG7)& ztBX6;ToAgPP*MD;H{J9iiJ2hMS$GnIH-20|Cpf-6^p#AzUBkiB>gIJ+Tp3S_KTJJ~ z4}b#y+Yb6u?%zb@KdZS8&?+OpO<% z7X6OV32@SSm1g-U`^BBB+BVuVm@^%g6tq!VQg1JyA&g@3g&gKxmsU|#!!hDuh*h{{ z3B#Dzgs;`#%)FtdN)3-+*tU7|!$&;g$32=T<)@R$na-S zTqpt9DUV6ow=__opF_oc5N@na%v?Z;;J=kbwyBM5wlCRU$VV3V(G*z`k&EnXKb}+` zhib)X@PL@Lv+}In!}#Kg_k8l_z5{O8we3d|V12iC)Sa_p%ju1vQf9PzD{)%v-~3eN6t}U}i*}-&G2!gj ze9o>uAPw=+(4IH&!-;CpMXohk{|eESzJ!hNoGb-k?8~|Jcl*Vb?cbF$_8BBv)w0zr z=}%5LCPZ1~%gvBrYBN0dq+U$*%1Aibe-8SVoL2XJ%TS&(z^uHIO*Qc5_%dsFXUqB2 zLbCZX>rOB94wMwK)V$Nk9&OaC*p#8 zE8QAUASI))Qmjy;Fe;oOpQ&pINzUHC687iyfk}QB`mdvqZ2yhIC_>1V+b0q)jSBY3 z^Gi9!N71v|j2HvDmFkwe1(U{3P`jBpM@2@2548#sf%+L;!EYJ`_|F-f!ZPQ;??jMtL3+_@>LBD+d zY9<1%Sr4g8hbHsNqWm2fLy@FvS5B$q1cO%%7KD^PKihE40g>OclXFVya}LL6?$uu{ zPa~UoR*sn8z;R_@*pw9b+gHb>kbEIkq0Gq63;mdTKr`iet35>q-o6(*dLdIWv0S5O9@&P557hX$AFgQrQio!ROW z?`?^#Q5!v!>g7M=d(TfugS4?9Tij1;r(qw+I@<)f!L?jDwTlNiv$b+r{@7}lZYE!x;3oTynF7lh5D zri@5DUaa5h(n7k{hk%Lo#h?pLa$7c4+99|?`yxj;De6LTv3c6I~%u#@(wUk4~ovzJoyBE28qBn zFZ$SlTCX4-5VnKgG$DZ+2w3Y0%l#_Z21CkM=`1$lXQ*sgz8@s?k;6>H&M7~@_ih9H zx0S2oE|{eP5SI@(gG^`Omy<-g&!!85BA-DyH!Z@J8dR}x|8s3xWSV4LX(jY4R$ehe zJV|K$(3B&_|G;5rgx$LJ`rhs z6On*bo#vYvS#9dWNOTY6rQX2Q?m0Py0msx_q*|Hq(ni&Dw!;^?4hPe%eM0e*3n>M#iAy!rOcA>RUm5H9TXrk{tnY}b=&dEUq5r1q+ zVYyLjV;0(r1bM=RW40@Z-@u+DoVuNAB&6N%(6j7-Y)xLUBQ!JaAOs>Uthj3TFVpWN z|Kb4+%uZrJtJtm(e&6||AuRs(z+P{*oB#o+QK+O{5rydL04p_hjoQZwnp(S~ZLEJ& zh#e)G^wq|8e!2}-wafffmzI%@?8iQ}t#0eS6XQu1X!G0X0nqqm73w-|LVoR53a~JxB@YJ=-_$c z?Kd7Xs4=a44gx@Dz~mFEwL@pLE;I7f;m;Ln&)1v8@l#0~p&8VYJ_9l!VZQO9eh|2D z9RQ0abL7`H&i9}CNV(fty@Oifr@RS9V0%^x62b1TMg~VnruMf(|0(x>!BzG=CgWJ4 zmOft!^@(L@Mh;Q2h`7W%hlb`zOm`+F^)+RnoWHW_nB8dixjHrvNDu3m^dNHOqha=V zzNDToM{nDbJsKJSENkQ>Ku*`2hsWK-Fu*&VfPg@mFOba;gr%@Q;QV9W$9c3Us!t6o4+0jqRNMxSx`; zd=1K^x}L+iML7CZHoAdo%Je2@|Hevw4ICe-?O50@ z!>P61f|RU1S0CXM)@I{l?Asn$9>y@@Tavb7;>!A2ZV&@}AvD>eSJk;f-M;V%OkS7m+mv&>41O&7j#vY?L{}E4$lXTP%0<_ z<8=oQo2|8c;DaVt?y)r@_0K7r0y!mj(R{L|b2rkL{`<>qhGi3bi#C1BqBpI9;4;C4<-CCCu-)MX%ovUn0$fd7mhV=S!4TO6pBN`{X(u`%{GY#j@wryPZ~l>buBgdub(t8PrA1Nx+L)dv z75NUYt4H62_f13)1_2iDL}U>tF#8h}LY?c&@~vX-+RleOTy0yXm2wQeo3%`$&b@b` z|2`4XeG`#lQ9fa}AQ-rnDrkmOKRsltZE5xl=WNz*P$cg1u-in2uCODBc1~7?4wX~lS7IY~URD-kQTn#&fhuxB+H_hLI9T^A1?>X8M6#1DX0JYxA>?4u zn?w7y2f9BuIs*F#-B(+}Tx^o@Kd2vJ(GddE&{EITyI~?0yGC3o(((ELPllvI1Suuh z>lA$QG*+%#d$!m5wPOwpWOYgJvN{i6StA2cc)~ZlOUxhz`Cap<-}?GNx-=Trce;|S z0^M|m7G#mKPy+xi=NDz~IsIs8x1mG@jUbC|l#7Ray+h6ZSejm9YgbqNX^5O_YzDh$ znehB4sRhf`VX${EPZn=y7u}81x>qrdjH3NSk%oL!%3)2!5=^<8UbBTbf#u$2?``xZ zYCb4j^r8N>^No$;akQsYC?7tn_F#`k|-M+c_P%D-U-9CA{ zwsxU!#O*Y<>U6@M@)N20+xY)KMvo`(3i~lMj(umXh1$6tyob5ZWU1MCu0Pe!E6xZF zLemKYp=?zE%-<377_}krvxF^oi^0fP?deIzH$33hTug6p z`F)85XbV}Lp0UF90<6xF3#YQ&EbIr>U7tWQs8F7oIXuhiGv#81WWN6&>fR|l)9h*c zj;)SuTOHfBt&Wq9la9@fZQHh!j%}-B+nq1@AMebUd3I)d_Uq0@UHP3=YgMhP%2+IC zLPI27jEN{Q4K>Y3d`v*PWi1jEzI^k_?b`L&U)`2N4) z`ZwSI1y`Q5_E8c@N~}?f)gN$&Ibu_yU!k$fxNG5v%OX1>6K63iylQ#aW-U`jzRE=L zH}y!BGAbaNykFYQySD826DOw^Rm&RP`r&0eIrt+U>>ap@aAY3b_ds_g>Jj~_Xg!;-jK4y%v-r~rd9Lu`HV(+7!e-OKEU=ehm<@Z9Rpl zGYfF2a;YJeJo(OzLm1{&mT@#&k3Z9qt=SeLXR15!0T+3+FK?G#3VI5n`Np_$u1zfv zE%~t^y80EGzP?iS5C#SW$Uo-PVj4ggtQD!9(g_%#i2JXRJ;?vDQG0QRKi3F2Bt(xV%OB0H=qPk%&(0>{((08~(o*vRqMx|&FSndKbOo_5oMPRkKsFK!zex$!)Y9jI273L6B z!SNJ+F!@7Y8)Kvl6bk@fZijcU@;rse_SS3;*_=HnMc|+VpT^vh%vJ8bK_(2na?LP= zu>g>AnKpb;t#PHoSoECPuC@&smK?3&ul-S%cOtPbdY9}B9nD5j0(5eRwXc52l_834 z`dF*7ww}I`{YY;mDPfLZB@!dkk6iGbQ0 zrA@KV*D9lBulHbs(DnNJ&{vlRih#~U#H|@PA8XU1|2M6II%z5gdA|6KzeMXS@|B0R za$CEcCjR*yw&(ywsXU+VKZiR*yGur6rI-vf6vw9O6AFufuXE)<^bbG)o($|Z zY5nN51)cs#f5UhLS3)DfiuZvyXHEyFQBE5j`&(l=N?Fqy7g8_I-$cJqHvZGADfM}r;FT>N31&N1E8{phTMYh|)-5ppVO;VdvxZAla z6Z|bA|K|I@M5LKwiP7=KnTX=cW|vB#kWvUYip(Jij||F;vu|sD=z_xnAG>A4)GlY% zCM-V&?kf`XZ^@{tz>7zdTHW!NO-EqWCG@#;jalkmrrVpJDV{VwuC8qa!YE@;Hg}xx zV*(!{;_pd)0fCnPkZR-WaLaM%ztJh8$UR6^dDG(fn0pek=pG`3FKm-q)s$|ST)Wgs z+ZfaRd+y2BE^X>z&FOwF%oSo5^&Bp#W(EITo@-9QGiD6)wQ ziW+0Fu!dG`lSH_!XmnS;E#s=0xlHxrqnIG#OL@!FLjUS4bky-jv8>F%GF}y@=OMio zlu{Mh?y9q{Vo*%%N?On^oS=!~9~3PGKQKmMGOp?L2xuQC>EgIhC|j(!y~==Wy@-Zi zIil`hjC6=*x3Q+froT3JeoreDs>SUSQrqp62M(SfeL!p54A8_uyR)tpA~J`B59=c% z7c!WP#L*7HdGa)*Yet&Bx<-5x!d%^k0dk$&MDgoElO~Nw8ec&D?o^qXRheaJzqOpM zo5KqsdA|rOQO{RjmKBBG(@3C3_#q;u2G4vUI4GfA5`)r@J6hkhOy#QT5}qXpl!fw*)d{pCNFMLMC-XuMInmKuqgXtJl}jJ6bz7mJ`SRe0g0VJ z2Hk5;QcL&m{9)>E%}X46f8Y&H8O{N^=PUazA{zSWCZCjn0n5>OSr1J#J)mD-1>=jl zg@#gBB-*i93LQ;5+iFG9C)59)h?KsINWk|*WK@CsE*we5`~t*NnEfrIGZvVbVtiZS zHK^v$RX#sWnYZp9EUEzjrstM{H*{x#Y@NkNol|jn0=LQStVhtfNld`h|)O zdBRpUOl^Bz^AN$!3Ate!_%XY^NCI5XV*9X4ScsG+`;Q|O2o|sB?3`vyuD{Y%^|n|d z1w5rI=#TkuirOuLxS<5j#=7@3KX^yODV<22^M@cBxjFYJ+y-oN2?2OGR>ZT@pE2+B zdx89fMZ3k)W%A{389=dJU9=6! zt0d7mY5D3Z@M_Gn)#xiY=c{Aukmv1R6WK7Te>Pt;w(?ZvQvaa@#_d|0Ah(%SGLDt> z)bQlRzC69m8EaVZ5uhb9m~@;=EHD<%Qxi&EQv3DT7_>@Am)*TeRf10XJ^)h%kNf8h zh&%vd?x32Uca6+i>1w8bf6qP@By!6n&JQ+m4>JOPpDn`tig=4`t_ z9%FSNDZVTWN`9D@gLbF@@dLNq;yYY4V(7-7h=IEr5fIn=iDm0lfxz>0q6WiVgVuh@ z;>)XW7(?eR^Z3d1zXzA+J6wT-7&W1#$Fbn|QP|k{iN^b@H>8b77r+2$OGRfyPTIF> zmcL5=yq+~xT0&Qir02u?A#LzVr|WE}vM`obQbs5Ax}=_-g@D-_#=e3K*^3P0`TBy8 z1Mb-<8r-%r5a0hDq5sYIf5Fw{2;b-}HS)F|SSp$^cX#;0$Ipkw4?r=FZh)gVJxt+r z4xF3zu!Zkag!bj>O+R;;Oq5g?(`x_P`LO-w{)1OP?mDWhARbC(XUIfq%kj4cG#)(6<@X%_}iL6{N?W&)-`Sc#q{713Jx( zXgs0Y6dL2KIEfmKTT`g~$HlH8mU)QPO3aN67_!JzFDnn(9a#~Wde9OS2nF{F;-bVa zNA7CSlw!6sWXVX_p2(?@D{gU`kjX=o98BlE>~fSR$36V>!f{f1A98%ZLE6CSq|rL_ zYcXqSFmg)5it+@3+Z=+!u+>co^fh7ob(`1IboI`JwConHb`Xuu;iHbZDeuUa7fA_=Qhs!Xe_ z-0T#^R^XP7I{Qdosfw2Enmee7OU*`6;is9P00Fll`B_jkRQ3S0?Ao&R)p`H@pk$&# z&mcsZQ%N-3+~n$R#;c(MCBwq2J$J%=+4S*PojyQBhj2B$`kykB%Mh)+EZ-}J!R6l0 z^ld|sCc9i!%t2AFhM1o9a8>FmVH{^K&XFlc2n$%{zvvr9d}kRl;tr2!o5XP3# z^Dk6;^XsI&?tzQ*-`YqsUY0d3Rgp^gD+`oKY8QZ&yo(3`9s0LV%0TkEg2$rWXarTz zF~L{Pq%Ab)BlAL!Z;4lJ#>mOuQvJ#Fzb7K{?;?`tEUw}!UJ`y*H2Cs^>*uxb9j$lb z1Bt5Ck#Mu-GY1Mb)^$}>F49UvQ+z#Y_&f!$ZzdEU^+=Upxs;DDEH|~%$$~X{8?wn- zV)5H#e(iQ)gvs}MR)em~l|nG2N|E8eMdaUn|CfkFbfq%O)dDuUT*M}lM<*RDoOATU zjdN=Bj_vGc83IThn{Uq%)-OW@oD#cse@0GJJmV0<~-^^TyUq}!8)`C+R8e+ zTa#sJjjb3$rR)SygYfcnoV$&u(LVC|5Rr;pYTF4xxe^BXR~u{0jSl(J)(CjORsYgs z%Pikklzk%|+d$tSP%LD-Ev-UU%Evh7NRc0CGb)=y+O|_B_^;FyArR82Tem3h!0_ECsR}z2dAg zdDr^glPWlsY9I2Q{vJu>6?$M%a&=$?{u1jZ&Lzw<1_z*7^^G^(KZSI?Hw0z@o*&`X zOm>V51csCb2v#vc7YaGpO=E#To*I1?DCNt`$jbGV0U4Mylkj zDoq8A`qQNZd^2p^+ZPue!L-tkbut!&@Z207n^Z6~Y9>Xzv(C-ja2lPdrrVjh{HKWfn7&7`TAy%?T~N44AW7c%88o<`t?Oxbie4mFO@a# zjG7{ML(9za5fMuvs5)H)Yc~1RdjQ;fILW<8eg;rtUTa zxC3_TV$GmN*;JA2t&90j#rL~%&1sYTzh;)M(LSZh$Y6a?g7|b{<`D5w9@)75?&aQA z+GRIuVQIGiJEcd#N$I{=Bd#NjVaLl%8iE*v&~{Fs$56`EVK-UR5vE88;L8juy3r?P z=-FUpa3R|XXS3Lie48tR^kn!hiWv7To*%#Qqg5E`lj(m?M2O!-q^yyLKU?2`={0rU z16mq|#|dZw|EAykvdXoddC+tGS^Q1L#J6s4sSUk5xC!T+83>!+(C>w6u%w|@l zA?+?wF-A33y%?7U{?vjPo_x|w)CI!C$0?Up3%9ceQmOVe?SeJTrx-<8;gkc3%xsQ! z54@E~LSOgTHfFk=ZquZ3I3-oDkHrf}b1f9|Qs&FSpZE}wcu7$dN zBO?|V6$^j)$?~~4h%F1V);aI|h=*_aEO}%Mz)of$fZbzKOCb~`t z5?LqIU#A)bj?#mK4VM|GveG4)lE0*l$6MXo;DK^pb;{f77Hd7SjNVq5?W4VQfp!?3 z8Wj^e8{fxONp~VbIW^g)c4`uo9kFEF`q`)PR?o-!0z5)`CjhECmj-P;r1zmNcq*Hy zr9U^u6UkSqD9s_{$xAS3+xB9S_|VEGM>pb{gR#%rElP=)R~e_Xe~L@`WNJK6)pdCJmJgBw#_P7 zswO6#J2k!1$^`2fUxgfO&lbNW$eFr6Pmfs(v9lRbfZyRgR=nOC5O)=i6hJ|c6Zkc~ z^eO#cpm{);IFLtg{br>KzoHv{Qig}bC$pJxY*&aEG^F2AI3f?(rs<9|lg%xw#+csEh6|re|8pWj zbpI|Q)n*yBIV88T7&on$E?G8s?yN8o5cq>JjWvIm(ALX&-hx}}xyY^9Ja+a5h@w#! z!H)e$gI@^&>gc7?7^67ZnPSRaQO3zB>~4Ej?&Yaqy)QgXUKPVtrOkiJ7Mo}W|NTOeTis!&Hai z6GH`tZTNC$$xHye0GW06yf1tlAOwE_{gnoKo?xBIe}MY+{FR`QQq}m341nBwT;Tn# zAcp#o71~SC`<0>WA9I z_)YE9m2YTKYs)&2%&ZIsEKLgU&>JzmsfMcYD+FR#Aa%H8!V1q1ucebCXTX6$&2R(U z^!dTC`Mvcl@zx#U=7|x;Z3*YueEtV4%k5zMSZN02w@s;;HN zH0AaI)z_N5ILY=7U~x9f_|_Jf+ihVlu5b}BsIOr-YC}`*58C8H;=<+ ztCF={znC3Z(5xI|wkh%MsI2{`qov0f*r30PE5!-b^G_7-M@XNcMkve$fU4MDdbcWOGPAV*;%Cb z;s@QB`BVS?`O$it*!E7W1cp#*F5N`?&bmemT`)LFi0b5?T^xY6-gcrxRNANvH!em+&O;N&UZtl zHOtV={c7Vy^z+N6P2#~XtN?OdLPu+VZrB-ov-anfMe<^VUlX92M98FzO|>=Xkh!1 z7r4Sg7K@QmMXFF2JYf!EfGYthWz!)*!KBk3Uc^`q@0lBQribN9Al&BlwLRCLP|0X( z;|rajm?17PQx=%r!GN2asOiNTNnyVb>fLx%j>q&5hkmpp3e?Ks?3ARR2GGo?Jk%A$Mt^su&3Wyt8Z5 zB=uJ1O~Q&;tBMz=Yfi}gz3BVftdIZnam-)yOcq zT-!jr`(2vsE4yQC^J>`)^8Opt27WUb#y|~n$-r-4`&19-|i<>U#PZu zeH0!?#A=qTh7h&Sn)~=AipbHlEo|jEQmh}2ku$a@k&65owcUHq zYCnag@+d&>?Z#%lDt<6zfC+aZ%1-(nuJ{YBx0?O23aS{Gq47G3B*6}Ir6el)n;d+Vbt3Scy2vd(J`uZ~jigYE4Ah~TplMNlQ$bSmfk7g3%DgXAf?^a_x}`X)L~fdVi(C}gRg6nDgc-c1Gc7o|0?dbm_QaIVmHxIw z>1r~U9XetF;eHGfg$7Ai&>}JA4g^^;P|bXfhyl;|)mTQW0-fuS4Mc3*MoT$+rmVM^ z`X-#_1FjZt?z780>uK>V20F9z{qXP8vi@-)-f^3F#L#{~ z4pp}=W2Gw3@053SKq=)uw`{Sx5QZ)0{0wYWK~E6G(BcMJ8lay)(9;7hFH{#TAJnxdCqM`TcZD%KMZ-`_>qf;~$|;&9r^< z&41VfpE?=bW8uKxsU|k*5sQPnpFJV=I{M)PBzGIGEB31-*LBX`~d1 z5;X53rR8oFa@eixOj`5~SAZGcK_n>p{UtOEgmy2%D`q*+!XyC2zJG@sxzzf+5^$W| zu7#8)W`u^$+^AvSls{VUA;a^FBKo90ognO-i8?5MX}a<&WGygriKC2 zw#=Q0Ih9>T^3tFf)Kmxn;nWLV_Y*NJxqDy1%wp)()6j(FGJfhQ{JF`5ctQ~UCB)vG z{i{yQyb(#KH2e&>P{nFsOFfB;x# z-H_UO%Y;`Yhw?*AYGR&34CPnkE-L}nFnAwtrlbpnIR{@@O|1QvE!AQoX5<$&vV;v-_z$^Qh>e^4U-V|WFftRa@+ljYX zYxc)$@xsDi6ML4!Z^T|Y@CGZ=d?84Plp+fz5rx4ii0yoqhfW`G4Vy!ytQU<2|9JdtWp3kI1Du`2&vtFCI-ULV2n?vmyEFXJtUJGaY;o z4S;&WU~ShsTwTWKI-iJvj=VQI5hgIWbS`(_oC&buD{<3h454z~g&RQ_#qs{!m-XL+ z3-ukYfK)r;#0VPn!qK101yU^#l-l`2>3Kyb?2P42q z18V-B*zrdqMH!sCQH$n-cv@V+;;r>BSKXmmQ9xX0iriRIa0o}nXbFs^y1Fx0`5Uf( z^Zj3N`TAkdGzzcy5nYAIns1ZB>+_(HnI zq8aPLZJZ}Wk3{mP*&CuK%!;`fVn@B&ZdYm26DehG-VrSN@EO|v*DEq}kU@q*Q_vDM zZO)>B)|L*N_0z{YnshV*f~ss?ATd)AynSC2h73Oo2_pr&BS)LDY#%($1g?SUhYhw= z{c|Rt=S}sSjQja+2-|rt~96g?zZ|KwMnQ1*3 zdmc;Kh9!1Y@x9uX1|xP1x3{?Q(OF&TR^uHQE`4be1yR9!%eZdfY!JRWO&61-ic*#^ zi+C6Dcaj(m@dmMzUpRazS|Ccj3LJfzj<=MbJtlt5D1&or{Ix(;_yEQ7vbSYS~wp* zN$;aRkPs+|aw{{ehRf=h9Bo@-NKQMnOF*p`IDh+2vA=+|EBZAV?<+9~K}J2NSZbe^CJ>c6WK|K|I@;EL+B z*#@mkz5wisaNZT;5Ni$E6hw2Z(VowfRv{$EUKEODpL&Zwvyv4M;6@rsnM2faB|>w@ z>(lk}u>~mpvx)Fsg`5fqZ1h_4+La_IUuyzgw51d}Nrk0_d0l?T4gI4!Q8^MYc0cD4 zq~7LdHdUvuK>icP4L>enRop}-SD^m*w)@9U1vhadB#@O}2X#ahay+D|)`&DqIlQFr zkBsHAX;UT#&wYEp%!C??bPEXZ7Z1PhQw@q8VlLxsN>{hJ#-kL+W`(DC_H z&+snMXf**bJH94!%Y-(dRPCRur<(2|mMW(UM!v}oNEG8`p7A0Tbp3`odvMG0Z5!)x_Ym#t7GiAY{|L8d;Xqc z(D}Mx<0Fwb?r=NIt#H-Bt! zr-jb#NB4Yr$pliS4##t>x3PYy)MtQRpkUTv{XLJZ$2aPA%brvCg7BjNZ*<^A$wQw7 z`9KD1&{Y+uGY-t1%KY18ekEzWDt=zsnx9o{6`Xczr)f`OG|w0ZZNL4kprtDeb0~(&0`SC4gVPdF zR6D1N5IEykgC0R#fZ%p^EQ}eh8uxB;gSVT$^!OU*z#BiMUkkmFLZ!pe?42}Ty$Ogy z=+WW;A2>2Jpnp^+h)J|NDMJH=;b_E`29?Kz?q`}B>kmGD?zl(@5GrHC%W!V3@b&`B+4XX_20H(M;VSH=Ykz;?&!2OxK9C6NO^C zF8*3A2em9&OGu!JHn{jDOhXP6qfr7{J%L14n(dCF!o(Wi_}EK&sN7CqCGz>OpWyjC zY^pz1931|R(EsN9zeFUO80_j~^-2ZMR14FfJSVFh6X4-h=tRa3RrbMc>^?uyI4~QN zpIApNIIjpM^g$DK;yWZ!S<-LfGl~+LMF*-h{inQT(Wz0NDDuvy9ko}a>PHnv3_x#D zruV-gr``7+p#xi-1WRap4~Q#+*9L}N>UL^5H(A9yszL4_J6zqI5Q~k&p==*^pMvyd z6EDk`+oNK`EH3BBARkq5ld);*#oVL=&&s~&Hu{^;BQK7?rNYuixH+lC1Ln!uT6;qP z62jLsO%;VsRhGcX=y`K7LA^1Fvur@vQqc3!cNSSU*@#wG(OiDR1Q7owF{xg&!Pw-w zzwCAq=t#PQ8Q~bfJw#7+VorGH`G5lV(%mzvB$+i*?D|JGh!dWv8tt{wG{Vtd;r`m zjeW{9YV_F2s|f0;l7$eeTpGFfu&H~E7NHhc64Hu$h-rw?y-^N6BDA-3caPeVhP?2w zWan%1`?~eYo_XKi0!SOF;#XWKGF=Q};D4mQp5YR9KtGQ_Fyi6naet6=AP(W0XJ=h| z>>h8LhNa_+yu-zgg|7JtE;l28Ls9-vFN{>)sjLfN!UFhx-LTMT4M5Q}Sj4Ezl~1Ps zJ-8y@;R8!a4?Xpv)GE1D)up!f2?2V5wp%#Mge z5e+0n5y?L~3kj$@WCwW1s#K$NME{JeTGRpXzSZ8>y;i!M9q;vbM?<=T+$zP_fPlZ@ z`ZwSI1y^xd4&t}83!45|Q?djzNQqS87aEC^BOAGJ3X2;8>-G}6?PO4x1CP9_)(blctc#5~Sn3$kpYgzM5- zKU6=Hll26&RGG>QJ$haI<&#J4o6>W*zTP7eJNdg_@vewNOf|iN)3KI4nvQ8q3Dz00 zcmUN=i#COeThquzU}bUM_C}zVl;*?A)kwTaXT9RyE0cQgp^c+`c{TiYptR#knX9+1 zYz&gY`5{QvfW#fX+~wbzJFmm#@lt2Gi-MTm5*NQd;F6bzYaDsKp}m!9N=G+qm8L~1 z{qjKX*jTOG0Cd^)gn&W(&-Ax+O&<3y5?9~EXAHo9Fh2VzGfUg43=hK&8n$y+uW9}r zE*KzmjZefZRAH9$2r9Wn%d(cr5VXkRhHq(nKSxg8te2?2chDgGWcuHO%itZZDm1@j zkBzL{ZZ3A(CSn$a$>0H0rzQL&AO6QMt6h*uBnvVHM+3xLO$o7Hqk)=xhbtkNY+69C z_(ge&+w;Y1gv46LS+7%72mlR#}sdR{O_|@!e`!{p?pH+*T zP_yN>(w>AqD!NPH351X+JmvrjTj1orV@3xFrsp)m90SQEG|qwq4~M>$IJ+JC^ijHj z0L>}+1G4=btt?SU>CCGUbS%9@(6R(ZgAYZsj3a7#(UAeu@_mPffBaiJcfyH2`Ef$kh%?ox+s#m6HQ%N z@0#425O4b`)DJap1BWaE1Wm%z0F$y6e!wN5Lw?gmTO+dv>Vq z->03og{5$%nYT(L?#BY-!~Fal1pW>mY;zAQ`^ogb z2kh5(VDs*8f5YE4pB%2TyfVA94S=W8->{R5$=saQ%oyP`6d8e~1s#*^Pj4Igvjt-s zcp)zzW6m?(Av6$=g6}fp#IYOxg5A(I*#IglrZo0<&9;y^)@ZS-o-@_lk-Z-j=KcG; z`fp$KFJSYJ&=!)AcjZWL0-CYp#8185>YKp|fz*2wd#FsUY>nu6esaKCLrhfrjW1g2 zuHGY}Mq<{1a(XaebQ!hTdtBh}iy{@cei^)jNwRCOvAaP)#wu<}GBcHgbB&#Xy#L?g z`ljv-Tb<}cSZY8uPm5Q(tB$uZj+iA;`uN@H#Dlzt$mSE;kz&4==?BjV6v!ij?Fv@_ zRih;mB*!m4>594G@4a+<;ARKsoQfd)RYBm>T71ZrPLi#j$0JS>xCE1Rn8-;zyw^ca zZCVobLCf*qGUsk3rD!%!C8=4_)|t9C*oC~Ra~@w^E-F33kr?q|l6{UNMv@erwotth zAZn^$sMoQlf^Wsh~875rEO3mK_qEGDkN5czo);IeV{6v0X#W^*jX$s+! zYhj1mnG~UmM!M=oYIV}Mnf!&Ter;PK*C>7=%JTEdh^fTkwNzo1POk5SH?`QH9GQe) zuao^s!Z-T>e50hfjud0~5qr2)ZIYZqe2|u4iw0ioVhrIf2T3RO>!mw{+^QR9gb}72 zYFS(&JIXy{?eV-wgFMx#&=GI@)$-~*H+HsJXSo;c?Tcxz=QDlwHyD$kwB{{yXC+i| zX^v+>2~~o)#Q`Dqy?MAfW`A3w9ac3xA45FEH8F6)iL)Oezh6jGHSAY3>**NQgL069 zeh-qt1chfCmTb_K>^nT=$rQ~*1NY~JNx5bs`!M#D?EgGRrzDt|`9=1U5{Wj3%V@F` z&{&z2{q(Kv$L17hY^Bz(r;qch(7~AJVGc}0(=|R*)>oUcOE9W?eZ7h z|F@P)Sr;gHNNqV9wxc=EFV%6D)`BiR;CLN_8yrY(tUjOjW2f)u^D6587z8fA6{Cm7 z_8<&5a+Jw_uu~f^P>|bf!*47PwXJs%DNaXM`=kud^7FTxW#kFW_=opg4+uvH zp)A-eZIyyaEsp9uMVH%T2#^X4PGaFHmwiNjfI_cNYCGa}VSHN;{yhYjG{dQYwJsZz zipF7#LX=|CJ>(n;m{4VkTLez@*M#Qo3ncCF;u4?-$|IpkdR?!*mJaL^g`EeeQ$LjH z-+0@#b`ZU%702TZsqW68Dl?F1j3LZHKu^VWaSli0(=lr=C9f-I(vgYP_`liu(L{8{ z0t-d6-n)48g)HPGcws>MJsU(QQ+IP(eAmT+1b#8+(Rs*SH?_DbM`&HQeD6`3@2qDs z!2*P+%)ROP{k)UO+f|d7W?{n&%}F&%=VSAr1wMprL@T9rOro9Wbs->Iz2iv~a_{gF z^^-#zSFM~d+dao)B9WAj+rx`rSjwY@6>En>#mKkpBtNFteBK9_zf)D}3SIoi0-ei&{*VmMy^VtcylFqu0{us7 z^HrGCD`f0NgB!2JJx5{V-4s4)5Ok-lofy3(cAid#zb#Mx&*RQ-0LX9qXn!AV|Lrrq zbNIjICUu1IWi7|W6<7X3id%=QQ~b4aF}$|j+bxedLxxJYvC#yr5(n+s`GS=p#19K% zWk7u3QMHz8X2fU)Eq`uhu<*QK`*sTb*y`R`&q}yK^ZLVHeadJ9W(b(}RZF8QVd{>e@h#O&IL&C&cIrR z{8e)5={3Yu1;BcKKtGRc`?jAP%uNmSm1>oVh4Q#6X%Nnj5Tr~yk`Ch>U|ucR!2r8W zL_M8+HKcSTi8a|W{tErE@i70$S{TAlXI%*Z5yzI)K z4jv5VX2YkkIki-b-#g3y5#-u^L+xN$bK_nigxW!gU6g9io=h#JV;KOSfeOEp$@#v+ zB`J@t@(C`ZYrZ<_)&lI^Mue{l&Nf~H&f@^9fhtRLP6~j%Jc*wp=zkBcig&p3`zxdc z+WC({xtKJis3TS~fh&fm^DCEuo|V)@5f$_VEhsB+H?TLb7nNs|>tytx=v{%8^>ZOa zMSl|+mg|T~BbMnX;AZ}5qWdv;#!%)PfHPL0N^~k{NZ!Kn1h!om>jsI}+nw9ACRlCI{s?lfD3yx-rESON zNZmn9`=We8osE(s*HTtvM+c{>_R}s=I?&)P8sMJG-&S$Gyf!Oplp24I_E23uaJoyl zql?6s!)hp)L9o=yjQ$3{^XnRD%W=L%QEwDtk^I>Lxo!qgyz?g<#5(2H_JxoTyG$S= zftZXb-o03EX0=%5RYu>G)5wfd4{Iz_U#=IJE|4X(%}6iw8?3hJiCJBoMg7CN5x@W{&jUku_cZSlqcltoZ$9A4IggmVQI5~zF5ebdOei`5{^Q}Mj+7v;EE{t= zv&;^Nf&5Rn2J{lMke7062oC4&s)bZDVeecN3UkgxXCiz$D!)Zzzr%&ghOYbxE^0h$ zdn{_jn=+6d9c1c1t&-SWCz{bY;?3+8o#Uee;?(CTVbq0Br2pi0+}_L zdqHzeE`G4K4A52RX3YFUc6jA|&qj&Z0DMw>FBZTF1fXr!Zy@}C^Zj3NmDAl5Mu@_C zrQ}Uq>XY$0iT-%nY0g)nS!o*&#O(?;9f~+S_Lp3-+o58Be#J(a0Iee{Kg6|SvZ;EB zi%B5|h^IOVDv!WbN?DV^)ONa6kpO7n0BcA`i%!?6>GB|b_$Zqet+i|~tD7KwLjtr9 z5R#DQ*)N{e^)_@#Ph)x9;p>F3^Z&CHm}#ejDGdUy_j~MFECb1L0&0M? zb|cYu3SNqza#gPdN-H9&Z#Pog2BTjJ*sY)q;5s3V>U%yzQ9;~F)uEPO__LrUeSX9> zc89pSPmt_R!jHR-#V6jn{1RawGoshFGG1XJ+kOJ~N4J;_)PNtVC46%a!Y+SaUyBZ% zog?Jp6$gN>c$ky8Ep+I*~G^nxIraj7s72?>v;epMDc- zG;JAyP>0o&Ro5JDKo3d%3-}{W4V!Xwg;wp>dV$~-*jRSo^IvddQK|HqEhAT91xbWE zK)K0XJ;D}EnUSpP-k+2^LBvnm%~Qq^;|E)X+TIpUn4rZr*y5}58X|s|`kKXz3}W>Z z&PDSNH~o+AFFfj%M+BkS z7fe_rog@EA5YAjqvk4mWMPI?#|2|ehnrO4TycIE z$ExK{uubSC_q6WDXnRH^%c=OI0*DaDCKTg_u_~YBzc0Q1?KAzQHi;A&_#pVW)iG|R zMNmqu62BQn3OY#6+bK4)10SW+fiXO2Pz0fPd{EP6J z?(92SCq(?cWmqXOvTnJ~*Z#TB`&Sblhyc7jV$Mu7Z4=4W(M=s9WHM$f(@%u- zt~Xup9d(%W2kf%6ON8ah5M}`1?=`oRx`a!+ho+P+&tV3d^- z;UuO}tM7}}CMH6D_~FAu!s^7t>R8~PbO~?a=^D>uW$xz~c|m3CGb<$+_03YCW$P7{ z^rC(R4pZ?c;j3qmx0j`CTET_Se)a9+1MY1PYGAh$#CwDa3Eyq4amA+|=b0x$2vvgp z-=$Yk7SkV1eG2Y|xEMt+`7A3`r-bO#^%bFkVbVU#B0PKH%fm1_K0NYtbEU(z^$xh(EO(7 zJ;<5^^)4cvC+LcwL`1amvR?#p29yj_fo5heAjXst82nk@HgC!{6R51H?(@>o|DK4D zy^BadC(vDfeTg65W2=A~PmTGgfv-yY%Ui;}^uo6?+tta`l;NP`Zunnk>#%gU3$y57 z>V$vp!JOZdPzW07pS;4VvG^+ZcWF=HEY{6c3AmmiA-`6VsY9q|;K)i*pN?Yxed+aY zzJC{y|Gln>^`kY5?G-Iajbin-28wfI(k3#f^I!Aa#itpQ8wsddg~!~M{6oKt(L75i z5sO!cX3}w&gn_kt`ppcX-yH8@+DNw~H&XJbQ~DRvUI(r6J{h(m^@*MjS+2KZgG+bk z`+1-$nJq`{Si4ZNVD33_Imq^xN|%9MQFQj>M#pQ4bzHz>*sTyjoBi32jF^or6)RS_^(hR$__o!C`mi`=Mj8^+v3!jxe@04hxI^_J;V=RhfRDM<4eT5vz{EqfE)BrWX;*cot)Vfw6rI zMw2$%c>jWxva<1~qLAEdJ1_f~V3qj{yq-K)X#mG7SEkNf*%tIW`Th>vsz6S6z|-#R zeeXBxLemOHKWAeT-R$U?<1Xqh2>c?Dt-4%q)?~(nT&s`sfU3;mROTe+QaIm23Om1q zxf2vBq>o&zD{?W(40U18dypf3fio`rT17p z7l>nhq6&+&a{3(D&C*N9?2vV$Izp(h*gY5p#s-pIDFmfY0`Z;0m>G11Prs;nd#Yk{ zGXvuI|EN2s@I1F@ZO69Vn2pmUjcwaTW2dnj+qP}nZfvV@8aw^J?tia!W$lw5_k6r3 z+wK8e;4}KaY*>|n?nx}mMR0$dmUK* zwHbtNsfSev9p`#Ze$Y%MT^+)4X@Q$rz%l-iQ^f$cBi0Vv9K@=jKhlDL)>Yv zP^5~IDPaD=c{KW?tM;YP+(OWymmA*Cxx`8p$58}c-hWN6KmDeEig{21Q$p_&9>?65 z29FmpNPVd5{Gh({&HIt~dZ|P%=McYhdM__$4)yS#!N3OMY(GFxHju}HPK)Pn`|9Y^ zGaiZHeyph+d#ZS=ehFr5L)baK-0uY&y0ycG!DY-(azVi`pjW+9j5xWXQTW z5VJ#Ai781S4kS(r)0*DbG^Y%VY@&X2xCd!79sBzJ=x!`8`o;xJ`!_S21KF536fy?# z=Pp}U#Q}o$+h8$rQ?J?I9IEi8Q~YA6YhSzdSIxXzDB47VJQ}#SFkp=X)*EQ7WBh$# z@x3qQQQcq_1TQKgw(gZx>J|?}C}Cq%X4RMy=85F5gn8ZzfJ;9c>;2l=#zSRHgD@hw z{K(}jU>|0?5w^6brIrq@Dr2%xU!!~NuZC*^09QcinD%x{YJ2a)bL7)x{u`~+dnlFgn~o?T*o$RU9bVTsPe88lWB zKyAD2=O14xGGmhYU!V9A(bi>J5>0{GYaJfmxNnYARiAA1>7{yZt9KSOmIj-L`L;DR zs`0N{LT%jY*az?|aH{E*TOqgAK0U)NlKwK5=FWcEy|!G$Z02<9+%>%5_2Ndswl}}) zxWIUj?iFUnV+oB$!6i!9P|XGArV^(;stYLX#@ebQK*}*sr&&h0*f6{q+G0iYcBA;w z>78={`5c(?8!pFl0<`KRK>@h$0fnV79w8W}_`}$9cBhYb_Ojciq2m7?mfejJs{d79 zE}ydjF66!fREulyJJ4DSavNF6Sd|$W+dTj+mLM#-cf53Q$9lT(@hcZ=7;G%VcE{z7 ziafOI`Xc0UN}!jfE$zJv{rl=xHUO<+oQ;0bDIE(hcSXNvp~**1!#1;P)Gyi({+QVj zx<)dLenBD0b8xFKI5LnXD>KnZiKQrBFV51O{8mwmki7fR)kKtJ8p+@l(^p2PUFaMi zHPX3~&}8;f6pc^TcOixTty_P}{Xb|`j*Z=i8yVOe`6Ah&ZsqkM9!6t%i3}_#XWpC| zWq`-GJiK6_;-QLKz>lic@!{JeGG^FfUOVQD@U2cVN7vRy*1#Vr1)|?OyCgbnC=zlF zaQoDpdrU(ynJg!6@WRvp(8~P<6yB}BMV?}mR55>usqJHHT|Tb z=-D52rW+5LOZ;$}BjAqwg%Pt=n*9+5a=on8t$*i%`ol+SUTq*c?m=K{%!GdPqn}OR z?hrTtb<2dkXGb5cDxN@OK*dl?NeHcIFv);7sQ^B;Bms+TTZl3r;*{mwLS{$&RoG9e z0;)~dEEcG@p;NP9*~$Hu2$l$>cejrZat$()6z45Dzlk9c&cUxIC9}r*O$%`|{x@3R zo)i)fqM!V>*J2lEBoh=PHBQrHg*4q;AUuUlm|ul|Hza&tw}g3G@A3j`k%6Y>6E5f_ zhBUp_O;_|3c|+}*2J60lk_W&AX^r*%u2NVU*Jo^jI>tVFqef(=nLQq~H^I z3N`#A3Wv!NRnrTpg#61SBxGu=SxbF&eC$Vs5?}veP`Zy0e?;p2opl6sw#g_ltGT`+}+skY&}Vx!#?n>q)H^{vTDiVGFyI zB>3BE(NY9pw9EWqyQD)rA1pED!W*gsIN8<@qfgZAP8AlY{VMORcUnh#@;s?T$Ld&g zjILq7u5zvXpvtX_(5=kl;TJFEoJ9|$!?Dq*aZbd>o7A$4@gL}as$hC)l+uM53L`D| ztb%RjfZM1^$(I%H5s-u8Fqb8S1hqH-qP6z=RrDzxjN^P!1$}&NK>-00!m{jHYcOo+ zhLWKb_))erf+9`+B@?=B5~3;2HJAKg$Sfq!Rv`TsV`O^FBaN+f_ChHmz=Rmzz}U=MnogHtvdI4E!EH~@cH}Xkv?;y4 zrbq=T>K+^HsA3EnLWy_$T8t8zvrH&NCebex$!zL_`205_~<&p+T}Fe_fZ0T0$1!P8;@3cs3J8yzfv?LZb)HN_07+0*J>j}*)iExBW zEOqW5Y(ZmE0MOguXvk4jegP9uY#X)T^Uks;3Q1GSP$3x*uSiD*3t z&rFk#e{}$!0SYlIgKKi^1o`s$^^AmMmChHH*|H@+WjRIhE}(|nA9w7oh=~I^4)83I zCEdb%rd6tBQbOf2E_pXyODDN-X!kGh9~tR84%-!RH&B*%?xJ)QR!sEZCD~oDi5F!>2I639bEv>U*n6G8aaFZ)l8o`bk}C2oZa`W$xus+ z@l6F3Y^47#^9>w~2}Q0YrShu@-OZ1O0%m)u%McnV=Tbhk%k|+^rSn;OIdV>1qUg~Ubl^5PFRXSRCp@)uFtt?L)@B4s3F5Rt;VP8G1@EJShOjrH4@0Gi_Ycz>&6p z@T?K>SQdBmdBgqOPknHP<{RE=`~yx^0Zb|sWBa-1XLZ2_R}&tbE4~*0ioyqzoP_9d z+p*1dP6#E~&d6_>R~c6}>fCSsst}+t1Cl`|r?-AD#Smssz{btRgz9F;YLch?v8@zg z*dC>CU13TIeEtQp zTgaws?9S1T?%AEXUAvbOgjCWiKZVdwfx{zcJTpM|(UN!9rVRK3c85vA(+6y}MVL6L zxFE6$!iGGGkw|MxPV3878V6m)aeU{v;`#pMnvS?yG}f(~f3#se<)X51L?+WxDIT`i4kLSADQ@+ zUe~o?L~+-UoS95M;i(`Pz@ZNbmejj10-e?$y*#7YB(Te-WypAJz5+uSePq%OKwV^Y zZMKHGe;4}KarogBz+vbjP24pZsaK+(tMW$;59AIZh5EFNB#^C7A$H?Mj=NLVH)g*O zqr_Eow&M$5CvPx2mp^KtNb*{*h7^#s1n{( zq?roL0Hcg`+4ApV9#BFg@@N$lmKd>{xj2lICZ2qbI0ALWzn7rEc)%Ij)7?*MfMokd z(yr8Wj_jZ=7QueK@4QwzX(kkn4s*=NzIRt5aDgKgfPoJ;^tcdwe}!c_?#H?)%z1Fv z{B#jA3+56mZovJ_<{|%)KF-UHktL?F5z&J{-(;J@J&|tH6L$(IfatEXJ2GY3p>5}F z)&J~mq;|&OrQ5yRk_!pAVW!swb9idM?yIv6KKK^YRT{BOqiGfg(2XH&Kf%WoU7vYA zUKA)U8}qqJ`A6ms9A@P0{)!ok-q_Khv*e_6^&yWdK3G>9w}3poQ-eFC_NeJwp7c?` z_B37i-gm#f*+p$GvHS?n9rk47lf2Q~#cjpP)1X zvn2(4RS0S&VPkowi5%B6}Q(OP;$kAJL@8v$%*~p zEKelUMZ-uDh!;#R%icvRH)3xXhLq-C$L>$L2S~{OT(7R6WTlTiPrUoiT4K0aKrP#P zF$@@xsYtVj#!pv%Dy4dV-ww3{Kl~=)8iRV9EsG5Pnb0Ee;aDPm{#Fn-Hww5nF3|TC zd}Pg)1%6~(UM(vh!qrSJd^NO+l>=-n{RL2@y2DwRd5rZy32_#d#i*X6B= zeqr5Pz}s0|8}{n0tJkZ>=hr|i5#fFcAu1ha0Dtpx6X1I(7HRNn=vFVM2ZaF2q#8wJ z_SED;dnmz)SXh)iEWpbKOgGW_S_+GADHki?52LE53YO&yonaWxJn~WpvdZixrRt#h z;%lNw3WUV`G3@{-G~o6goi7ACM8fkfE_D_bG=i|wR2qn(-RW&y{yLoo$OBOs3{B^XsKM$XWQQ4mCUI0q zA%~Q74G|SgewT6@JJUJTn6Fz`c2evtpg;$BgwLB@(B`yOOp7GFjpc^_ce9z^@tmM&vxsv6%PC;xqL#RA}}d8)72GCu7(gBOYN!1SlV_NEg~IU$e|rM0o( z8<5?j2?r6OJl(`RHR;;~YeBHXoa5Aj+QOKqto(9>Y6=}V=tzEDIEH+}d5`|&NGzz} z;8Xp0aXLj!5%Wj09GBLU#~@HVzl1BRvqdrH$BkFn&#A=$Y#`Q3dnMRtxLucn+z$q0|& z7O!%Br(#eNN;`;XRWNx>4Y;Is6DO$Bnsi8gFJ}Zi!qR>2m?^(JY~VWlC(bU+d@Y4q zNp=$zsGibP&`-O7)qU0?txp(Qy0*7f+xK70*5y?b)sL2a&K|Adl?0Y~5ju9jFCucj zSSMb~?w{#Dj=11jP8M2vX65#xGkK(PdV|?xN(Yv59X*cSziEBSy zW4E;5x4J=sV|iz41VD%_lL+cDm&IHQS>Bk1GUz?eUE*LKqhb2RUVY@l9e-M{`3=`< z0G_lYWLYWA{S)0|LqWmfG$&mu*f(V$#gfXJQcG6A_3HoF;SpU_yHw%aQ0|6ty{Y_y52Z@-Y?9E$X!!Gq*xl3ykBl5d*8GIje8T=b1?b*>Ls?k53?< zqWOp1J!iEfWr?q>F{aj!>W)17)4?*3iB9}F3_dFq@Bn$)Z(^~J^0XBgg;gvBv93NtN|Wo(C@GANv~=k`FbsaBaU|g1;B0K~`xzf{ z5wQf8<%P!4(voM>$IWvQu?7O+V_DCmPqeXw&WO&erchsf*1g)FVcdi2qDK)Q!*(_{ z)S;6K`ojZJ?e48+vMtB3){JZDcsPoXS#)JFuhMC&^u=)J7E|JF=m*87e=08>sB#`_ z?Mm7x3awJJ?IJ|V3@W8~k!{+@_ESvbaf_&ck=u+zW&|mj?zEa-H2IEfgI+FF)DyAb zM7*TZmvu>0k_saKN-43$(Iw;nCOUe#tB&c^C^uXtIvU;NjKy#n32yq}`qNsp)cjO| zgV((V&O~sy%7K0Zo$|T`V)-%sht#<5G@9Piz>y0rKR1D{@y$nh!M!?!5(+U^VQh6n zMSf8bEGaWN2iysNBWSqz=&tIP3vPMvmDX#M>y%idvqGUvJz`??+u+dnqt4QB*vD$E zLf!VBEXgKm4{OXWf`Wh$v~K(K_QV~VJxBISt;w9e41gVOgTm(HcnxSGnUHnBNxT&% zo5{k3_Qh<_tS=tc=M;niS#^EI7bV;p`%+|zu&o=ul@gik#mF4U4SW9v(Y29q{4sk| z|LsHE%V)Q*f~{vj+mmx2WOGD}?U)q;l4c}+FMe@EtnE>}Sp?i`#FJUw;MZ&R@<-j= zy`Hb1gWL$6AL0LZ@JyKX$lH z!_TZvgxb2`g->K8JUVR~=!2QIcd=}QwPM%S98}f-5g97L5__i%?oKtkC{vo>wH$)P z4N)2Qr65CEXz{Cx9|H&_j#@7p--Z5tBEk+3k(|b*%L_a{**=S&vPVhugZx{e|CIZGL?k|oHP#;bn1*)7!se4`umrw7DHi?t z17B9X(&rlLuH2cNKnS6?p>67)+onYQmcV1;Vti=jbO* zf#ik_6K)hE1JKBdN%u2VO%_Q_w1x7P(SS41ao zgP%jF$TJ93qINRLRbYrX_I7FH2h|AD&$hRXnRMTnvbHs-Vd(S)W7gf^E>7`vJ55Qx z4==YEVsaGk_fzeD`^8BigN!I4v;R1)Z~E$$cfXDlAfxjWR{rATLs3Z&$V7=!@pxD_ z7t@DsoA}tNxiGWu=_w6g`h&_%KVDOOAiWS!pPdQv3^?1XJ=GM7#2wYKt<`>^q!H#h z**wJGEg1$At$k6`%d^UglhI&3v)tu31M@$p=mc^ER<8Gtg&hC17ZzYC9$V!1K>xay zhru^|Eab3N0Yv@fQXpF-&%r?PxS8Y=j!qmKzXJNRO3%hx-JD7^1PXyO4HyXrv-EJ6 z$=o`J)b9$t!9qxqJg9Xd)20=#RyKgw@wMirwh;;6a{g!E616V#|9wKQ3S&=3NzsPN zE)Bhb%pfPVrTE$Q;j1QE*0izSfcNUxwtbR@(FiG1EmyxYQ3rJfU%L6 zQ6eupg4;n5unH|{c^CTk!37I|s{*NlV!?rJZ5WZGy4cMJBXDF%l&^RQSRLMT==;DT z1(3LY8bOr3J#ss6yh43Y6AY?|Q)L#bp*#H5JR9iUn@QF&jX{o&YASSDlt86Km?cL7 z`lsDPGz)oYSd7qcmVa&HKjr=(xSEo3ZnM|IOIKV_5{`RfWTo z1leX;ECa}-$+x|7bzXN8Q?N|EIF+Vtn0l8ztbE3|S7@(j3gW-T11(OFl-*30tM9ji zLPBwSm!z5Af^2YJ*!gK4%dgi_HrJrh7NOX4Nb)n#g19*D zRaLu%Q%Vc1?#SJ?rpL)lIEO5{fz5@o+oQPBscYhcL5u!vq`{*TnxQBe`uxw<{Rk9nmDlar$h zurqyl(Z4#n8V}`sY9+)*E5z5Uq+96kMN*D$s(o)4909^otne8p4br9IwVd?(#!vwT z;B{g1Gw1oIWdtQvVmIn};EoKL%u+l@VY}km_IgnW9}p&u+5{aTJ*x4G7!zEC>M{^Q zISrZbFcN8|xr&Pf!mY!D3pHJU~{&gG@YydcnRP)3f zCVbT5KfH?9hHHF@Or8s!#tSJzmlq5vsWlfZQOfH+YekS0a&V`+EPeikYVAmk2rQl! zoamC5t{I@R6dbc$XJ$bRt*HbNq0=bpa@ns9Tw62?}f)d{U!j1|I^CC z|MO37C98Nx2FC1k3(T>q1w^!V>EaxQY`(^?Xf?U5$E7yt>rPN0_Q9DMa=B3=*vV%& z1pIkLbRq}%IRV<_Y-*aUW0*`_)0o{59;tIqJz1o8-t~P2M$swu#Me2By*cK@Z#NSkD%0>Td4f8COzw`9=?gwd7Q*K^F8Fdff9R zy{1ZsloRjC*f^;%f|Llp6$Y$0^-Rn+E8_gkFZ>kXvU)#36nbzD`@Tjz1bwptl3Q+Y zBv(8ho!aC{DZR_yuQ(-GmP`Ys)F#o$=7%R4Lja~uvuaIh)&*4^^tq%UW|D#TxkXIy zfcvPepEIDR+NV3+Jlh+zK=}M!VyvIN>oo>mrI-N6h zUyZ+&V-rI8?;BrF7JY`FWVgL1!|KE;B}TCL%0Z_Q*j%_=m9|_?B>RB7#Bf}ESiyisL3E7BY40`Hj^2(V9NGLS~E zH^f_5liIb%iczZEJ}}Zz#>n#L5n91DFA&EFB-x3|@qgEkf6DzoB`yr2L*08A2v{b$ z860aN-u)+^hu~Zs<;y8S7-WHiTR-Y{%Gq-?7?32eib1fz+BvFB)q_DAzCl@SftB|i z{1tcV-3NkWjB%$E;2CP<8yRSCE$Jo3qE^e#{nu_^#su@eI~B8#+0%Pt8K8}(nB z(g;U{XlN*^Dv)7on(`K6E9uS`%Ck;#k|jQuRGuu@MIwn&q8wLl%@$u5bBuwG7b zw8J=L6w(}jH=s&~=7I)`ag%~U#Z;A`zAO}XFzie@SF z5Me%p*wyBGx(`W4r4y_QuxOGnV0dahE!zc7&&mN2w%XEd=8dvE+fL$U&dLc@E;O(1|$3T*M>Rirrr;0b>VE ziEyk~ziAxml6AAemW#OlMoTdi*cjJSJnADgzUlICdwF^Xp)`F4x`$<+vdiLTEyn-7 zs9(FP``LWz(|PZkKZabq3WY#>rA<-YqXes?eA_Xy>ni{*L<%gScf^$SxI4zjc0*X| zosSN>ZsvUb&`P-7>xp7ud1jwN1IP0&^zVZ!0037@bOVU~k~^w4Fk$2((hqy>5I9MvfYw z0whLQa{5yjIfiI1NNURZUvF`bec+e=b$I@i`+wl_Yd+)vanweH{6RP9)H%MPMLIrN zd#7v>kvNb(dh7x&%k9;h@EyK=%qxl{c34jisa+%r>iko}Gyjl=?2!~Hr5riL9 zha)b}GUOIftO^cob% z+u2)@YS}nz=^p5`H@v*~L4rU;^dMk1*v*w&I5NUf*`!pp0%( zR(eQRH#yJm+r^DV=6Z>n*s;2Q-fvFtpX8$Ou>KZerV@+XNDiLvZa(!$*3!DySio(z z7rCAplGS5Ml`lZ|OBNL*f4jCWL#Y)C(2vnysi}n_ zo}j=B=Hk^lH$OsvNjGB(_q>v_Hu*CjlE3<|7N1oT^O-4?-gRVTa}Q^e!fe4Kzyo^! zn!DL7qio(sp&JAfBe5<$d|z&@IO+K&;Aya0GfJ;lOj9`7h2FLCut2yrM>EW4Kb*S^ zBIi+~tF3JkC9)4s$)H9)PRw70zp1GJO?L1YSh1yM)N#a~{_0Ld@EZ8-@Bo8Xi)Lzo ziMmqm1;nbANO2n))Q4-ns>!6S98kGXK>Y9V=2q-W28VJ{Vfs8)sygx_s!-Vqgxa7@ zdAEX&XK}PlYTYqKYuDxw`(t&bop7PKcqK4wBdusaA? z@0*F+aZ)Si1T>Hv9}nzlhM{Xpu*Ut=0V8-J7og)C!l)?zt3^Z=AR>k1)b>$)GR>Ln zFrFza-|_Ok%wsfjN4isufaC%bUCFGy1aiuLhb)ujpbwbXRuO`CVg%-bHa7YC!VUxu z3sQoDXBwzMZK`O=V%Fn9Quy^jFsenNHK5uy;Rko`3JcS}o6tYy9v~wB^Q5($D!-}Y z#a~jSkLtF{M>KyToZsRi1+}iKYw84Rt2BkF!;Blf-}KBIvu6oc2I35LyxAP*(FZc1p@+l{NVX?7jQY>?sY z0ckjP4oLS>BrGlWEyun!)hha19c*^~@J=(mK^}+ZIR~LD#CY1^8EPmYFv8PaH!61i zd|JDjAFr3HgcSj;%X&Ya*~h3z=7{`~ay7ktu3$pYOIP*Rjmc|yU@R{m{S8dOx!ZFEO$gqk*`b+aR9TJvVQoXqWZExdmQrB>jMuN zJ7|D!OsUwTjZ5)V(<~jPHTlNrFu) zsT9i1bE2iR%)^4i^uH_RKmDeEig}|%KPM2U&%(q{jtOoeedp}_+ex_qjvZ9_+&a$^ z?`0PCA;7}7M0V7u(QCpneHSKs_LJv@gZ2 z9h?&N36}iE6ZQ~*Uck?6?H=lmwzu7|2tw3!;G|_wf2-_D2*K$!&rq=|hHn;A>G>WJE z{?eTbo_~wnpK||Ckt>X%YpOd2hl*E`;hXk5;em8({gms^M|q|p;qZYUj5eQl`1MZ6 zVxZ1i<&fU5zZr`73x^CxfDSg3k)uxi*a@jzaXjh34oezIE5@$Q)e5Wn@_>tC8NZI| z*B|;;0zLq^f^+w{!BO0XgX~=S>~Lv>L19g_OoPf z3;UuUQVH|sVo;P>{K7J5O%oar+z!{vHEpQ}UPl>koYel^o5 znDtCRP;+-1+o?E*sIPNNY&*j&C>&ZhX)T)oBfJYgcx_pzZ}h+}&KGkQz*N-OLd6cz zd$%N8u&pd7QVSG>$#dYlJaR)c-E8fuK9|MyrMqvE`xZx}mX~Rw9htQ7eP|hD(ZyYTd->gvzsT zR#(npKI6rrvr-MtLcGV_8roWfgZejI?=RZm!ym`xKlSS=OWxc~UYO(T4BwCn7{sI} zb|*|rJYBzU0nGfJ+t&+-L~+fKPNrs3;wvgH^{?uIIRuGWH*OoY-p>FIRZ6h<-obT< zcIP8pzPGK!D2H|BzUeFGTZPn4pf7&T(%NbV)b+l_!{5i@6oA8IG;Pn&Pr$Erf$^4{ z;Sj%`;CR_m5NC`mzKF$0I7dyM4)4Hi_`~}32$sULI4P5Qk*8o5c85;4KHPpQy7)fUnKjII>8erB?bmsN z#1*;EyW!d~l&pCEh*!hLedDgY4x?*?yg3@=+#3OV(7t40iMnL8T#^ir4jLOyX~AK! z+AZtE;<bF=*h6JS&;!#?~)O zn@>kc<{~4U2b*w<2T+(bu@;9h0j^-sHKz9cbVAvSL)+hy{ z2W?Ky6sz@eoLmIT%C$TORF;C1)Hhkc#`^5M{djfexnqwJp4>>kXEpZ^r z8Wu%l;OAnKMlaQQZ$sFS8T^R^7CX|hYk|00jR!gwXbq9G;jKJ5y<=^;H{y$*Jf`MB z=#Sn~eJ8H{zHg%in;J+)4zS02jhyBC`q_I3JXWv?m3Rvq2t|`b@nojujd61-5tbYs zA{`~qI;Y*L=@rWbw>qGUs^*n)$`0m+m3;hK5!;!!T96o08g7c%Ye-rx)Q-xyqem=( zo=4ue5DZph$8Er-C2J(o?^`mBsJ4wgCEUhsY5PR_&B+PIYaOb1#no`vy*b~p@R=Cm za_RSuH8;@=lFw`B<%}_&5@cJVzoHwQC|XUsdJps^7jvf?=6~MSIJRRx($>xxnlo`W4F%I;aC{EeAbR zAQUpwDr3CazuD#-sJP*$wKa*{oD{}!`&0Enq_VOiD4k1orjo0?MwS0oY2)8j@}F}5 zkAOtWDzRLQAu1h<%E(~k0ufWV^L$|t!SJyH8nWD*T9h*Z-50{(OkWCaj^PvI2Li14z$s`{dVVf0bolA5o zyco5aO{xN`)NQ z>2UwX`=I}8dI*Zszf#viyu4*u#BSu?7twisIT8jBas?Wf&AKAkLR9BaxT#2O;8&;k z6)E|Y(dH2BH{a6u8fs$6AbQ$B@jQ&?XYO?~HVwUJ4m!Y{AW5_~g$1H*vzbsk)`>G; z*BR8;s31WH8X*<=e@{Nz`jPObu>K|om=CjWvi z&Q&Gr1)gNfzSbUKTFV&Vu4m_`b$`n+qzcA2kjxnw5Dz`yhE+?lK*d7tWRysQ&^yU- zUXkA(?)&v-k__KqWmBpk#$_$*3L|S6#e&v@>`d6Xib70O6I=YdIu|h@7;vuOIk@%0c?47>`Hv zq=D-__ag>IJ5Oiew6c92?A{MGm(}Lq?CSz$A#f3$%UC{OB3hWNiVz96Q{>zTZOPD| zuq5)Fyv4W;)r4G&D-dm5r=3OoWcroVbwHDaf0%`8L#KqV0%|@C=<+u-WbT(P0iV}RG1UhF8b|>ODXK8D3>hK!dDrRqy~De;up!R zG#@OCn-f;n?2SS-y((aBa(boDH=wu97nvKFIG-uqy-@WYk;bg3e(g?9^QXYf+&xNG zBj%agf#R2Zuf_z|M5PA0`>rIOxFz`(1vhJq@$9|kewu5`Mn&1zvv;ZF!B*%}$32S! zE9AM<+4Z|RhXev`MA&}f*KG=?d%mCAYz<=gn&#nev5)$zSJT^H9~p}5pE1B-0J}>T3bM>YM?U{JQgaEcA0hg`Ez{lSs!>WDWY>>su?b~uFss400FVdN#@7xQ-ZB;GN6 z7y9>!h&Vt*;-*HbH2e6bWv#{eApHjSHC7b1E6bZaZP^STb|wSoL>dY{<|xvNBJ>FN zriQ<5z+U)(0ShQTXxOBoZ!4PZQyO04-UW>PX@BYM_FcS-cW`FkB4ol>oJJ@?ez z|0^PY%Kbkg5+S2HBIXhK-1F7ws~>w4*F)I;EBol)Wlwkz2J4j5IZQZmQNg(WJxDJp zRFwKw0y1yE`mEe9WqW__OC}8I-3H!$f_$yzX$Bqi5haJ>rn?(5(}y2zHDk8!9|^-^ zp?-@WPw;iuJc3Z+>s?fuwE*%E=aYknovB22EEG%Kuyc~RzB(;G#rE<%LlSXM)?5kcn zJ;edbZ!y(N5Fhxi4mV!$6dTx}5dB^EJ?R$(j$MpUQ8{b$)Sz2UK2Syz<)CPrRx#-& zw3Ed%ePcC}ESKzQz@p{<$js0|DgAlm<_?2|Us9?sdO||4HBLh4Yguhj`(QscT!5a4 z}ZxA+9$;i8Zq4VSuUK*osch3_aLaY z4JBk$^qkCcAG#-l!05Bd&TI6%*RI{vWI`8lOd5i{u)*>1gYLxfR9UwmJQDgEl+kPA zw-Q_=sG#e~l2iSDoiP^S;6J0m2X3V`iU>I$$c5Lq&Z6=j)za*L`GI`6QA@#W2ZrFI zz_zxmF`lWls1CuAk8N!rF(`A{Zc|h2f(>}QYsP!b?z;Is$v9tZ&sc`1w+$?xC%Y;d zq-r?q68vF3JLf^#V@Z1SMWsdGPO7g0ZcXuO{=}G5! z+71smZTkJ@Zt2Gu)1Z_uUh$WRbhK)G(QMe*C+#o$0qDqIu(mQ#2>Zo zeVWrlg9B_Km021WJ*~vVjYxsi)YOJ>T8GV~Cwn8KWw1cp5wMdFRn_GZNe)Fq9E9@Y z3}U*&%!ricnDG)k(#$?0`V-Chjswv7|M~=f%Kbkg5)7DYmZNk=TTdrz)_{+;nu-~I zsES3)+sGJEeMlD0PA~Cf>z_3i4}~fY0#?lE4@VE%eg=C_##jN0#zum?8-&zq|0Qp= zETnJlt;1uEDyfWY2Pw{v@5f6G1g9_*$!`%!Wne2A)^G!uE*%xM`ZZU5T<`!sdb!zw9FJVdB@p1>5dHX1ms)ASO}oIJ!bP z@YbO|{YEJx1cH)Qe^j`s2JKfHVBrXdun79x@(;x`E88;ila`&yhd6CYAB4zN;=S%yZThGn_V^BnoMMp};f zX-=&MUenuqHHNgX$}4(Hw)2WPkj3_R*f_K_In_q;AZan}#EMfVOXmoU`@gC3G2 zh_3gv(EEjaF4dJEYNPQJIii>`z`|2Jd>GpFJ8q`sN7;T(f7us$yHV568BU$YfPG4- z1KB!0)-sr=+U_Eq@v5DX_V}klHiK={hsW$I-q9JcMV{B^N;%BUU6kBV7@a2Uj%I_i zYY0OZND`t%7H(()v^TvF?1h!EVxG4yVcGBao~-A)`o@}jhDtG0czv4S6RC zMM0pJqyFCZX+{O<-E)}ecHb0V#5dp88V2gag)P&Y0eWMHg2nmn3#Pc#^}e)D^h8bN zO&Z~e^!oOEUE`pfB^OAy204`snu^m(ki}6sEJM_E3=)MJV z^e~LBxa=+N{iFL&fs!qhFv8RwAD@-}wH5yKn*e(AKZoGKG%qDgt?aPb>=d#c{#P2` zyu%vo9?h?~uX}m@XWTOJ!Ny9JoRF0)U=RG{U)}kFULlSu-Fg8GeS?Chv z0fV>j161ZVRg!ON)HUGDK~bqDbqb1=94#1EL*aV@NbzSO{_M#bvxQszoo#Dp^U~V6 z!fNqErY4BtR!5Gu$df04tpKJlvl5FLwPmY8_5y0Sml2MC%#1(_-sBG>jgGyM5xg2_ zvfAdOw>sdec--?S1o9!EHB<9>B^nzYvCemMrqJ%luj46!R|fB_d888usGydvL5izh zY_tq+$anjv+HYII?nfH?VxqRrIcu&Q0)E4W$#k9voz}9zxB+?s?m-PNHrRhXJ5F=Q z#lhW6+%bD~Gw5);6rI$A+lt-Lng2)KImPF-Z4W!PZJUi6v$3tlb{gBZokopq+cp}z zaT*)n+w=eS{^gvTeZB9;do$PjJY%e}<{We0i>LCF8QL8HF8)m{t`EdO)io@@a8K~U zqCJbrDgFNZ6740BM@`rBS-vVIQ)7zcL+HN`uHHXzwZOwRSoVA5j9+^ezWi!=gT>q~ z-KB{|iB$0NT|+DVwXS82!r^4O+h_uCL>Ep_Ccqkrl}+IZbdo{@g9 z+9g%^{v0Ve+{XjdcZbVC`C_>E^~uEIZ@B(x?f**Vl}3xGqEw$nflq6s^mE&)>Si8| zPbY&b63?v4SQL=3xABP0^R^}(>_#U|OmaFoq3MvSZJPvtTE6#&yjch#w;y738{S;i zdS3WYeiiX>!Ehhzhv^5*JC_h5O%6QgO3XpJHmuD4R>X6A zOu^S97@tZ4xX*Q14y^wLw&3%3eH7its*D&bR%F%bEPjm!)`f0KUzpwAy$7o^De|wPjdsp_ zXYF~%N`K%AbuC!r+O5|l3tYtYnT+hOQVtG4uQ$(C!mBFr&QRt3-%5EL#JPNQvvD4g zh3v-jHvzFQhHu6F&<2FZbb3XVUq~GQE|ftm&JV;a*Mx|)KT|=*?U_K??P||Fl>h!| zAfI4$BW<{L;{EN{htPi?TuA`90x&eoCo~n&u0lrJXUMhQL+FpCCh<<`PSLO2xY+gY zDzH#XeVxK~e!Vp{O0tMBLhMP5m!R>Zc61gvugHTtuOCO~a*VCshh#aFfDfPgh9IC|yociq(8}dzu~t7LibD zneeQanaI2*JDNyn+iZpoCu{%$`h9TS`&wP1HU{$~fE3J~c+XY}oVIs3XV*6+0U3(M zzR5IEb#(r8!3!&lQcqz;C4wAOX|1$9+{L2$_D;WR?{Gq(*`2tbmfWxGz%hq!S{tpF zA}p1U#*DZe8=9(@H9z^ZXWIPY+0$^Jh@DVlN9&ZM*2`-cm@1#A<=O74@uq@0z(TEr z6-sUu&Ck6x2t6?wk{Ot-OYDRcE4=TxpE6%mS4egj{~(C2WLKwyv1O2rq>DWHvw5YV&*BKAnY zt=KYrcgdiuY*TUt96a=nE~{=KLR$4oxo5E79lIt~;JKNtUOpil&&Tb^i!S%XiblDGcH$J*DZq&6r!VuhP;m(lufsnpkQeTL@4C?Xy*Bz?Jm?roPYP!uJ6>zQMk}E=FOi<`6yFs&?fm^5eh@ksxBpE zEH&uuL1k5ajRK9)1$d-a3vdYPPozd^@9R5V86NYayI z?Joz|rUo4Ffpf1{YJ_9R(^&L2E*%2fa<~I43SssVEXw0slUs}QW1kP92HaxbnHI5A zTRr;TX+#_*zTyc4i#BZ=tifAvaI)q_eh59q#VSxb^9{A`D52AxT{-8n8;S?|#E%zz zjWPQUn}{V01ifE@#qr@6Cz4|sJrh59VoM#|j)@Q~k#}+s=X-+-_}c{Y5lNa(K7{`J z)MN%wQ}bA5;Z?(F5P`oU(TFOz9UH%2GsLo>f!9SO($1s8WoHMHya`h}8a3YF&kg%` zMv!$_Vj~y=tKDlnUN8j)+F$zolxy9(tdJITU%SBF1Or0bgJr7&k!*Ph1rUI|cK_}K z{?ilvOHHYb`I)gQxR?E- zrn*{H+x)jO8-7F?qdJB+i&~Fu!o4rHc5KhcVF?{QmKD|}U`?B=%SY7R1K{4smN`4% z`kE%j6&X}esyiaY5N@XO(H*n?>OZqzx%c<&$%62<>v8 zVGdQl&dOa*Q7RB_VbVEv&L|D??Mr`q-X5f@@}WGezBu(h5H|i?{i$d#I1j<^djK!Q zAd4YjDycPr9EDU6*L;z?zT8*-#wiqkg~PI&o>V-f>;cX?+0=yb3w->hwXU%XZ<*u0 zA1%I0wne=CEe+(3#vQFmg|DA_anCk=dd%eyZ9$36ux|>>y24(w3@b%5(Os582z@oDig zbWcl+oBh?VmNe^_P!8If7e1UMvQEm8Y_%I<$A=#yu=+v{U61bRXfN~Na)xghkh;k^ zl_Fyyhd)17b6m~xl+3P4*az-H>kIgtP`gN@>Xogng00&w=vQOD;-gdy0*21@^vF`9 zB*}vEl7DL3GT6!2r^iTgg1WX-fY~gKF&plrVBjsqkUrL`hOw=vr0y)LS`(|Jdfqv< z2iH%{{yi2^ioZtROY1jc4QbCGRay+&%bD@mALmg}-H1l8PhDTXEN*fC z|IZ29u8qQKer|?2+#1-R?aw`ZN}qe5h7xp}V}>{1&rEp#+=TpbsCPo7LNtoYJy2pA zEzSW%KJ#^OCjMdvBq^>eT&iws+!R0})%sZMAIzZ8D|gi&M^@9cnb(lZzPlfgbx_Be z`U+A_xHN<4fCT;_^xr2DZh%B`T;OS$m-XFrWpcv@qOFX&yYUEy!RMD zr0_hD6ra{fBMIEJV)pC>x~?i#L|z;W#b7zS1I<^9}Vf&Yn$H|tWLn_ZIJS! zwlxeTbP7dh1$BdyoP|Iqlr2F;0=zsVXo7x{Wm{#K+sd<(lTllD)~6bK`J(V#_`Y*g z?6Op5&OmAE^x~CXhb*kHpT(?P;!Pd$U8U`IRK4f zWGA$vd4w&(t3S)kjlqT85r6Lq8gl}#^whY}ksvM9*m-&EbdPoK1bLizR+DFyd2?ET zjsIu}`$Bx=yeson%%A(W?TPib1@=upZ--Z20{t7Ol29u#55+7fQohRpf0{mQkmS~L zY%1}(iLZT+R_c0*CE*L8j?DAmVDAk}gTg`_E1;oxIkm=h-%Wm)Ok+r4vt^S<5$X;a zkRmWDWiDyM=bOC+Eu=~Y%3W+#NeOYX;F_|ApFqi_lBw3xHYAty&--4N-)d*N@Jhr3 zb4C8=Z01GN{$-`S2ExK(5%F%()^bkAA>ISbD|96msj|SJ4>dLtppo|B|G%++k&l4J zz|$^}MaAPuC9_XA&@g&zp2kgycLJsm(DNa*DgimEv0*j)Yqwk520FK;fHq;`qR77vV@U0uMDC<1P59-m-ibw&V0C}tqPjvBpg46{`-(c03ciS-aO9+(E!?0`$Tl( zkAjF5!URX*|N045Q|BAlBk_P{Jz5d9VE+2sHj|xYNQnT*vr>-_%sUrbo#?gt{&^0J zS#Fr~62x4%8-a}NSCpaj+~e+2vrr&!U0zL-2)*#X^Zq|QQ2?_4X{PF`uA3bmmfuisw~?&^=f>-x-jX76bzlK9x|(g*0Q+b9^cI6aogk$#Za`UL5AU{2_;MXp$w1DubbJ?v+BcRKEd4U3y&SBf{5yFPA@wT zhKzOV+_glkcXY_xjuUwBoaF|PoKXd`ug7W2v*Qh5!?`&a}lIfeR2BR6avKgPz#9bLx48g<(;&@%$7j>+W7<)@Bb66rk z{^b3zuLw@mz10Q05uQC%p|`X$=1{M$(C{oc(tZM#8a@)(SpV5Zkno%o^>&r*X+9<;rN7@+rOhO!rhad2Y$xlb#0DWpt&x0|8eV_0l^j{|t z+--nFVvnI9IX|zUgA(660!G@HtcVS%5Vh@dbHtZ?w}xHuFSgYmITKY$7RJZJile_@ z1CwME!Id0wW{x(W0^=R@L0i_})-jD^H90xa8h279o`w6WuO<96;zRoRYOfu4|L>;Z zKdt>=5{c3g4CoB2Wfknp>lKe-ygI#7#fq7M@!=}8dvKO=+Q+7VI*jM7c!I*;I^P2^ zIYlq|Hlh2vqRT2XCla=$sA~M%lIT{fPYvqTgcKWL`@4`pNcH8g#tKh9ltTpeh$F`GS`ReQXc<}9l1kS-1OQSAR z%zPoJwZrzcinBtf(>@hCMYw&nm;xXq15m%N!0Iu>#d2&|n&~SiBvbwoO5` zjs-fxc6vYvEG;HORyx>t|Gm+Vp_Rz2ah1Rq4oH#1<=4$n$oKNFO(o#3?vRh@gNIF9 z0Jw;Du~MPMJemWRZECFa+;jJL%k)JE@gHyMw`KBBWdR{ui~ zkd^=QT_-plFU)dLu1rD++r3OOwoBk|35t%NW#F}(yd65{b_!R~fq!S{e_H#$;7S^- z;w5(KNXecu#hG3&g5=o8#Xp;ZLAAZCuI0YBaLW**u)4k7&Na(b6z2a4;ea6SwtePh z*I|lL!D+)x>#F?4ZCObxGC%wC>K+@FT4m98?1Orq0_O=EM6$kM#L}M(U7c+UM01^> z-RWWXFn?7X*{IRBDV#^;-EZNyn{m7ASwpwzTf88JvoFn@>9WIoy+L z|3Y&Y*i3pn(ZbD@Z9#i>2cCn$sAZ%C2P>{(k=Dc;)1Y*EABeo~w*7q7y5}7a?5DW0 z2?$c3q3p1b61jzO#V?ja44OHArbhW`*)FXF=5#ZbOatqW7e%SNEfg^Q5!Qygk&_{6<#BVd zQ~BN5xk*O{&yPW6XTC!UA{e95h-)^)juaFYQQOD7m^dgtOXYK%#*NTYc-A{66+TrA z!JRptlEDgpTIRJcO|<)67mx6^xrVd>BkB%ER{*OtgCl#xBxs>Pq=SA3qwNRVnY~cR zf@?QUrVVO&UF0#oKz{GKRoc)_;4JLpBC9je0*lf$B;wcRnx1@hFtwL)-d^kV4#Lvs zPc0uwZ&TAmY4>E(oT0AQJbJ{gzXt3-487lz@%MRq? znu%qO`u?kd@|$&fsEzSi!nPMyIKE=J?>sDwAU58A9~@_7qi_4>Vqdzv_h$5p{9?B(0hOzwC6uPz3LJy&g^yQtL9sf|cg z8#v5oc$NoP=p-?0as4X^ve3CA^44W&v4Ne{GmmwD9IS<76AjC=;bV%iGX*Y}{A4yO zB%RSo!=?(>HM$>a)=yT)Z51xJQm+~nDg8-*v)W4F|>mw^7sCpfXU0dc@=8gc_5zhQ0B4QU%WshjpShhwGj zI=R`cA0}#76C_Eb!wH4JBk^8YeoA>mB1cX?uxSMP$c(L7_oz9nYSK0&{63$B(s$8f zPqr z(*0>={`8<`2SX`cfT2O(%Ie$Eeuh~q*%1`X?_N-VL326{BQoFk1$S(1 zv_1a3IN3}7WHO~Q0&+p!)Xp%%htPkYL^J^sX+h{~mm5euup6}HQ;%G{vTLIF-8vqY zk=gtc(Ji5Z=T3W&{}>GiN~D3yOfC+Q4%vJ@09-K&W|qG;FS2ms6G>dkyl3?e>ojPs zQxdFqT}D(>@`^X`8szkRcwy19``=~$Kdt>=5-Fl}^aXn_tDO~zrKxfaX=RK9N?tWURzs|b%H^MiSaqdYAH;G`|9@F&$L0rru0U)UanrT zt}`da?px+g77^V-vGi?dqs1Hsp)H`ykGra8)gvtL3}K22Q0*l5lVfDJEQ7z`)&JCCa)&H)Khl9*~P6A1EZ1 zMSOMsQ|2=Rjx?C>wQT;lOX3o~l}&dZ=vFuHJq2^%C%WC^TXgp25@SS5aHQ#FUEhf` z09#CQ9+1KWs`uG>pnSo&??e?@x4{ztYOxo4-P{jfA1YBu2I`iFxGvG#A+AU&O~tn2 zR4eWek%8!_9K7c92KxK@n}1sSzu*d*-0cGnv|B36Xb;SGNh=6hb{lNE@0}BteMDH` zqHYj^J=>|I-D&))V{s1oDaaIP0e_iM7Y5V8#BW7N-mW#~=o7c`cV?G<1P7K8RT&uI z(IP6im&v1Nn1#yKejWcm89J$eMfDB^kAp30bRz!|SKZU5m>5x_I}%bo7Io<-6=`_b z&CisG&Wrt|zN{3aW{6bn+RG*91k}uxnugu2`^0hao^-g$i`Y3#+F(N(s=}3LY*~Ni zVkJ)reD@Ve;zD#8LKdWb7+2{2#!v?KNBYZq{_-AN-*xRUUwC5^LXiDDo^gV-89K?Y zFBM6wHMiGM_ZVa9^Zjw3}dXuc4*^FKMHUf(T_|;Kunl zAv-bzvnT5_zp4=(F(}FDtUlj$wgbIO&3h&_Q6}{ZS=>@jUcGJLrn_a^9+V>^j4Od% zz`coM>LacnSK7H`QosDZLkUPZU zWQ&bfl)q}jHhOfI4XYb_8N($qNk00_htPkYLVy4YDKifxBc0HPf=)ggM=rFEMR#jH zJLd9o<)>0nvi5|=k46fKw<1*t@p0g|kWkDB1-@{}VPyUNY$X%})vJdb2t*NN%`Q`8 zIE#SWdu6rKQhfG2`qjv6atAFw(PCq@>A2Q8N4PUK>SfiUGP9g>Z>b(D(1ptSgyJiqqS(p9R=`r zP8xi0&XRf<<6qyUHE8wu{U&)4HJTqHN{QdKwW7I<%w(^CHE}s1ocdjf;F5`|rf#u& zTPDg$g4e%nBxEAFpA5^kjvQQKz%uF-=$#mK1%OR(ts9#!kqA|8GJWG`*V)ZQ^!N5r zE>ED0(vtQ_rL~?5L-vP8&jCTz%J}uA8tHp_{v=m44t>oTNE&q%eLd)$B81PvuDC9H zQQTB5q@&jl#b*upk;c6HY4D43%ah=gl-$9!33H7j2i!Ue&P=O9+#|d|t)cix-B%Iy z-*AuPi$TipFmXu~Hfs*wOuVC;vj#>LohPtkYh-aHS@-dY=-j!RrAWmd12!Y)*e^bwp zicY1CpQpOMlbHh+A$Nl*t$;+_>iF{HR`|%G&WOw=q8<4kg=pvEyFgP4 zZfC({r)R0gUS+D9{bps8W)mUrlEnf!Rl|n+k3^)9KdBr68K}v{$=RT;o?BCtWnxIP zLy2gRUl?-gKVV=({dcDz)A+&wY`;Z`6ahI{*G8a~5WXnk`1iHl(a}KUMA7;vKqCAm zSd1Ucz;jHMOv2{qxhO~oJw+2~gU-kVy9)%J05n(mb0P{M<3s4bP9ivS0EyHtH$*eE zPHSQ+Dl=c0%wsI8lzgAMb*AmL8u7o6w)q`sy5f0Fwm5>LV0pnhp7jeYph1z_7nPEe zseBV5OS@acR4sNvi~YK0>%P@;o-NYvTJ7SDodI#YT0_YZ61(K@BLAP({x69Hz?w7& zuYSHj_R!JZi8{h$<^aCxZ&>Vr4xA~>ghZicJuhLEvMeC~K1R^5a2L=HQI&97)(LYe zb04sypS9MU5&)uV%KRn;J(laU9D=7l)Th#bpgsE;-@Q}kK1J>`pvW(lPF7J05XG=l z%?;63*%$!799p6)W>(E?34^70-a4GOLMRchDAgsMla9bhn3iek^+d_{vD>BvcV4RV zyYsTZnh?U^hP{da48|SXU>KYFy%4kG35$7(8*}`D-&sd>jcM81G%797I7*~q){AuPFoNPkY+WEK9n5>4`D=VXMVNEu{J;9bYMep8}71TlY!#d|U zeJkvI<{(^aKMDPI_FOg}$LGsVr<@3!9V!dmoc|te^-pULfa^aSWRe`Se@n)hi;^71 z!3iDSi*F&i!-S41a|cU+3M;$oT;2C-uXz7rKXIm0)E3Uo}7UsOG#kcZwJ8D#P5qjfO6lM(&?6nL5z3K z%|iE3^V5>jt%)lghPh>M6AluZ0!8cK$`~69neHdCTe}ri>8eVlc#&Z znZQxkYH&w{#~Vra2_&2xYlx^E#cr-TF&(`rFgK`R*o$q15oODUjZ|S-9oY?s-1z3W zY_Dmsgg_m-@LpdkzxT?z8PEakDM#qU#+lN{LLTVRig9OeH*6eRwzPoHx3E0KP_({W zY|#aV#aaUc+;&FY^(#cVoQsGhfccGtPfEREcZ6++H-u_utlwO>FA#hn5@Tc7-c9$68h zWR!z=A$UvUNJL6gBPjmBmGgzB5U&ER%PS{7hb=pX+Mc936J!Xt|Moa^On?N1?$7S} zk4MNpCuh+?hBYE8z-YbIR>3=I7lDUCg+c3LM^^*%mi)2qH8(nk{{(i79$|Ub^vEy2 zV^=82?rz!|u;9NS@$HgzPZ$VtpB0P#1BZHptdD+sL^oSIx86BQKPP1&j@Pr4_(HQ| z8zi?9YvDeG{`-=g8-T-lK1VfA8{~*aiwK>wBM;+Vq~tL@)=-)2PTAHW1tKSc*+XYP z;r&iB+EC#F5vNR)tfwb4R-0UuDAmaq=Af{#@ybCYV!ln5{&k3(!>mubs85aVIy5uf zOtH4%z)Ii#u9W}jG5wX~qF%qmekYI_r|StjPzBy%#P%;;c3Lh-p=n}IEu-$j+v5c* z49x*1NlKdco*Vv&162n0#X^bBZ1u=Uw<2RLOYC!d6ngF^{S#U}Sc>gb^(*Y-mA`;u z`k9cI&nRV){+~)Y6|do|09maNyEN1Qp=nLl;I>Yiz80|NXD`^Bg-IB&+@H?Cnpd(N zIHIGIf_#hC@xJ576YPpjfGe+^{Dl`{bT}9mMtW?`Z3@U$mflpHASl+t!i}q0u-`P+ zdP>5O;Q1(Z)woDJ&sC>j;G+xG5iO0dEb|q2H5$~iOE|3r^E z80c$F%JF3^TA&HX;2r5m-j~06!^E%Z9BAu=8qa-o`faDE7==GWtqhmJ8~aA(a}^W# zKua0YaGp5L>SJGcx1K08RlOL^6Aqm)#85J@U%iu5a#dswuwRYD@QZ6Hc1wv8C8vAz zx77Dr<iOd6)Ko!R=`hg0Ie*ZD&SjRyP!wwKmxgA z{;V~7mm#LS5Z|0*)0cwILez0GinhHB`mW`gst6eT^RQw>_WCd6?we%v`EgEb&Uujg zSz#ct0X#9Py=!f+BHaFD%D%FKQ4~KZxr+Db9k9?PmDKerq_N^d2`p^DQOmA%v9)4U z#1iL9#oI++1|58X_GZq^i)1jxF-fvdC%Q~!D!ze3Er;787Hr^UpQ}`=Ar?2dgt~Og zP#=F?4G~f~Z&5mz1p(7vThfH*Vz#f6bUfPoQz;vKhZ79PTc;%IME7ZPP2-O{+>Z1+ z@rw`Y2`L)I%uy< z!z-&2>1`NRo3zvszaKwo-*X46w)|Zw|I^z4C6Q!2yHE#;(s&->gAJ*jj&idy5Y@1k zHdgCJtkrY)9W(GRzs7AlDnMX<;Rs438La{ZC)4?-KzLRZ{W7!>R|=j9r-DK1RveK_ z-?{+5O7Sp>P^|06M@==+jW_g~^!l^gwRQ;9$y!87s{J|mtx7lkZU+UjQuYBTN7hur z+%@SdMe$<@7`L)tM(PYwTkOfMRMTpg<_LxUig!%+^sPmwn^u-py}qt@zhujuhi;o) z_7vT`)?&Zmw9Rfy!`9UvA~G$i*ERa9k>_Ts^Wh$<9r>dVPls*J}5j zcneNLkZRL??=%CJ*!ZpKlTT!OhjiEVTfqFyBPR$q?cSj#MG+8O8uU7A1{XTX=*dVJtv-qkc<=3JDj4zQ^4+ZU3U&ddH z@HepBzYBYmA>`GQUV@?(;-dQgaTfXf6XwtbQbb7j1j!E*VRQ?I3>5! zQ_VB2$ZvD{M^3?Oo64o-WX7}9jG?up{l>kFNHKZ#&*Hp?J%m#O;EHo(oG*13&L}*A zfbYGfn++Eu$i9AYlM{#fAR(Jtmh*CPQYh8mwG(N?%Y_1P5XKmK^QGC`#G#bwYBxYx zTl(rTx6AC&gBd?Bq9Z*`<@?@rwg*t|wbcnfJcpVX2`|KNFjOrbf+dNSxt9EaYtO#l zJcVjRH@Ey zn8Kp@@QcU|{83Cj5A>sF_8;%ogc`CNu{dVB!@!pv<%2M^;UDM4{_8lzz5;NVN0SQX z7e2Fp{gsV?NqJH0o;o6?g6%4#OlVQG8z+ta>L%hbh~$^Xw#nB9X1!lq2rQO|%KJB( zSic6>p45DWVwIek$I;xaf-n>(4#TN$VP-uUtE66e8-=b#mF(wy{;rh&=`sDqVek;A zS0b$;7!1=Knux;Ep|3EONqc*)uNcd#x@%ac$;>nZC_0@0`15nSB^Lv+7f8lZTER2C z&EZti@o(=>as*jnNIYfWf_&(*r~$@55cMz1(EW{|A6)bB?!AV6_x@DM^&;vkoFY?v z#&39>o+-?;L{X1+A*P>gWAf{_;`761v{`8BCz!8dh-#67+Mb?|8f}Z$JQI|s@!#Lg z_z=Tk5DSGhE9}yhNm2TyF-I>XbiUNcr(8PxTn+Y0iW%6uUU`ZtGg0VJeERYI4F1}Q*=xUc#&9A$zrgS8P6YY*=9RRezBtZUPLk~e z6uNO50h|}8mNj7n63om`=y;P8W|jdeNnvu z-Ec*W%9YZ6c#;3C?bs8Xg?igCvB=W^^RCJ6q85{z3~Ys)zp$D|Cr zj_C7~8u5rsk-Xt?suqFDXe1mgMns@*5psGZ)lUTDCb69fpQX%Zo^#m0`k~xG&Brbv z(a&f1cW+8X`mIE{A1R6sBE%p0a7nQxjG zT%vori&&y~e=23TWf3`rmC%)=LbK^czGf*fUCEBgrK=}Aa2L`RWfrafKOxGT9bQvH zHiu{~{UTJicjt82_`W#YS~VN=Z0pkAN}J$+he~Ws?6H*^evi@NEJ7Ju5;jkEm7pzO z4{8h60TOr@HDdrsgent@`h!G*DV44#Ph~aO5PWB#2rIEsUlTJxl?>+d_o&h;g%(vuUCXOx{5Qy-~5j%4i?XGz5^t?Nbax>x*n zrTkB850J=z+FngB3&QF4(=r9Gjw4W8sPnp z3a&{6KtZ5iV`)29C4yE~rW-HKmf4bTqatAH_~P>wnt|otuXkA=dTT9f#h0Tc8O2#D z3I6nyQ?XBB1Qep@iQF2+-RDS`vA0)$DJoDi*IIo>M|b;#M-3ldmjXwZ&)jG5voz0vjP@O zIGOD%4l6wM6U$Qp84E#WP&?HGYqf5FT-{VSP-uk19>UZ(|N2|Yj=Ek;kKx|FEH>rX z*DZEsQp9wbaK0}qu15-wOE`fZ;5$f+aXt@ljouPfX3bfF`1*D5?53Hguk~KXq$g0u zoMNb3^y^RC{!DiN@^(nn%EYlDY1!LWcW|YRj4)yG6Vc zQ94IE>l-k6S(&*k@53BoIR!S+e_tKHJQSIc%Ma($60NdPI(n~5V-buGerM1ms8$PI zhD&N73;y$j&bHgF*oi%DCbC-(^1^ADl_z6_lT zfU7`-i=WcI)hyQFt~3EL{?`T~-{AsT!8<%C$bz%ZtEg)b@F@~}5!+7GowR|jR4YWR`tjcx`k&VR zFSuIlb#h!O3Si#l$KUfybeV!4%~s1ePJfh%lbP!(F8sPHr@^I&(mfTE@23waJzB{ z$9X#b@yCMr)va)6z>gR(h4hJPy+>Q4K$)g;-^Ojy}G$l?@6(&P4>mr8}hw=B}uRL`Ceoe&!aE+)7NXu(+0TU3lOO` zgkDbB@F%50Xsz3X5yA`*e@S({ym|j8UyK;}4aMMNVH7Wa>PYc(cZUqbk*+1U0ixVQ~Xaa z3t7><2|4Ip3_3nWO}fz^eqDxsrtS6KW4~_&QKVLy{eMqz*|evmM~Fk`i=}wACfy^% z!wrAaz3|ae=HwWq$yd_upMkb-OH!*Xy0VIb9YKwFaNm;&hz4wd@tan_% zXg=Wsr-IG%-wz^#2s?&iO_}GZhpdWKeN#=4Y8q?^Gu0s7!bo0fpHMbgYp zg^>()HH_F@qOE@Q(p{*93_7cbG7}8ZOB~z7ptc;;4;Jk?2k+i5h93P|SU}u+(jGH8A|+_D&_LqR&!EXSpOH zO~REUU!!Y`7MB3N)#EYtluj4(p%~F@LTm`6Ch_NIr_s=NwWTH*c#Qx*()l{ohko{G zu;&%_3EyFE+(irHFSk6FoZHIY7P+$8@=s=Sid}+2>#Is6FQw~P>Plb4H2rcsZm>lR zd$-s4$UTy+a@|e%QJ#EzBeW4U*}Fx%{8~8nMh}ykw%;UzF@J{EJ=fY{w8#uaP#5YV zg4z<6`i*SJT9W*FzHd+7!H1|F10^Jgen+@3_jDam*K24Cg^s^wdhh~W*S68eCk+AZ z{3H@*fEw?>Cn)}CG?LAT0-s)l#`t`2D-4N2{26usvIA9{aVxhy*x6}OoZ(VL=VG}? zqUH4z@+Ac|M~_K{uN2%I)ELD~KthmbHsOy%WJgv=ue9`Bp{40PlOFi-mC z1p@EHFvq1Ku)+Q_nTDWi4~8qGDRYSL6}@gK3kT%K4XLEp3W$PPNZ?h8C%Cd&4$zOA zX?2j=h-Ix!U4nG@ARmXv2n%SBy?kHeaGRxxG(Cr{#0H`Tf z0gK{;Z_+(DlUs-{&RF5YKp&tv?h;R^E`sXzp59cf9)a%DK2C=G_o;~wpr%j|xt+)| z1?^azu$o^nxP%#CI5>|4TUs!$T8ZBC22~s9CS*DsL|{C*7PHXE5_RzIo1a7A^>K}j zou>0U^btZ1xjFSJbRq`+L2r)UQij00+=NJeL+ibX)ZtkR0`z9)$RczH;6gxR3$X(%BR ze-`j1Q*@==%CP(q$InX5$~8*WfY)xD-`Hc?%i97UAYWRTp=MoRFl4{*V~8}vA#)17 zQ)#z6m&+8YfhNN!C_(m|2=6S~XUhqm0P;|4gfqfd2iXmdV<6aPU9ZoEBgRU2jSCA} z-7;mLEmNDTY-zMMv>j@63mZun@b}zOJTT~U=Fh0I`4JQsI8=P7o2ddpUum{TN1M*L-+Xpz{UDXPtJ{gg8E|`0W;c_83aZ$$+$iBYL zx&7mT)MGLoGu)TlVt7nVgwPwi7fSGn5=Qq3d{`Wkk^ERjJ@$0>u0bLCZ5j9-BF3-B z`zJLah1QRQv3~wvXBifBoncP&Dt}%c+~l$h%uYIpj)F{GNWL90vKIe}4-y+f#=IUy z$Rh|ebh1#1rgR}f$8owGcjRajjb$O{He z(4%&R+#a~q!)V_HDzMTR0j2k7dPg!Fs3^t{QCT2T7fdi>kAq)D#oXq*X49V|7{hi+ z8Z>0Y1H_%m6ex=!*lolFQ(t@aq9P9~=X1FA6#jr9HL9A9R1-M9My7Tz|z?@+f2;tSyF|M}k3AGG4rO)66i-ES-<3 z{Di9n{v^xCP4U`u9%6te?`2Bh_ZgCa0{hFlCe#m)jk|UMU;@>MmO;7_au4v?sX5#W zpLsj;0Y=LC@+AAv?y^g}UzLv@z}56LS&g4ww3om_2VC01H&7acW@4MWpMhPp?=4QFe?E4Ya>ESBUP9ofLkQ@za``D1Y4 zHMAlY()=>432inn!wm`dLm zx)D8-zZ$2ze0n#MRne09N!S>6I(Z=GI@{`mNvkn4r8@0(Awc|h9Se;mAwKlG;v}5X z7=GYBZ*Ap`rvQ*Uh(O1iRCESd+Vj^p`pHn4BwPqJ2~Cl4yptlC*^KG3&@R5=FUg0- zkQ1(0wa*hOMFX=)tucE^qEWGAhqZSJntz?E1j>lSye13>#!vv^+DrWgWFQFK&8V65lsr^*KQgbLy z`SpGIWx#WtH3tldS72sUox^Snu?*&nai>v{GmWq`ldVDSLNuOA**u?PCD_z};THJ> z$U5f*S^f`Pp%5uoivmU$Nrv4<+BQv=nIjQV#NR;-5-}h1taJM?v5EeBpK_=x?!FY{ z@@b_{_*;ZfZ6!S2Jjl{3jw>c=tW-z*<~9H>yb?wr$&PoW{0on~l++v2CldZU4LP_n$NJzBlLkTxN{5b20aLp0(#(Yt0GF6nQj# zH%7e*Asp)wz3RPL1QLGbJ_H-Jr~R*nD+~Zvlh#_&WNb~TN;K2skfRY|Iny2tP#x)g z4b6F$Jx&iwm)$7rIXWd>$&Ej`F-6ucIu!rCbc~YD!sxpO?&gjKWb6xtx-aeijv<3= zVKSkYF^_tTg$!mwnEhY~c^i_;-(|0Viv3@3m1(ntV+1-a&Wdvm+C_A!=X6#s7nYTd zl)H{%XH>J;x*v>z>Q!BViU47!nv-wJ!pH0J@b;F_$^}K?Ng>E<)+nkI(Dsr*$3Sd| zG`SdPoRjVC6EoT-9QH2K)~N7}{>fNl!acm*`Xmqo$?2C*^Wr-m4ZE75$Wp5zVT;`Y z-Uxrk80O!pW;n^E6U7k4`@y`|C?}QQhQxo$6p5oWFd4UXRoQdBPLhs_e7LIvzkEQb z?;sPex-6A70Zy~*iAjdWj^Pbjam6jk?7)xwUJQZR)|I;Qy>ta%M%a6WufPpMM^x}c zSakZk5@V#Ogm{YI zwe+Y!KI?qRWUOfZt_l{GE@VT?<1I^~UZPnTIS?E=L(O1cl~gcPh^NN0eZa7!Pw$JO z*PCuJwO8ZD9MW!y;!>CmRw!kWCw2U((5?MZH1|v)-(_J4Q>r`rpWmjY;=%1CdE>Y0Fa^yS2Q2eT=HN^}b1!!D!n5#Tc zLW&rM>!WQb+hxEtP@@7KGDE+~#HkYb>IM+Q16sKhrDGil5Md64Zont`o)oWUS&NWya~Q$BK&u zpy9QOQwpF$>w>%-#QgU?g735M1eE{3EdpE*f>7Korv8O=DM@V2p%O(pPWDzMb8j88 z&5LYKhQa?nx{UEqrfCVaHjq@WTbPj8zrfuJP=_Hr5~pI@E>i!f=8pqW1pQQl5kl0p4e9}g7(b2* zC;j8Rqg;zsys{cvetV>xb;1c3NzwoFdMA?+QboY#S)Uh z*B+2$g~j9u7xfk>p*x;uAPHM=_sjgv>BF0q#PTo0<({m5#W0rp<0-Y$tgwNA-*&w5 z!Bsgaq48Bb1|x1!#%qO>WzBHQ+a19TBHNr9f|D^7eM)wu)TpxX zQ?)9p#p|lCZ(Dj-p9`_iUuqx7enfRC=%KR&!a2*nQ4m%CCNcz`fwjfB-9cMMp6Q~^ zf{C6bTT?raOvA!af!T#{h>HW)98(kLL>~hP9lDTvrt8+7|1-uX7V~_4ebsFYo76d0 zva>cB%1(t+%g=?nj}nZ@C{<)D$Ofi4@wIf@MIAw~StdYG;+&)JSf$uRU7Bg{Jutc3 z_~Mm97P$k)g$pD8J7!(1Dx7Lp<;QRhcw?Wt)qJQf{lS>bq2?xz?%cQH)}o( z%!be(apJ3D8$CLSpsZ`MewRPgEvtfH)b`EJ^gY)Amcez*z1s<;?$#Ua(6{PXs-r4! zfW-D1=O+m^4~Z6__qv`kb;lNs!E@M;+PV>juj3%Q8h}z%!O}gFalWgqi?b1);pBxW zd{&`e1|&IbaSL@IGVhB#17ZrS_w8Km&LR0vpNph!{7x_fgTxoA{Y((il#s_q0C{Zd zq#CgBJV|nzy>cfdKXS$oWMinujjq8d0$lp?OPyapcQu%dKoqjcB`}Z=GIiq<60mr)c$8#mI%W+`F0wQ>+<&)42>J?SJod8t2I+-N!x&4TjHwcBi#ahGM0c%1 z9j0LbINb*SnTtjE!3?-@yGN+dy%`5EF;ejr#doL`Tjnr^7L7e1F-r&_8vGxY{`(|C z50FSQSV{0ki-!J=ueh%$k|LGDLW@T?u&av^u|zO06|sVd-xwxgwx=D(S0uRjTSs8{gr&T1p2PvmmF_n2C69ULjc3T9=X#DWJP8;%9_qvSvJ54E&p-O7 z*#9Mw24*mHU$Jw};=8)O{tCV+`eEhT(aXh18%*h%-;W;MY8arS*6fEhv=;&wHWLH^ z*mxFu>`Zpb{t00ZTqhS&iYiizZfU9bs~jD|$p$wXJh;E;=c=<>7iH$L$7v`~)=Q4vE$Mo1?*t5h98l?aQ(fjEXwKHtbL|<-w*g zZx*jpw<(#JnscI5TF0%<{TMLAajSVV366S^@=B@99Hi;kvE!wl=22EKyvybE@upa4wOsLBI;JV^Jo=I z=uZwdlWBQLr;}-vz6#VKzVBGhWd4>MwFN^Pu^vAlt2!wrI*7QaEr8a%?*Z$YQC5;d zdndZ1?jR?pAZN*#veoMF&I}i;rk5lYYgN#1lE$7n7s_d4J#GB^CrE(4?eToXv!!Nz z`hy}>C&8n9otet2iv{Ln@E)evQaIsK3ZZzn;O`L{HU4^*l05UAURNiPiRv7&I#^yj zA`f^?&~EsV<|>wWdhWPR>&0`=_uLzx7g=3z9_4A+F`Nu1H%Is8FcRozOgNa?z z4~Y<4!6-{b;3FQ2NlM8BvhS#2YC8&zQ!9k`~G){NGWMk3h zyQl$t6BdF+@IfMP>PMXXq<$PPD6=6~qbb1sUC}$+49qC<_#vw|$^jpT#Qyty0}Aj> z#OGJcUH0}#nwScge8fT2)ac=>V-m5~xXhvxxr6$8Iwr~3tp&K{^gYxns2OWjXX>Ix>e*v32wck0zdJ?z)7SKu zZ~V|9b=3#?&G$#8*5Vqpx$!lM+5O|2pTtk} zB8@TLLAUbD!VkIvZb)nERhz=K8I5JDS?aUu_)a(QSQNkI!#2W3&66Ed{ZNQ|>2)L1 zotuj&86KlGPN79EY|qMAf`~H_V!&5@$>*Pz%TQJB*UZgG1Jxmt+g~>s)LcKN}5f1hP!wQ~Y+C;E|f>e*Ur3nRk>gN~DmUG|wx6=*=9o20v z-K_eW+f^^O#KS^Wb%3Voi z%XOTHE{4_*sXz7ZBF{Nd_to_L^Y&zvVZ|<(fJP240auluJ%zzaYF$UN1}tS+k6E=5 zTRrz6^KQ*y<)yuOJlq_>5x9K~;qAr}I);Ec;^N~P7a^I}@n^~c9l>Fj_%@8nqWYRx zNgH0T+l#!3A`PPc_$KutDe2;!QmuIfA0l3wpU2mj`WlmEG*W>%w_5Htj079*Kfals zA`#2+-=ey3mU5ippBh{Iv}%5!RRLebg!ciznXid8@Q~-`J;3Pxn%bgD3`l zf0o)QBEHbOe9i2K)Q4L+{y7n5Eon(p}-P zXEhW)EdAFh1alssklGqcgg%Wp10dDWKG@1YM`D!}O<)(Y-7CkE%2d{|CAtlC0po6N zwY<8q?+l&aEwGm}XsDmVM&3>x`}uK>9Bq!TJ`r{HNFh6!M?0&z0zh(vVEnIl+#(?04Y<5B5sv2*TFqHymVV_u&v_8D4Hd zt}c?|pEgKKcqQ4;l@L2+XCgh;>E@lo2U?0c;qw`<yaZGxD^_#SIWuV$ubCP5IxCoibCxZ#N;en{?uqH^=h!p^?qEQ+)Yv~2 zJS455-)9^rm6!6fuDUXxOI%e;+tM#46BiDB%Z)BBKdodp4xhYSqZP3jMafQ@I_;?S zCNpri#z08KDo~BSJJA^_CJ*4Wk>vN^mEEK#>Y2}ee9^6NEDDEd3~+Y$ygrjl-tZLN zC=ELcNN6`ONGoi!Li%E!g&iLDfyxHzGO8H%5<~jt~3((2Q z`Xokw)ffqE=oglxRVkF_DyQrEGeS9F63*c1C)Zi0=WjEId;F-!7i9RhRjJ8fCOGY@ z+6u5GTy$gnJw$s5j`O63p5H2pf)OQ;m1ZF;@|XC&y}AM8n^Tu6^%G^>gf7P^_X!0b*C~+F# zjg8?TiyYX7@Z$k=asvOtg@yNl7%V(jYYdQh0WXNEk zN~9$;q*+JA@+AZMxnN?3pU}@7n@`q(PcdUPRCYGC@RQF1Zgi7H4%WcQf*!s(G&eaL zf5Y`pvHuIMoCJ1dSy@BDPiWs#t_5q@mU&0pJ_B2qGTSU=xsVN^e%^JQZ+y{r84n^) zeA?;g$K-q~j6GF{f0|mbq>pJJ+d@bjZn=^-QlaQ@!{61yeWOGae4|2?uIu1@NO8n6 z0KgU9T5aW_*aI}Mza8L*6L7I3!*%xhRW7eA0*Q_gv6Cj=R*>n5BKTRpq!2ZAxF|nf z$A?kndZ{=TB}2^>V%BaRUMKKd>A@d^s0b zKAGfZfN0jg*fivAX}1uqOjl;M23g-}?1xv++C>pule!v8ais>0HK{C$d1(Q2AzO*D zJ%b}sl4?4t3%<9r;<#@cdhk+th@pzZC~u@vJA8ore9F*JHEuTvxa}IcPD?(WE!=

hRd> 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

vHSrHL`4Y!))mrU|+My=J*?NCLvdFH?W^2AuF;5 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
8FM`BK1|u zEXX2khgZuTb5uD7T(lP7A02xEjBh!M*}B8m2o5W<3G9XQ^7=PKqacs#MwP6IcVgQz zw2=uHzgD^{l(lT%oZ7A0tQegN)~iPq-zxT0jfis@(Ihtt3R&q+cXl460N0(SPoFUU zEys-w>a{SvKP#6Ub+XJxSjaL$XjAcE$2|xvK(Uq=%3oDB%-3J5PcScTS=C zbs!yRA>^`{p>vzck<&@r-P;xOLn*7Do!8F;+Z?Xqr!dnbpBZOv@6VYPL1SAG;g|7? zCXwtk*OD@>pnCwDZzP&E7NXX4QcW=QC{zwSX8piD%Y?@!*EkS!#o@vRt9YJq^P3x7 zw%22V@#yk|@z%tGx-UUH`s8P+^UAZzx;v|Ni%2b+wmK4JtX6rJ#=2X2$=^8(8Vu{V zCh81js$*hTU83yI%|e9NhIx_4Ru@0seJjMI&s~M#*sP|u076WPsE;b;(LsTpPtFkc$Iv~j(bcN6vU#%yB9^oTi&OWNw&kYthTTB`! zVD98)I3}sKh~YL8ZTrH!#i9o;f|HfGlS>*_Y~L5Gi@k_JFWqHF9&2XR*z%M>Rw`- z8F#6fdn*3gA@{}!1u`8FXrXVY+9($N&E}|qVuOBJsUUcuu%YM9%`;-`)95-dp9aMy zW@%J2!uMIe&3DCzne`6{zI-ZnzJfA0=Fsm1&0*u*@H#ArsiJ)5Ryvs4rzU#&nHoNs;y+~4K77Q$xf8v;CePlc{@ zo%5_Ee4&|?nUu_FIWDW^pj&HKnrNdY>UgK>B{09X+y|-hE*l;j=O9ZL0=~Cw|CWF! ztL}iWv}Ucz2u<80^*R`z!(3W(^@B0so3zGt~DcZ7H42?}Uo$4=7&V%x6dt%GGXs~gi{g_R9%|I;xCzUS28uEh=@oGtdgF3f-R$IQOzc>%gQB47o5Ow;HjFpLSW6beHX8~) z)(-oZk!Z`KP?sKp0D84ST&CcihxAKUA3KLf-LZFJ?H3tQdpPTy?{RnPe9EyM+V8M5 zbDKL>C)P$(oByqu2JD<#f}yD7wUfuiZHgA3i^gFFqTiGliyC)#Z?4GV0zXOFN7RfF zYyB-UVx}k^+k@b4oD2p>+$Q@ZVy)_rIro^i2|0e-r_Mo%SRPvzs^tZ)U`Udjs@xOP z<%KCn4jJjDnPlWVx)D**L5#uXbwvZS=XTU;aH^Lo3^+O>4L82JNX&-LFk!4?@Bmg3 zYN4jibW}l7bw)oD9@x9U2Ly9P2u9%-l09A>Ib_>@K7Z?lPIMyJvaZVAAx3y!dGo&T zMns>5*sz<+;iodai%Kbw&xiBBDe-RNN2adQEwcPGudH5J7eP3KR0TGNwx)jdFPaNK zAobIYTb1ejV@8f}-g0q=KBht2OXFo|LX5X=FV5o4eY41!<(*R&Qo$eI=uj#$$(bnY z7!L*3_sUjL$yn2_=^cn9&8`L)@MexO#XR?dPA@!Hmk(F$Xtjkga3@s~maGNx*T*W8 zF$R6lt+#YUJ6NhGhfso<0M_?>bQ<+079SMlp||8mQ{bqkjwys5t2;k7jm4GHWzWp| z8hsLRL?r{43?JYNT}T{u9^QsvyN6%#a#mj!)(-VOj1t^q82XrWVMSqrFnh@&yP>Gdf2qoiBZ)5!s=X z)8}iw5U^WZtTj2QUo%8~TQ0RFRo~-laT-t+I9bOl8>`ollhz;25P3iHVW?MI;;TZ6<>=8@p5dB#;SEDPIkNgC^X++-~Kl_B2TP!`Q&a5p8 zd2CNKa{;4Bjmle)>?Pl7gWfN^vRde)i{WrHMu#mi`(XidhQM?6%#WP9C%Eie06ux| zbs}RWoSs}PGlY7kV4FfcJWaIvbdA7|)p?j91qUx2U664~FH3WK5aoAc_H^0w)f(Op zlAoX9uUeS`K$`w%?mM8fS7-%^_sSgJ79g!FW_Yo!obacVB(#=8iJ)2LYB+OAYc=%I zV)0!&J(wZ-`S~7YqFwo12ddinhoYM7P zD|1vIa~^_zf~f`_xtPJBt&ij}D;Tmt8PF1D*p~C-z(k$|-Cl!Fn#v*1_V3jMWjZGV z6kl7oC(Mm2I}1q$xdd5m!Zd49g-Yp?|x0PigeV-!0jr?Yq-kpYz#yx0EZ zC%f9VTNj{5iY|XXAVtb1T#s&QQhV!a9~Bg!Y*4y|hE>^>8P=5D(0dozlc$p*-Tc$7 zOYu^@b7D+V%DxX;^*HSHdJ*VZr?v6x8p8J-7Mo#Z0z0Rf97i@T>D=Ic6W$8qrEpvm zKjQL)i>gn1slIK`MP3T-$!mG@uH|ON+ZU&s7AFwf2&acn5lm9mSm$lC7T*!L@0i6m zi&>)M;FN=g2q4p6QZA>e}y8vMlKQ+^6$1mD9V(hRORf zFc`Rcd)QmbXj`(a{H#+mWM})-rJ+z&Kj)4apyRdsLORBtUp&T3^|K8l<6RA33|y;` zd1id#*#Rk^E8n`xj1C{g^m3zvd4>40l#5$QNrETGm6trP_NF^LyR+a;>j@xcKRYbs zWOp+a@~KOeUR76b*n33-l$p!x8;Ika&fkhS)Y=jFo@Y<4@1>=Q0Gs2hhY32VIXwCT zfm3j>KZ)?n`19T;Tn|@r>6ka!Yf8Bq>b9JiXUBnHUt~GOS@_e${@0YM%|fkw03h)3 z^|>>@UgNVJKwY{fZgsGp`LaB^Fieq7=MbF^jfo{F=`me}QTV+K+((NpA2~|@yV?w# zClU02#jk?)FfbTDp})mYcwk~b1B2DkdS(WO&!?VnF)%#TI3Pv;P{fh%ZkRkMCHdPI da{+CyOH_%|>)e|#`sWyKXy{%mxN7zI{{t9-t#1GT 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) -}

ecf&5+ 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 Date: Thu, 19 Sep 2024 21:26:42 +0200 Subject: [PATCH 2/5] container: add cbor serialisation --- go.mod | 3 ++ go.sum | 3 +- pkg/container/car.go | 4 ++- pkg/container/container.go | 54 ++++++++++++++++++++++++++++++--- pkg/container/container_test.go | 10 +++++- 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 7059979..ce6e58c 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,9 @@ 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 diff --git a/go.sum b/go.sum index a2ea228..78f2e82 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ 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= @@ -21,7 +23,6 @@ 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 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs= 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= diff --git a/pkg/container/car.go b/pkg/container/car.go index 677fe7d..dcdd589 100644 --- a/pkg/container/car.go +++ b/pkg/container/car.go @@ -29,7 +29,9 @@ type carBlock struct { data []byte } -// writeCar writes a CARv1 file with no roots, containing the blocks from the iterator. +// writeCar writes a CARv1 file containing the blocks from the iterator. +// If no roots are provided, a single EmptyCid is used as root to make the file +// spec compliant. func writeCar(w io.Writer, roots []cid.Cid, blocks iter.Seq[carBlock]) error { if len(roots) == 0 { roots = []cid.Cid{EmptyCid} diff --git a/pkg/container/container.go b/pkg/container/container.go index 6632a85..58e3f87 100644 --- a/pkg/container/container.go +++ b/pkg/container/container.go @@ -5,6 +5,8 @@ import ( "io" "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/multiformats/go-multihash" ) // TODO: should the invocation being set as root in the car file? @@ -37,6 +39,43 @@ func FromCarBase64(r io.Reader) (Container, error) { return FromCar(base64.NewDecoder(base64.StdEncoding, r)) } +func FromCbor(r io.Reader) (Container, error) { + var raw [][]byte + err := cbor.DecodeReader(r, &raw) + if err != nil { + return nil, err + } + + // TODO: the CID computation will likely be handled in the envelope + // TODO: the envelope should likely be able to deserialize arbitrary types based on the tag value + // TODO: the container should likely expose the decoded token, and have search methods (simple, but also DAG reconstruction, graph path search) + var cidBuilder = cid.V1Builder{Codec: cid.DagCBOR, MhType: multihash.SHA2_256} + + ctn := make(Container, len(raw)) + for _, bytes := range raw { + c, err := cidBuilder.Sum(bytes) + if err != nil { + return nil, err + } + ctn[c] = bytes + } + + return ctn, nil +} + +func FromCborBase64(r io.Reader) (Container, error) { + return FromCbor(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) AddBytes(cid cid.Cid, data []byte) { + ctn[cid] = data +} + +func (ctn Container) GetBytes(cid cid.Cid) ([]byte, bool) { + b, ok := ctn[cid] + return b, ok +} + func (ctn Container) ToCar(w io.Writer) error { return writeCar(w, nil, func(yield func(carBlock) bool) { for c, bytes := range ctn { @@ -53,11 +92,16 @@ func (ctn Container) ToCarBase64(w io.Writer) error { return ctn.ToCar(w2) } -func (ctn Container) AddBytes(cid cid.Cid, data []byte) { - ctn[cid] = data +func (ctn Container) 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 Container) GetBytes(cid cid.Cid) ([]byte, bool) { - b, ok := ctn[cid] - return b, ok +func (ctn Container) ToCborBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCbor(w2) } diff --git a/pkg/container/container_test.go b/pkg/container/container_test.go index dfa7282..b294b43 100644 --- a/pkg/container/container_test.go +++ b/pkg/container/container_test.go @@ -19,17 +19,22 @@ func TestContainerRoundTrip(t *testing.T) { }{ {"carBytes", Container.ToCar, FromCar}, {"carBase64", Container.ToCarBase64, FromCarBase64}, + {"cbor", Container.ToCbor, FromCbor}, + {"cborBase64", Container.ToCborBase64, FromCborBase64}, } { t.Run(tc.name, func(t *testing.T) { ctn := New() - builder := cid.V1Builder{Codec: cid.Raw, MhType: mh.SHA2_256} + builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256} + + var dataSize int for i := 0; i < 10; i++ { data := randBytes(32) c, err := builder.Sum(data) require.NoError(t, err) ctn.AddBytes(c, data) + dataSize += len(data) } buf := bytes.NewBuffer(nil) @@ -37,6 +42,9 @@ func TestContainerRoundTrip(t *testing.T) { err := tc.writer(ctn, buf) require.NoError(t, err) + t.Logf("data size %d", dataSize) + t.Logf("container overhead: %d%%, %d bytes", int(float32(buf.Len()-dataSize)/float32(dataSize)*100.0), buf.Len()-dataSize) + ctn2, err := tc.reader(bytes.NewReader(buf.Bytes())) require.NoError(t, err) From f7b4b48791087c99307eb065302a574215e7671b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Tue, 1 Oct 2024 10:33:38 +0200 Subject: [PATCH 3/5] container: more experiments --- pkg/container/container.go | 99 +++---------- pkg/container/container_test.go | 60 -------- pkg/container/serialization.go | 216 ++++++++++++++++++++++++++++ pkg/container/serialization_test.go | 175 ++++++++++++++++++++++ 4 files changed, 411 insertions(+), 139 deletions(-) delete mode 100644 pkg/container/container_test.go create mode 100644 pkg/container/serialization.go create mode 100644 pkg/container/serialization_test.go diff --git a/pkg/container/container.go b/pkg/container/container.go index 58e3f87..472b8c5 100644 --- a/pkg/container/container.go +++ b/pkg/container/container.go @@ -1,72 +1,24 @@ package container import ( - "encoding/base64" - "io" + "fmt" "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" - "github.com/multiformats/go-multihash" + + "github.com/ucan-wg/go-ucan/token" + "github.com/ucan-wg/go-ucan/token/delegation" ) // TODO: should the invocation being set as root in the car file? +var ErrNotFound = fmt.Errorf("not found") + type Container map[cid.Cid][]byte func New() Container { return make(Container) } -func FromCar(r io.Reader) (Container, error) { - _, it, err := readCar(r) - if err != nil { - return nil, err - } - - c := New() - - for block, err := range it { - if err != nil { - return nil, err - } - c[block.c] = block.data - } - - return c, nil -} - -func FromCarBase64(r io.Reader) (Container, error) { - return FromCar(base64.NewDecoder(base64.StdEncoding, r)) -} - -func FromCbor(r io.Reader) (Container, error) { - var raw [][]byte - err := cbor.DecodeReader(r, &raw) - if err != nil { - return nil, err - } - - // TODO: the CID computation will likely be handled in the envelope - // TODO: the envelope should likely be able to deserialize arbitrary types based on the tag value - // TODO: the container should likely expose the decoded token, and have search methods (simple, but also DAG reconstruction, graph path search) - var cidBuilder = cid.V1Builder{Codec: cid.DagCBOR, MhType: multihash.SHA2_256} - - ctn := make(Container, len(raw)) - for _, bytes := range raw { - c, err := cidBuilder.Sum(bytes) - if err != nil { - return nil, err - } - ctn[c] = bytes - } - - return ctn, nil -} - -func FromCborBase64(r io.Reader) (Container, error) { - return FromCbor(base64.NewDecoder(base64.StdEncoding, r)) -} - func (ctn Container) AddBytes(cid cid.Cid, data []byte) { ctn[cid] = data } @@ -76,32 +28,21 @@ func (ctn Container) GetBytes(cid cid.Cid) ([]byte, bool) { return b, ok } -func (ctn Container) ToCar(w io.Writer) error { - return writeCar(w, nil, func(yield func(carBlock) bool) { - for c, bytes := range ctn { - if !yield(carBlock{c: c, data: bytes}) { - return - } - } - }) -} - -func (ctn Container) ToCarBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCar(w2) -} - -func (ctn Container) ToCbor(w io.Writer) error { - raw := make([][]byte, 0, len(ctn)) - for _, bytes := range ctn { - raw = append(raw, bytes) +func (ctn Container) GetToken(cid cid.Cid) (token.Token, error) { + b, ok := ctn[cid] + if !ok { + return nil, ErrNotFound } - return cbor.EncodeWriter(raw, w) + return token.FromDagCbor(b) } -func (ctn Container) ToCborBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCbor(w2) +func (ctn Container) GetDelegation(cid cid.Cid) (*delegation.Token, error) { + tkn, err := ctn.GetToken(cid) + if err != nil { + return nil, err + } + if tkn, ok := tkn.(*delegation.Token); ok { + return tkn, nil + } + return nil, fmt.Errorf("not a delegation token") } diff --git a/pkg/container/container_test.go b/pkg/container/container_test.go deleted file mode 100644 index b294b43..0000000 --- a/pkg/container/container_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package container - -import ( - "bytes" - "crypto/rand" - "io" - "testing" - - "github.com/ipfs/go-cid" - mh "github.com/multiformats/go-multihash" - "github.com/stretchr/testify/require" -) - -func TestContainerRoundTrip(t *testing.T) { - for _, tc := range []struct { - name string - writer func(ctn Container, w io.Writer) error - reader func(io.Reader) (Container, error) - }{ - {"carBytes", Container.ToCar, FromCar}, - {"carBase64", Container.ToCarBase64, FromCarBase64}, - {"cbor", Container.ToCbor, FromCbor}, - {"cborBase64", Container.ToCborBase64, FromCborBase64}, - } { - t.Run(tc.name, func(t *testing.T) { - ctn := New() - - builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256} - - var dataSize int - - for i := 0; i < 10; i++ { - data := randBytes(32) - c, err := builder.Sum(data) - require.NoError(t, err) - ctn.AddBytes(c, data) - dataSize += len(data) - } - - buf := bytes.NewBuffer(nil) - - err := tc.writer(ctn, buf) - require.NoError(t, err) - - t.Logf("data size %d", dataSize) - t.Logf("container overhead: %d%%, %d bytes", int(float32(buf.Len()-dataSize)/float32(dataSize)*100.0), buf.Len()-dataSize) - - ctn2, err := tc.reader(bytes.NewReader(buf.Bytes())) - require.NoError(t, err) - - require.Equal(t, ctn, ctn2) - }) - } -} - -func randBytes(n int) []byte { - b := make([]byte, n) - _, _ = rand.Read(b) - return b -} diff --git a/pkg/container/serialization.go b/pkg/container/serialization.go new file mode 100644 index 0000000..c802891 --- /dev/null +++ b/pkg/container/serialization.go @@ -0,0 +1,216 @@ +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" + "github.com/ipld/go-ipld-prime/fluent/qp" + "github.com/ipld/go-ipld-prime/node/basicnode" + "github.com/multiformats/go-multihash" +) + +func FromCar(r io.Reader) (Container, error) { + _, it, err := readCar(r) + if err != nil { + return nil, err + } + + c := New() + + for block, err := range it { + if err != nil { + return nil, err + } + c[block.c] = block.data + } + + return c, nil +} + +func (ctn Container) ToCar(w io.Writer) error { + return writeCar(w, nil, func(yield func(carBlock) bool) { + for c, bytes := range ctn { + if !yield(carBlock{c: c, data: bytes}) { + return + } + } + }) +} + +func FromCarBase64(r io.Reader) (Container, error) { + return FromCar(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) ToCarBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCar(w2) +} + +func FromCarGzip(r io.Reader) (Container, error) { + r2, err := gzip.NewReader(r) + if err != nil { + return nil, err + } + defer r2.Close() + return FromCar(r2) +} + +func (ctn Container) ToCarGzip(w io.Writer) error { + w2 := gzip.NewWriter(w) + defer w2.Close() + return ctn.ToCar(w2) +} + +func FromCarGzipBase64(r io.Reader) (Container, error) { + return FromCarGzip(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) ToCarGzipBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCarGzip(w2) +} + +func FromCbor(r io.Reader) (Container, error) { + var raw [][]byte + err := cbor.DecodeReader(r, &raw) + if err != nil { + return nil, err + } + + // TODO: the CID computation will likely be handled in the envelope + // TODO: the envelope should likely be able to deserialize arbitrary types based on the tag value + // TODO: the container should likely expose the decoded token, and have search methods (simple, but also DAG reconstruction, graph path search) + cidBuilder := cid.V1Builder{Codec: cid.DagCBOR, MhType: multihash.SHA2_256} + + ctn := make(Container, len(raw)) + for _, bytes := range raw { + c, err := cidBuilder.Sum(bytes) + if err != nil { + return nil, err + } + ctn[c] = bytes + } + + return ctn, nil +} + +func FromCbor2(r io.Reader) (Container, error) { + n, err := ipld.DecodeStreaming(r, dagcbor.Decode) + if err != nil { + return nil, err + } + if n.Kind() != datamodel.Kind_List { + return nil, fmt.Errorf("not a list") + } + + ctn := make(Container, n.Length()) + cidBuilder := cid.V1Builder{Codec: cid.DagCBOR, MhType: multihash.SHA2_256} + + it := n.ListIterator() + for !it.Done() { + _, val, err := it.Next() + if err != nil { + return nil, err + } + bytes, err := val.AsBytes() + if err != nil { + return nil, err + } + c, err := cidBuilder.Sum(bytes) + if err != nil { + return nil, err + } + ctn.AddBytes(c, bytes) + } + return ctn, nil +} + +func (ctn Container) ToCbor2(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)) + } + }) + if err != nil { + return err + } + return ipld.EncodeStreaming(w, node, dagcbor.Encode) +} + +func (ctn Container) 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 FromCborBase64(r io.Reader) (Container, error) { + return FromCbor(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) ToCborBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCbor(w2) +} + +func FromCborGzip(r io.Reader) (Container, error) { + r2, err := gzip.NewReader(r) + if err != nil { + return nil, err + } + defer r2.Close() + return FromCbor(r2) +} + +func (ctn Container) ToCborGzip(w io.Writer) error { + w2 := gzip.NewWriter(w) + defer w2.Close() + return ctn.ToCbor(w2) +} + +func FromCborGzipBase64(r io.Reader) (Container, error) { + return FromCborGzip(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) ToCborGzipBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCborGzip(w2) +} + +func FromCborFlate(r io.Reader) (Container, error) { + r2 := flate.NewReader(r) + defer r2.Close() + return FromCbor(r2) +} + +func (ctn Container) 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 FromCborFlateBase64(r io.Reader) (Container, error) { + return FromCborFlate(base64.NewDecoder(base64.StdEncoding, r)) +} + +func (ctn Container) ToCborFlateBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + return ctn.ToCborFlate(w2) +} diff --git a/pkg/container/serialization_test.go b/pkg/container/serialization_test.go new file mode 100644 index 0000000..14ac11d --- /dev/null +++ b/pkg/container/serialization_test.go @@ -0,0 +1,175 @@ +package container + +import ( + "bytes" + "crypto/rand" + "fmt" + "io" + "testing" + "time" + + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/crypto" + mh "github.com/multiformats/go-multihash" + "github.com/stretchr/testify/require" + + "github.com/ucan-wg/go-ucan/did" + "github.com/ucan-wg/go-ucan/pkg/command" + "github.com/ucan-wg/go-ucan/pkg/policy" + "github.com/ucan-wg/go-ucan/pkg/policy/literal" + "github.com/ucan-wg/go-ucan/pkg/policy/selector" + "github.com/ucan-wg/go-ucan/token/delegation" +) + +func TestContainerRoundTrip(t *testing.T) { + for _, tc := range []struct { + name string + writer func(ctn Container, w io.Writer) error + reader func(io.Reader) (Container, error) + }{ + {"car", Container.ToCar, FromCar}, + {"carBase64", Container.ToCarBase64, FromCarBase64}, + {"carGzip", Container.ToCarGzip, FromCarGzip}, + {"carGzipBase64", Container.ToCarGzipBase64, FromCarGzipBase64}, + {"cbor", Container.ToCbor, FromCbor}, + {"cborBase64", Container.ToCborBase64, FromCborBase64}, + {"cborGzip", Container.ToCborGzip, FromCborGzip}, + {"cborGzipBase64", Container.ToCborGzipBase64, FromCborGzipBase64}, + {"cborFlate", Container.ToCborFlate, FromCborFlate}, + {"cborFlateBase64", Container.ToCborFlateBase64, FromCborFlateBase64}, + {"cbor2", Container.ToCbor2, FromCbor2}, + } { + t.Run(tc.name, func(t *testing.T) { + ctn := New() + + builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256} + + var dataSize int + + for i := 0; i < 10; i++ { + data := randTokenBytes() + c, err := builder.Sum(data) + require.NoError(t, err) + ctn.AddBytes(c, data) + dataSize += len(data) + } + + buf := bytes.NewBuffer(nil) + + err := tc.writer(ctn, buf) + require.NoError(t, err) + + t.Logf("data size %d", dataSize) + t.Logf("container overhead: %d%%, %d bytes", int(float32(buf.Len()-dataSize)/float32(dataSize)*100.0), buf.Len()-dataSize) + + ctn2, err := tc.reader(bytes.NewReader(buf.Bytes())) + require.NoError(t, err) + + require.Equal(t, ctn, ctn2) + }) + } +} + +func BenchmarkContainerSerialisation(b *testing.B) { + for _, tc := range []struct { + name string + writer func(ctn Container, w io.Writer) error + reader func(io.Reader) (Container, error) + }{ + {"car", Container.ToCar, FromCar}, + {"carBase64", Container.ToCarBase64, FromCarBase64}, + {"carGzip", Container.ToCarGzip, FromCarGzip}, + {"carGzipBase64", Container.ToCarGzipBase64, FromCarGzipBase64}, + {"cbor", Container.ToCbor, FromCbor}, + {"cborBase64", Container.ToCborBase64, FromCborBase64}, + {"cborGzip", Container.ToCborGzip, FromCborGzip}, + {"cborGzipBase64", Container.ToCborGzipBase64, FromCborGzipBase64}, + {"cborFlate", Container.ToCborFlate, FromCborFlate}, + {"cborFlateBase64", Container.ToCborFlateBase64, FromCborFlateBase64}, + {"cbor2", Container.ToCbor2, FromCbor2}, + } { + ctn := New() + + builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256} + + var dataSize int + + for i := 0; i < 10; i++ { + data := randTokenBytes() + c, err := builder.Sum(data) + require.NoError(b, err) + ctn.AddBytes(c, data) + dataSize += len(data) + } + + buf := bytes.NewBuffer(nil) + _ = tc.writer(ctn, buf) + + b.Run(tc.name+"_write", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + buf := bytes.NewBuffer(nil) + _ = tc.writer(ctn, buf) + } + }) + + b.Run(tc.name+"_read", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, _ = tc.reader(bytes.NewReader(buf.Bytes())) + } + }) + } +} + +func randBytes(n int) []byte { + b := make([]byte, n) + _, _ = rand.Read(b) + return b +} + +func randDID() (crypto.PrivKey, did.DID) { + privKey, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + panic(err) + } + d, err := did.FromPrivKey(privKey) + if err != nil { + panic(err) + } + return privKey, d +} + +func randomString(length int) string { + b := make([]byte, length/2+1) + rand.Read(b) + return fmt.Sprintf("%x", b)[0:length] +} + +func randTokenBytes() []byte { + priv, iss := randDID() + _, aud := randDID() + cmd := command.New("foo", "bar") + pol := policy.Policy{policy.All( + selector.MustParse(".[]"), + policy.GreaterThan(selector.MustParse(".value"), literal.Int(2)), + )} + + opts := []delegation.Option{ + delegation.WithExpiration(time.Now().Add(time.Hour)), + delegation.WithSubject(iss), + } + for i := 0; i < 3; i++ { + opts = append(opts, delegation.WithMeta(randomString(8), randomString(10))) + } + + t, err := delegation.New(priv, aud, cmd, pol, opts...) + if err != nil { + panic(err) + } + b, _, err := t.ToSealed(priv) + if err != nil { + panic(err) + } + return b +} From 60922ced96b54ccedd2e5ebc2248a516874b9353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Wed, 2 Oct 2024 11:56:32 +0200 Subject: [PATCH 4/5] container: split into reader+writer --- pkg/container/container.go | 48 ------- pkg/container/reader.go | 173 ++++++++++++++++++++++ pkg/container/serial_test.go | 189 ++++++++++++++++++++++++ pkg/container/serialization.go | 216 ---------------------------- pkg/container/serialization_test.go | 175 ---------------------- pkg/container/writer.go | 107 ++++++++++++++ pkg/meta/meta.go | 16 +++ 7 files changed, 485 insertions(+), 439 deletions(-) delete mode 100644 pkg/container/container.go create mode 100644 pkg/container/reader.go create mode 100644 pkg/container/serial_test.go delete mode 100644 pkg/container/serialization.go delete mode 100644 pkg/container/serialization_test.go create mode 100644 pkg/container/writer.go diff --git a/pkg/container/container.go b/pkg/container/container.go deleted file mode 100644 index 472b8c5..0000000 --- a/pkg/container/container.go +++ /dev/null @@ -1,48 +0,0 @@ -package container - -import ( - "fmt" - - "github.com/ipfs/go-cid" - - "github.com/ucan-wg/go-ucan/token" - "github.com/ucan-wg/go-ucan/token/delegation" -) - -// TODO: should the invocation being set as root in the car file? - -var ErrNotFound = fmt.Errorf("not found") - -type Container map[cid.Cid][]byte - -func New() Container { - return make(Container) -} - -func (ctn Container) AddBytes(cid cid.Cid, data []byte) { - ctn[cid] = data -} - -func (ctn Container) GetBytes(cid cid.Cid) ([]byte, bool) { - b, ok := ctn[cid] - return b, ok -} - -func (ctn Container) GetToken(cid cid.Cid) (token.Token, error) { - b, ok := ctn[cid] - if !ok { - return nil, ErrNotFound - } - return token.FromDagCbor(b) -} - -func (ctn Container) GetDelegation(cid cid.Cid) (*delegation.Token, error) { - tkn, err := ctn.GetToken(cid) - if err != nil { - return nil, err - } - if tkn, ok := tkn.(*delegation.Token); ok { - return tkn, nil - } - return nil, fmt.Errorf("not a delegation token") -} diff --git a/pkg/container/reader.go b/pkg/container/reader.go new file mode 100644 index 0000000..15f47b5 --- /dev/null +++ b/pkg/container/reader.go @@ -0,0 +1,173 @@ +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" + + "github.com/ucan-wg/go-ucan/token" + "github.com/ucan-wg/go-ucan/token/delegation" + "github.com/ucan-wg/go-ucan/token/invocation" +) + +var ErrNotFound = fmt.Errorf("not found") + +type Reader map[cid.Cid]token.Token + +func (ctn Reader) GetToken(cid cid.Cid) (token.Token, error) { + tkn, ok := ctn[cid] + if !ok { + return nil, ErrNotFound + } + return tkn, nil +} + +func (ctn Reader) GetDelegation(cid cid.Cid) (*delegation.Token, error) { + tkn, err := ctn.GetToken(cid) + if err != nil { + return nil, err + } + if tkn, ok := tkn.(*delegation.Token); ok { + return tkn, nil + } + return nil, fmt.Errorf("not a delegation token") +} + +func (ctn Reader) GetInvocation() (*invocation.Token, error) { + for _, t := range ctn { + if inv, ok := t.(*invocation.Token); ok { + return inv, nil + } + } + return nil, ErrNotFound +} + +func FromCar(r io.Reader) (Reader, error) { + _, it, err := readCar(r) + if err != nil { + return nil, err + } + + ctn := make(Reader) + + for block, err := range it { + if err != nil { + return nil, err + } + + err = ctn.addToken(block.data) + if err != nil { + return nil, err + } + } + + return ctn, nil +} + +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 + } + if n.Kind() != datamodel.Kind_List { + return nil, fmt.Errorf("not a list") + } + + ctn := make(Reader, n.Length()) + + it := n.ListIterator() + for !it.Done() { + _, val, err := it.Next() + if err != nil { + return nil, err + } + data, err := val.AsBytes() + if err != nil { + return nil, err + } + err = ctn.addToken(data) + if err != nil { + return nil, err + } + } + return ctn, nil +} + +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 { + return err + } + ctn[c] = tkn + return nil +} diff --git a/pkg/container/serial_test.go b/pkg/container/serial_test.go new file mode 100644 index 0000000..76e8d74 --- /dev/null +++ b/pkg/container/serial_test.go @@ -0,0 +1,189 @@ +package container + +import ( + "bytes" + "crypto/rand" + "fmt" + "io" + "testing" + "time" + + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/stretchr/testify/require" + + "github.com/ucan-wg/go-ucan/did" + "github.com/ucan-wg/go-ucan/pkg/command" + "github.com/ucan-wg/go-ucan/pkg/policy" + "github.com/ucan-wg/go-ucan/pkg/policy/literal" + "github.com/ucan-wg/go-ucan/pkg/policy/selector" + "github.com/ucan-wg/go-ucan/token/delegation" +) + +func TestContainerRoundTrip(t *testing.T) { + for _, tc := range []struct { + name string + writer func(ctn Writer, w io.Writer) error + reader func(io.Reader) (Reader, error) + }{ + {"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) + var dataSize int + + writer := NewWriter() + + for i := 0; i < 10; i++ { + dlg, c, data := randToken() + writer.AddSealed(c, data) + tokens[c] = dlg + dataSize += len(data) + } + + buf := bytes.NewBuffer(nil) + + err := tc.writer(writer, buf) + require.NoError(t, err) + + t.Logf("data size %d", dataSize) + t.Logf("container overhead: %d%%, %d bytes", int(float32(buf.Len()-dataSize)/float32(dataSize)*100.0), buf.Len()-dataSize) + + reader, err := tc.reader(bytes.NewReader(buf.Bytes())) + require.NoError(t, err) + + for c, dlg := range tokens { + tknRead, err := reader.GetToken(c) + require.NoError(t, err) + + // require.Equal fails as time.Time holds a wall time that is going to be + // different, even if it represents the same event. + // We need to do the following instead. + + dlgRead := tknRead.(*delegation.Token) + require.Equal(t, dlg.Issuer(), dlgRead.Issuer()) + require.Equal(t, dlg.Audience(), dlgRead.Audience()) + require.Equal(t, dlg.Subject(), dlgRead.Subject()) + require.Equal(t, dlg.Command(), dlgRead.Command()) + require.Equal(t, dlg.Policy(), dlgRead.Policy()) + require.Equal(t, dlg.Nonce(), dlgRead.Nonce()) + require.True(t, dlg.Meta().Equals(dlgRead.Meta())) + if dlg.NotBefore() != nil { + // within 1s as the original value gets truncated to seconds when serialized + require.WithinDuration(t, *dlg.NotBefore(), *dlgRead.NotBefore(), time.Second) + } + if dlg.Expiration() != nil { + // within 1s as the original value gets truncated to seconds when serialized + require.WithinDuration(t, *dlg.Expiration(), *dlgRead.Expiration(), time.Second) + } + } + }) + } +} + +func BenchmarkContainerSerialisation(b *testing.B) { + for _, tc := range []struct { + name string + writer func(ctn Writer, w io.Writer) error + reader func(io.Reader) (Reader, error) + }{ + {"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() + + for i := 0; i < 10; i++ { + _, c, data := randToken() + writer.AddSealed(c, data) + } + + buf := bytes.NewBuffer(nil) + _ = tc.writer(writer, buf) + + b.Run(tc.name+"_write", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + buf := bytes.NewBuffer(nil) + _ = tc.writer(writer, buf) + } + }) + + b.Run(tc.name+"_read", func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, _ = tc.reader(bytes.NewReader(buf.Bytes())) + } + }) + } +} + +func randBytes(n int) []byte { + b := make([]byte, n) + _, _ = rand.Read(b) + return b +} + +func randDID() (crypto.PrivKey, did.DID) { + privKey, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + panic(err) + } + d, err := did.FromPrivKey(privKey) + if err != nil { + panic(err) + } + return privKey, d +} + +func randomString(length int) string { + b := make([]byte, length/2+1) + rand.Read(b) + return fmt.Sprintf("%x", b)[0:length] +} + +func randToken() (*delegation.Token, cid.Cid, []byte) { + priv, iss := randDID() + _, aud := randDID() + cmd := command.New("foo", "bar") + pol := policy.Policy{policy.All( + selector.MustParse(".[]"), + policy.GreaterThan(selector.MustParse(".value"), literal.Int(2)), + )} + + opts := []delegation.Option{ + delegation.WithExpiration(time.Now().Add(time.Hour)), + delegation.WithSubject(iss), + } + for i := 0; i < 3; i++ { + opts = append(opts, delegation.WithMeta(randomString(8), randomString(10))) + } + + t, err := delegation.New(priv, aud, cmd, pol, opts...) + if err != nil { + panic(err) + } + b, c, err := t.ToSealed(priv) + if err != nil { + panic(err) + } + return t, c, b +} diff --git a/pkg/container/serialization.go b/pkg/container/serialization.go deleted file mode 100644 index c802891..0000000 --- a/pkg/container/serialization.go +++ /dev/null @@ -1,216 +0,0 @@ -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" - "github.com/ipld/go-ipld-prime/fluent/qp" - "github.com/ipld/go-ipld-prime/node/basicnode" - "github.com/multiformats/go-multihash" -) - -func FromCar(r io.Reader) (Container, error) { - _, it, err := readCar(r) - if err != nil { - return nil, err - } - - c := New() - - for block, err := range it { - if err != nil { - return nil, err - } - c[block.c] = block.data - } - - return c, nil -} - -func (ctn Container) ToCar(w io.Writer) error { - return writeCar(w, nil, func(yield func(carBlock) bool) { - for c, bytes := range ctn { - if !yield(carBlock{c: c, data: bytes}) { - return - } - } - }) -} - -func FromCarBase64(r io.Reader) (Container, error) { - return FromCar(base64.NewDecoder(base64.StdEncoding, r)) -} - -func (ctn Container) ToCarBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCar(w2) -} - -func FromCarGzip(r io.Reader) (Container, error) { - r2, err := gzip.NewReader(r) - if err != nil { - return nil, err - } - defer r2.Close() - return FromCar(r2) -} - -func (ctn Container) ToCarGzip(w io.Writer) error { - w2 := gzip.NewWriter(w) - defer w2.Close() - return ctn.ToCar(w2) -} - -func FromCarGzipBase64(r io.Reader) (Container, error) { - return FromCarGzip(base64.NewDecoder(base64.StdEncoding, r)) -} - -func (ctn Container) ToCarGzipBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCarGzip(w2) -} - -func FromCbor(r io.Reader) (Container, error) { - var raw [][]byte - err := cbor.DecodeReader(r, &raw) - if err != nil { - return nil, err - } - - // TODO: the CID computation will likely be handled in the envelope - // TODO: the envelope should likely be able to deserialize arbitrary types based on the tag value - // TODO: the container should likely expose the decoded token, and have search methods (simple, but also DAG reconstruction, graph path search) - cidBuilder := cid.V1Builder{Codec: cid.DagCBOR, MhType: multihash.SHA2_256} - - ctn := make(Container, len(raw)) - for _, bytes := range raw { - c, err := cidBuilder.Sum(bytes) - if err != nil { - return nil, err - } - ctn[c] = bytes - } - - return ctn, nil -} - -func FromCbor2(r io.Reader) (Container, error) { - n, err := ipld.DecodeStreaming(r, dagcbor.Decode) - if err != nil { - return nil, err - } - if n.Kind() != datamodel.Kind_List { - return nil, fmt.Errorf("not a list") - } - - ctn := make(Container, n.Length()) - cidBuilder := cid.V1Builder{Codec: cid.DagCBOR, MhType: multihash.SHA2_256} - - it := n.ListIterator() - for !it.Done() { - _, val, err := it.Next() - if err != nil { - return nil, err - } - bytes, err := val.AsBytes() - if err != nil { - return nil, err - } - c, err := cidBuilder.Sum(bytes) - if err != nil { - return nil, err - } - ctn.AddBytes(c, bytes) - } - return ctn, nil -} - -func (ctn Container) ToCbor2(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)) - } - }) - if err != nil { - return err - } - return ipld.EncodeStreaming(w, node, dagcbor.Encode) -} - -func (ctn Container) 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 FromCborBase64(r io.Reader) (Container, error) { - return FromCbor(base64.NewDecoder(base64.StdEncoding, r)) -} - -func (ctn Container) ToCborBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCbor(w2) -} - -func FromCborGzip(r io.Reader) (Container, error) { - r2, err := gzip.NewReader(r) - if err != nil { - return nil, err - } - defer r2.Close() - return FromCbor(r2) -} - -func (ctn Container) ToCborGzip(w io.Writer) error { - w2 := gzip.NewWriter(w) - defer w2.Close() - return ctn.ToCbor(w2) -} - -func FromCborGzipBase64(r io.Reader) (Container, error) { - return FromCborGzip(base64.NewDecoder(base64.StdEncoding, r)) -} - -func (ctn Container) ToCborGzipBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCborGzip(w2) -} - -func FromCborFlate(r io.Reader) (Container, error) { - r2 := flate.NewReader(r) - defer r2.Close() - return FromCbor(r2) -} - -func (ctn Container) 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 FromCborFlateBase64(r io.Reader) (Container, error) { - return FromCborFlate(base64.NewDecoder(base64.StdEncoding, r)) -} - -func (ctn Container) ToCborFlateBase64(w io.Writer) error { - w2 := base64.NewEncoder(base64.StdEncoding, w) - defer w2.Close() - return ctn.ToCborFlate(w2) -} diff --git a/pkg/container/serialization_test.go b/pkg/container/serialization_test.go deleted file mode 100644 index 14ac11d..0000000 --- a/pkg/container/serialization_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package container - -import ( - "bytes" - "crypto/rand" - "fmt" - "io" - "testing" - "time" - - "github.com/ipfs/go-cid" - "github.com/libp2p/go-libp2p/core/crypto" - mh "github.com/multiformats/go-multihash" - "github.com/stretchr/testify/require" - - "github.com/ucan-wg/go-ucan/did" - "github.com/ucan-wg/go-ucan/pkg/command" - "github.com/ucan-wg/go-ucan/pkg/policy" - "github.com/ucan-wg/go-ucan/pkg/policy/literal" - "github.com/ucan-wg/go-ucan/pkg/policy/selector" - "github.com/ucan-wg/go-ucan/token/delegation" -) - -func TestContainerRoundTrip(t *testing.T) { - for _, tc := range []struct { - name string - writer func(ctn Container, w io.Writer) error - reader func(io.Reader) (Container, error) - }{ - {"car", Container.ToCar, FromCar}, - {"carBase64", Container.ToCarBase64, FromCarBase64}, - {"carGzip", Container.ToCarGzip, FromCarGzip}, - {"carGzipBase64", Container.ToCarGzipBase64, FromCarGzipBase64}, - {"cbor", Container.ToCbor, FromCbor}, - {"cborBase64", Container.ToCborBase64, FromCborBase64}, - {"cborGzip", Container.ToCborGzip, FromCborGzip}, - {"cborGzipBase64", Container.ToCborGzipBase64, FromCborGzipBase64}, - {"cborFlate", Container.ToCborFlate, FromCborFlate}, - {"cborFlateBase64", Container.ToCborFlateBase64, FromCborFlateBase64}, - {"cbor2", Container.ToCbor2, FromCbor2}, - } { - t.Run(tc.name, func(t *testing.T) { - ctn := New() - - builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256} - - var dataSize int - - for i := 0; i < 10; i++ { - data := randTokenBytes() - c, err := builder.Sum(data) - require.NoError(t, err) - ctn.AddBytes(c, data) - dataSize += len(data) - } - - buf := bytes.NewBuffer(nil) - - err := tc.writer(ctn, buf) - require.NoError(t, err) - - t.Logf("data size %d", dataSize) - t.Logf("container overhead: %d%%, %d bytes", int(float32(buf.Len()-dataSize)/float32(dataSize)*100.0), buf.Len()-dataSize) - - ctn2, err := tc.reader(bytes.NewReader(buf.Bytes())) - require.NoError(t, err) - - require.Equal(t, ctn, ctn2) - }) - } -} - -func BenchmarkContainerSerialisation(b *testing.B) { - for _, tc := range []struct { - name string - writer func(ctn Container, w io.Writer) error - reader func(io.Reader) (Container, error) - }{ - {"car", Container.ToCar, FromCar}, - {"carBase64", Container.ToCarBase64, FromCarBase64}, - {"carGzip", Container.ToCarGzip, FromCarGzip}, - {"carGzipBase64", Container.ToCarGzipBase64, FromCarGzipBase64}, - {"cbor", Container.ToCbor, FromCbor}, - {"cborBase64", Container.ToCborBase64, FromCborBase64}, - {"cborGzip", Container.ToCborGzip, FromCborGzip}, - {"cborGzipBase64", Container.ToCborGzipBase64, FromCborGzipBase64}, - {"cborFlate", Container.ToCborFlate, FromCborFlate}, - {"cborFlateBase64", Container.ToCborFlateBase64, FromCborFlateBase64}, - {"cbor2", Container.ToCbor2, FromCbor2}, - } { - ctn := New() - - builder := cid.V1Builder{Codec: cid.DagCBOR, MhType: mh.SHA2_256} - - var dataSize int - - for i := 0; i < 10; i++ { - data := randTokenBytes() - c, err := builder.Sum(data) - require.NoError(b, err) - ctn.AddBytes(c, data) - dataSize += len(data) - } - - buf := bytes.NewBuffer(nil) - _ = tc.writer(ctn, buf) - - b.Run(tc.name+"_write", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - buf := bytes.NewBuffer(nil) - _ = tc.writer(ctn, buf) - } - }) - - b.Run(tc.name+"_read", func(b *testing.B) { - b.ReportAllocs() - for i := 0; i < b.N; i++ { - _, _ = tc.reader(bytes.NewReader(buf.Bytes())) - } - }) - } -} - -func randBytes(n int) []byte { - b := make([]byte, n) - _, _ = rand.Read(b) - return b -} - -func randDID() (crypto.PrivKey, did.DID) { - privKey, _, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - panic(err) - } - d, err := did.FromPrivKey(privKey) - if err != nil { - panic(err) - } - return privKey, d -} - -func randomString(length int) string { - b := make([]byte, length/2+1) - rand.Read(b) - return fmt.Sprintf("%x", b)[0:length] -} - -func randTokenBytes() []byte { - priv, iss := randDID() - _, aud := randDID() - cmd := command.New("foo", "bar") - pol := policy.Policy{policy.All( - selector.MustParse(".[]"), - policy.GreaterThan(selector.MustParse(".value"), literal.Int(2)), - )} - - opts := []delegation.Option{ - delegation.WithExpiration(time.Now().Add(time.Hour)), - delegation.WithSubject(iss), - } - for i := 0; i < 3; i++ { - opts = append(opts, delegation.WithMeta(randomString(8), randomString(10))) - } - - t, err := delegation.New(priv, aud, cmd, pol, opts...) - if err != nil { - panic(err) - } - b, _, err := t.ToSealed(priv) - if err != nil { - panic(err) - } - return b -} diff --git a/pkg/container/writer.go b/pkg/container/writer.go new file mode 100644 index 0000000..28a9dc1 --- /dev/null +++ b/pkg/container/writer.go @@ -0,0 +1,107 @@ +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" + "github.com/ipld/go-ipld-prime/fluent/qp" + "github.com/ipld/go-ipld-prime/node/basicnode" +) + +type Writer map[cid.Cid][]byte + +func NewWriter() Writer { + return make(Writer) +} + +func (ctn Writer) AddSealed(cid cid.Cid, data []byte) { + ctn[cid] = data +} + +func (ctn Writer) ToCar(w io.Writer) error { + return writeCar(w, nil, func(yield func(carBlock) bool) { + for c, bytes := range ctn { + if !yield(carBlock{c: c, data: bytes}) { + return + } + } + }) +} + +func (ctn Writer) ToCarBase64(w io.Writer) error { + w2 := base64.NewEncoder(base64.StdEncoding, w) + defer w2.Close() + 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 { + node, err := qp.BuildList(basicnode.Prototype.Any, int64(len(ctn)), func(la datamodel.ListAssembler) { + for _, bytes := range ctn { + qp.ListEntry(la, qp.Bytes(bytes)) + } + }) + if err != nil { + return err + } + 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) +} diff --git a/pkg/meta/meta.go b/pkg/meta/meta.go index 9dd8dbb..f3ea126 100644 --- a/pkg/meta/meta.go +++ b/pkg/meta/meta.go @@ -123,6 +123,22 @@ func (m *Meta) Add(key string, val any) error { return nil } +// Equals tells if two Meta hold the same key/values. +func (m *Meta) Equals(other *Meta) bool { + if len(m.Keys) != len(other.Keys) { + return false + } + if len(m.Values) != len(other.Values) { + return false + } + for _, key := range m.Keys { + if !ipld.DeepEqual(m.Values[key], other.Values[key]) { + return false + } + } + return true +} + func fqtn(val any) string { var name string 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 5/5] 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 zcmeIb2UJsO*EX!9f{ql$5u_`iC{;jui3);Z_qJaO6&fFB+~!>Q zMMQR?Hl0CVAJz4S8z48S{ghg0Eq;9%>jlQfr1>wb)XoNCiSsk)1~upkH)3bU=P>qfYMP5eI{SDvhzw$>(SO#M2C*wjbC#lSxR=J(2;X_P0bsXwkf&p7y-SOWKo)4w$Udm`0B4K72UC)8KL}UtS;Zgvf55= zrg)@J)^7pq@FYjyOwT`P)JhVlLaHCi^KUe6^!bI1Mc`cu)X#lsb|Pmt^O2ADTL2Nu|O2-28g z<0^onA|5S*<6feerIWnTRM!D_YevG>lkouR3aWV%|^44U8QLg-e-n1J? zh*l1_rDXr$xxxGt&)NPfQOPGJC%sXOm@oFBXuwy%vm-Cjnpj`TI^4)fuG(gUm~;9k!lTY`#w19(P!c zem^kpfVqEUM(jhm_5`yZZR{O`Y3Iz|!N$ul58Rah?I@M_*F+T6H!k14_+zLavI0=~ z0}MY5=Z9wiyy*`wy0umO*d~76R)2uu2N?eU9be&I*rw_e-a;{nI~-pp|8|&i0zo(@ z$oIk0gA@VSahYtUX}P=|afUhWW2KO`?Fu*Ae>)`i;?ZJZf;DG1-d$qXczUSs$a@D7 zrSvQEH@w7{EzKJFZU!5cau#xK<1Ls1jy!Cb%pD+Hf6s1t1U8<{EO;UObB47%M{4IQ zo&uG)9SBJ)w%2uereQ{Ve~WwjX5Sxr`&HPhy>=PNv!}!MI;&Ay>s@U86$^0wuD4A2 zd36rkfqNZphVKL(L=NBn^=@~a{b+s+5HR=M?91f?0_(oDQqygYuk&~cwkDUy)Oa4a zIl1%4!~S0o<8l(X!Z%h<`yTsIKw5?0Ih}Xa0Hgqz_RXzaFnlLM5;*-+ z>_2}>!{jmpN$i!@ckg*aWaO37WjFxy&tv+{bb!s`?U$h~%>c!eZUY|v`-H+{0DZ`( z%bY$zNw~&N9Xt5q>4PvuHY*2L4J#2K5e4j3xQ-kSm?_)qyI+Q`Dcd^z)oOp6&>`VE zrhEqtt2%}>cq89?B#Od+e&pC&o5;(0B%D2-U>IcD!!XLz6=f6^6y~yZ9*rt z@39*7!5X){oCE8tF9jPvy2>dvsuZ3JJU(VjGZc_v#7@AWG36`2W%_OCL0RDRPu z6&XN!{@c){5MYs8p6mAs{R^E>kwMC9Zvn4&!KA`>;^dY;{TkeWcl-^rPz7PXIX*ttCu<^5 zJ6DbL?{r3zkH%*CjWSP8ghT$>lyW9L5_VopkJYbMI@{*|NoW;{IaU`F(7 zVk?5Ro0~@rp6tLbYB1`cpDo-!M4v%o20~>Ey^s5^vT&F7R=IE9$IXCjvcB7-dMRV_ z=bi;lnk02o%goCRqsVNQa?W^gyv5ofZV+i$&d?cWb;4vNE2yQnL9j%i_PYUlCXL%saxTMCr%ck3^Iv+wDM)!&sq?N_5()$;!Z+AzH9PgQ;nnMQy9qa3-~M&Zf- zFXhPYC@+oh(raeVbFVA19idmZa!$*AL}SDNCs|x4rf}muIeg&eLEfv6Si?6K#mrJW zA2Foz0q3&y%agZ*4IN)UUir6^?OtNKdA}}f`MA>Rsh0cKv@a~W;6)C^!sl#)nlL|a zx!eDdfd*e^mX1mC;XjUHSG^#REI%zBD51Del~oWp*dr^s+>|^;?FxGS-Dt>C^=)}W zA%xV&$MQ=DYG;?7YN4?6N%Kn8=7uK?Jf&M{|0C+Z<`QiY;1%mUQq}Szo#J9*-8IOd z?c#;hH@h(0rOqy`X~u*>qC! zOVX9D^xuH#Rjx+F`vnbL=vkR=W>QC;z+Nh(^;}GHoroj84On6DACPlNpe0ypX_VV3 z&Xf(@Mh@H_frQr0wswf(rCi#=ppY`^N|14E#1vHj-uK4!QMA2gU4CuxK{RVt6RJ2U z0h=;S?W%X5bHJQuY@cnNG3ZntJcZdi?IbdShCQoMnqKU)vwxC}OK)Xfycj=ITGBtK zGg%?85H0sCLW!e~&61YzWRZq%TMu$hI^x2hv5+s|;Yi9N=oyKWe60DzY{3apwf>pw ziA+G+`Ksxi;n?qa=jg!S%t?Nodq*44|2E0RM!L^4&o5q;R}XmTcyjKh@=QQ5BrFUZ zTjpVeF(YCM1DZ{9G>*!NK9l5?T9Z^JtQJDvL(1a97FDZh{0IZfc<{X1Wq%3cu9@<8 zuDIzAd)g z))hA0a;zSHoV_EDb}jZIk57#wdTO7^txuOtmi3^R4p6P}s1q&dv^D$B^q6G$Fw>M9j1bZB}$ z;(Xs`yN}9wjGlqUC`yf7FdASeB#mwww8z4af@iDq`24XHC*~5I%kc34HdF0&D$P2{ zVs;beLnbB}l+i4bhq0uS*(_=e*7LV5Ymk!cakj*b>klrYlSY3|}d&$M}bxG-J zJXLoHq>sv8!=tsQgBTYpC+=)Vwr%%meq(A(x@6sk@fa0PIZEQIsgYQ#bwl2obf3NiM`WK_-G7ufvAhy7NGC(d6ItdTME&%ev6v0PWI%h@rPY1 zatsic@LY0;Pmmtas*>zCj^{mfp2@3XxH}LswtcS>bxhT=Tc`)`rzOQ$-^X3ibcv|% zG%Tu!S->nFMmwjB&=tL)1{D08LvLPCfa%rS>|kj{9t zRm}KY?0WED)eJ?2KWc5?k^=WyG2R*dV(&*1;~ufKQl3q&w;oW*X}#v;a-$Cw;A&{H zQUN7ol_oqHQ5l6Kdo1y&PD9^u`Y$=Cf1pkAb_a~4Kc0ck_toW3L@iQLEH~U;$R4wT z256@sZfc(&e)k7@%Y5LxlFbEkRRL0;n9o;OQt5|haUXAn_gs*C1L>W)Od=)w2+~_-`R8H5W zWZL-7O8=;XFPpNhCdt`J?u=WSkjxU%4w?){I|6(nGr`=Dt(Fp8hFDIPpHaa%jhzMz zQ*_=UeenoyI^AxFYo)vfq|bJ!+Zg3GUrm>{gj|k#kpK4g;$BVhR`Kj_R0stqTxBnk zk0tr8Ga)|-(I9BXtmpB~4Q*U0NeDR*pU|2rh(D<2D~}e#!UA^9;B2EE1L}GT8T~eX zl%gK%oYIHQ&kq_!6PSy{%=q0hYhFJuPgP;?A)Mv8Vx`OI0sSLnQR1|*O)2Bm<363% z&=u5kJ%UKy>2EWBdkMQ`rT`PFF>Z_QWp3{{oIO*GC)X7*cNVv?3Sub{T1 z;&-bf_esQ=Yt ze{EIOVqH2l#9Nz|_sodP%sk$dEbcx=h-ztyK@YgzJ%v6#9atGM=jud}9)1?p!5=1h zEKIWBBK}ZK(Hx98Pi%ytt*h5D)j&|%;qSb#=y(wzKc4M{j0;t`a{u?H$~QTB2;-ff zoh|1QCikV^A z(&P#En^YJbjUro^wcwPxw>RN`*p&Dp6()8y4?BNtc$K~nxwR7?9X}{tjiPws{0a|R zk39xIIcPk3W4)TXC#id#%NCO#q;#Ro(g`3Tx|(pG^tHgPOhFN$L31`#ZO9zjy)a{nO- z45G?Ddl1PBwOPi9WcA6gFex#;2x@$)D`xLiiq^y=)F=8`e)@5PHrm{%CmEwbgTz@i zV&?jVJ6EGX@%A30Pm-1O*G(K=@sUYM#5%)F$Z||h^L^#%Y}^DP@zw|zeChLW*Vpmm zeaS_Pys8usKn~N<>99*sEKgdsO)Eb$OEiS7LNgmkvPKkRWTZRy{1H8Jkh2s1p(XdK zUJ`6B!~<321@Fw7p7s9AB{i_RW8F^0DCF?-GqSJh3GoZ!JJ{{i8&1_q`J^se;M{9t zkp2F%n9bQj2|Y;#t;mfb7C*nXM&!n;FhZ%aZF+X7`#Mvs*gYn2Cc5ewBU9v z0P}kY2}iH9&s(g}C}vT2{|F!F6RZ~xV>@WX*O5{4p1~JWR&@Bb`iuz=!p7b~{)e5c z1lr!|jI=Av&-#Vi^Aj-Gcs?QK(d8>cIRuT(cEv1G6)4V@Ysu-p;7CQjgtDs-c|M;X zd>=$J!j-tpkI7#fMZ24sz$SB7MwgS<6qVi2kMT=WpW4pR8C@Q{E(L=un7O%6-`$bLfR~e1fgtN2SeVJ!UE6pyzfJ#cj}1mE z9(2&&Zx)N3=&mPxP#v|W>}Qiqr|QAo#-7RAP;-d=5HnqpJTN^6#>x~sA$>Yf(`ZiS zG%9GC#om9@(DV%-b5m~zj2d&9> z^IMH{hL20P74X|F#2+ZTaV4JnO>#kL9d>dFuP#we?QHFKdEZ4W*(2DhIStn|n#UW& z3#yz&`G4x1tY{Bt{gf}-3Ch==PM_#oUuocsm0sr-nO&eBAg_p*m>S%QYIe(ydU{|w z@JvE4Dt~#+O|;ot_+fK25PQFmQ;1fV_C2pr5NK>Ql*3d0-^0(0`RXH?|3KGSBlwMA z%~nzAeU#S3e_$qj%O3n|G`k#ZeEU0FA)71!#iHRy|C#4UE96Hjo$O4S$n=t@xYRVt*wg;W{kl4;_39QR}a? zc4!aE@()ye3z_aOadduZ4fzL7zlF#4SIE}Bhe-Ita=wK^_LsKC0ju4jzkadh|4j4S zZ(8BIa>EelP<&w#{x?7J4N%xU57svVdL2Seep71E9g&+{M*3x z6{Y+?*wnYd?JLUi7X|&fSNs9EAAtMMPW%Vpz7C}R_jouC!5Y(Jn9PJgW1~gfB?Ywg zlT)3PJ22|fQDWK}lO7rs2${*qoQ$4*7R&uIuuc0vZkB(`f9d)H-Br&BRlED)!!!|P zSK7jgU`_VuQD#3@D>!HfU$#)9}I znb|J!{}gciy=&9^;c7rSLUaqwJqplLV73>_Ql#TbZ?by`S& zu;-uK77dkrql*eldm-gFbS-NE`rYla`gtOHXAAZD&jav0{g=O83QqX-#U1)W z)G@-Bw`c4I`6_R{%40(09lPbP-zbIt^=10Gr_fT0i`7YUt6@29Xk^C>a-(imE()}- zwGNCWE@8{~s9us$zZSsNC-;sd#LdGO5R0~aAm6x7M?dU33Gzi>2OmNL(6ojKJNK`!QFC%xS@`OdUQF0x>N&dX~^AJ7W?oB0c8c35XPWo zd^W8f#tTCA#*E}S3T?zXlTd}ZgGiMi)f(6KVBer&21Y|9Y2tdlZ3`#s%BIRu;4htI z?cp=iNC^6%b?F-0Q!{b$bElkQf!*!I&9&;5)_R|4&8R_enYo+WOyyJ^F+{g7z$Lrb z66+0XkH3q+A?@JHLgdy*!GxkH2S(@zA;HKY@I#gXZ7F}Gf1l(cSW>mfKauKX69(&E z-i*{(R8jUJEjGWDzV0Ha^m3dT;cg%Av!Hage*vedptg2}{0qo@zZm6o;#!{CDk)(I z9_p{!LufY^jFC}Y5W}KI=$02TlR?cUW@`!Wbp*uO;j$#@>>RQ>dHP^e>-K;^uzuAV zq0FGmaNUdbBeZN^#2Xu~(-1KB!O6AFv@Fu6e2DvO#%yMYe%zIOM{zDSnR6N&Ll4}$ zUD7*Oa*4at_6{k0*5^AG=RCLRH@thc%c(7Xxrrr#wG*bFtPyxsid+3+KOPFk6>J|h@%#)V z51)b7-FmA9WaD)NWYyR>MnfGN9ZX;HpVchHS#fd^M~epy``{OJiPw5bvIe#;b$sj$M+c~o)kD*jb60vZ7{OffdX?6Co$g^g1KA?z(l zX6p$8P=0Clz|VkU#Spm0KnvUE*c_L`;2T-h1%cNKp&f!CQS5@8x&OL=nAzN$6361! z%Q#|N(D|W+z@x`jB?iWqiisQ0py)-ZA)S6`fWwr1aYP4J83m)SfTQ~&3qH<@ z5yuTPUoJ{1o}X5)AY=wiGS~aJC?sIncC{1h#8EbWdDS+&Brm6Ul0YSxPJVj`XOpCX zq!*`AY?@Qp8E1;Bs61qJjz;s!%n(n8ZJiD6CCOj3g(h7aN4WgyIzTb)3+8rFKSCOX zqt({N4!RG@18@29agJLoB(YXf$w@*b0?~{Sn`=1FxN#({lJV5QeZ-ZObUN|a0eEq~ zqX#vZA3RnY9pShDn$7}j9|K3;MoUh%Vc>_spasDde+_;7)vXam&5sjOO ziZP5IFmF^FA|FhZG@x2%v4Ct~L)b3sdaR@Jso~kjV8x+L!7>B$lZGzovVy53UdXthbUF9Jn4+4+R-GT%cf^Jq4?(!vnJ?B%@~xT9i|w zqU#ySYvTS5SVxmn-LqA%5h?RZu(d@=VUmgw3O!@v-aTQ$kh>*d7|5w)SjTR8&Tf;W zj9hl0v66bTHQU>up=XIhnd&Jfk~98 z)YB`0K5@L$6u+zdyvFIJrh;!u2bFnomz6gnqd3qVO9x79(c(V*)fp09P)X& zuFTihwUOwO>>~kaHJT+QGpK(;w8bVR?Jy~5fJb4)8yAH0ntYS9EUu7DsO18GUaeBV z3{40|+s4vA72$L=Yu4!HE!ANpr_4E%Rd=8kbnfG~8>{8a$ z##qV9#>}#hh$JwmKUc1Wl8ErfU06rmv1HndRsNcq)j5+0tQVbe{?#pV6%N#_w{ca} z_7)mxXZrrxF8y;r^Krio$UU{7Y|@zU5nv;i-@*jA_kGeJt`!T4(4}#^?y?X5%+HpL zj|tG{mDB`cFamZXlDgTaY>!99x%Jdpx zBC4p6c~)^WxAx9v&+8J=@WKUbds*@8wZWN^!*TwcN(TW#=>t1IWBMEXJ`>m{XLmx+ zJY!~%*i}mm9v3DwG!ap@m#yl6dGoO)gA?$J05cVhb0a1sXoB9`RZ;B`FRg=1M7^mO zGYla;u>x&W$@%%~L{S^*`|B?B3Il-(`b`t7O|vSqkje$sdh1X02^CZ#SPe{HwKPmSN%GgX?*a69$N1sSx zx}9%&gH&sD;I6v!LA|c5{VcHF4JDgckgzPsq*zM$(sdn`hQB^!H2TZkVdP*@*l%S9N(uG>-PZ#R_yI6 zwSYb!>xReB<^-KU<04;r;b%3w>64WG%Fca9tx0$vxHudjGE8a9-W-0tnXf#eSJ>bZSD)T`NKF>z1qlG=3b_@q?=7Nx2%%wWL>F$-0KKl}e zUQMWK4Ken?f6>wBBvu*CbI)Gq2l;yOYs97a%u3^_PV;DFc58zfTu8O3TL(2j+l$<| zKxrNra&B3FelB~MvV(i`!7U=qZBc4z_LK%~b{t9kP(Mlk876vT!)wHVzSMt@4tlja zjy@Ij!14A$Wxm5Gn^{Z&SCDYEj|NO~>4Q8o^$K6*?%JY0|3;O#Ms`b!kYj#R!_pWI zOn7tz*4${bu&N|=vnf>e<;Bd~+Gj|Dm^s6KVUc4?Y<*{ zHmqZ<$GQ+K5l~?c zf2WXEo0I|(46CI9+lJG^r2^g2pgAVx#fAfuZN;RP{GPz}{)7jDHbZP+FwbFC#?<^S z_zq3KwkIUIyna#jf`XsJg0!jQ8$eKpfhf|6bM>@c&L+Cv@s>-E@hxHKB(~Homkw3E zMh|@7fgF4^Pk3Ix9^cOFl`snB7Yj-~g~2)=nG3<;1cOAbT`TK=U!r?9Y$C6tk03u2 z)gi?P*PrrQx&#I0GpbZrfs8{;Z|v^LsLyn^lChyx54JBcc+3W6k(cUKsIV8r*Opm@ zaO!DTft19AwAAv0%AXVJLnhlKDSA<*kqIFhYx2B057c{(tGQcc6J8c>P2g5J4|H~c?y*!N z1V>%kOK6*jjO#(bE{`S}wga-W17xS%#(qDN-Eht)vE6rePbF!cLda!Cyy_oXWu;dc z@vMwL4}Od)D`^rG&X*{z4EHNrkE7wCqU;&WLlhXT`Smq!Fsp9L!xg z6h&z3VS6GOPr1i3u#i9;&glyP-~kx8VX*&U5&WLBZP7vC(rOmLnkvVNeih_UpLA*9 zg<>(69>s-OQ@4ToGx|2QV(c^;K_9*1l3n9I^joCZNr}Cf+D#7-s%9UtXw>LghTwbB zpLi$;9tmN{(?sj5-X#|f-zqz>f{G<35D_^+!T~J2LU<}c&I2@$Tm5_kcWVZYY+9uG zNU3-MjV;40pki@}p`oK-=>#TE45i^GwpJgpQDu~-t-{ylJ85lVyC7}u9Ixm+plQU7 z3g+`)-Hz;g9H!T~pSeZQ5|&L9rAcetP#E#^!Fe}aAoi7TpjC%LTM;-W)i$Ad#NutF zUHNw68dyyg?;`Rl(CIU)D(T6k#+sTjA7_41HjuAjoOZxr*y`;3OT4pUebi5hM-js? zBwuA`e4Jkjs>>3q{hSyQTL2T9gKh@i=W!cELa;ix!fP?8h^p;_R3UD{x$?z}kYK+zK`Tvx#J6kA7@jave0yh5RnL)Pphy{HHM26G z^70z|7>|9sLia82Y&9Q(lq_rw(SpL`FDaN7RkLigwz%U1+E*;`U7+Z|e*WXU>8m$~ zd?2d&X+X#jw-JTb&-@IOOFBz~E@V(nEu6NIoy7O6D|Yc%1pbmyQQ+pp zD;fj?Os`+<2K{7iuA3$H=U`}ARmcwNR20|bT3P+O!?^KxAw#2U(YXh#+Z6Jf%i(4e z=jzl`{mD+L^^VZ?Fs>G3Z9WN~QkwP(C)stFE^GZ(!M!VXKK+nOKp^^!=TS@J91PIj zby!Y^r)dkT?aRhwp+^oUSb8Q6uQm@k;oB2g)*hh#YdNa+xj_(+J((J=CKrAjzqu7V zt?OSRF+}yksa12twRyr@@G-hd!$ZrG2+u?(+s|vNx{F=Ln92U+C;=5i?LuUs`BK9# zOfF>258^AUepJll6L+05LLQIHTiuQBSb|jB=mFGlu3qd~a>%gssj@I?O$9 zxGn#xIpR^GmPCx*`{zQ(H1e)`UAWYncqM5d3zeVS@%)w6g!oG>ScA^&UMHs)*JNIu zi4nW9{mPYBH+O1vo%b_ehhqYtV}u_0RtCgVXl-+XbKnktn@-Y#GJ3_#n$;rPr)a+) zZ}6DR{40rV2jsb#q`g9iJ1?h%PjSIc&{N`!^POAHob=7r9e_XN5rw!kjFnjk#8sH(6*XAUKXBYKd#e`l z;l1D>Ux`qNNtmqpjeagkGo`x4%$pf$M2i4k=pV{BKAk>li zNZU1l-!ff%FW4|+t{=DKQ5f!FkcAjW*2gD&JA)H=?$6u4vS-x4kFeTbGnVBwlNlL0 z*M;vrBvgLK{?NfNkb^ywl~MD_{9#42wR(lMp5*cTnu~4Ix{-J4FsP@7r*E&x^%mvr zanw9sRog32^(<^@qvANB;UzW2A=eO+Q^0AukpXBveEZ46aAB;XvV<~Nty}P#i#-oW`=#tG)@kT(zj?97s2}M4AVg09$UN^9Q zwlQ{ICcWgWhuwBzjYyM}S8KxK_7t1^g)Aq{hM^;gH46ndFlCeH57o@&c8DFW+vI*+ zP_rcago7i-$c|iU>IRqjX$P0kvU8uNID==gl2q4yiV(@V=Ya_p(rNf^e)2%`E3)7j z8>F;Evi){pg-BfXl@*+txdr#bpU65QVOda(gmtLR8S5B~9+Em^ws<_t*h}Pmf`zqJuHUr77 zt9uXKa%)py)!a@b5*Awr$1$E!6dT=}ESBD))(4}TMJAoNxBH;UN`>U;1E~7D}N8Up-JUDdHZ9c6URZt*B-YOeNjF)+@|7XVQzSdJrQ+! z{6dD?_vp9Q4Jvx=9?84$SpL#Y!Oe`?Q9%u-ktL%y5TSqyTM5(B597wEZ=ac1yce9( zy>y53WOAJhG@$G`p#?hwG$iP+xq&A} zyOVBSO-Rp}P?c$p#vZ?s-~|3`s~(@pM7YAIb@tYhPz<-L7sat{BsQ{P7vkN^Qb8O3 z=6J(_?Qwp~iQV-(th^`BqU1t(Lf;E^hFbOaiy={3iE6Mu-l|9Uo5s$)5PM%Zrv>Xq zNOOvS?sVO_e=VlYH7G;Aiak&;%((DOFI9JGabS<;i;m-Ysh`NNH!|InY*HR>=gtp# zH&l33CGt_jCO3;kmOYE5$g!DCrk$mfqcz}^hZ{Qc*TXB)%h<2%KXCH)`Q42dP3}3h zkk#bV?!T28`b8iF=SQ*H-%rl5%h-D^wKV0Y7$zCtm{%f`g5-U0slqYFG~>9~{3ERf z87Q>%q!|?00vhvxAm zSn1RciT=`KOJm!imO3^Vz{ECMFqRl7Wx!rCwY28W98M>$AIR4Z-Pt&H?)FLZ8xK($ zJ#LecGxDbQCdsu+XE6eaLhN7_mp0}0%>WKfLR{bO)wBmYXDfF#R_i`uao5Zr-5Y)V zoy?FDD|^X9%6s4D-gATXW9NjTT|Gulzu~RL!2C(|PY?Reu7y4_<$27eZ<+XJ=5U$Q zV3dc6vRX>WeK$p^olZ@2MQ*(hi#HD0ctaz`4qcPh+j9=bSJHX!Ry^OfV6NQ!Im&er zSlS~!QLAE4GZlfUrU??FHaIb#aQgios!RoFGhk+a6_G{2^(W!Ghn`Ho&2QhPW!s$6 zb0~UK6#Qvgq{O{={~?=}?I(R>Oj})*rC2ug5pU5xg5h}gk(w-Dr#{|KJZ|q`-cMzM z_BK9P{5YPL75SJ?Brrg;e+9vZ0~a>5ExBqHsN5F^{W3N-+2KlLsh{$MvRcg?)nZ*b z)1Wwv>pR3!GPw=VC4XE(=Dsm?Ze|xu=R$mR2_5U|=cm@cfDe6NS9{WVnl!AYmv>yx zvd@>m`Dc-He! zS>+>e<@tU6OMO-R!>fxEujYo2Ptdg5`pfSz9%Ej?U@4#9pVVWE+PYifZH7U;@|B+Ds!GkcUPtYcYT@Am6og7}(3Ed-zEl!!AG=*P;}#JdK1ZS$O1zc=lxvG<{g zyB&*V)(hlC%#(XP(jTNfMSfCOKY3C%DP=}?TkFRtXtR9CF81&n9-O3$W(NcvqN{+Wx&tPY{#7b$y5 zM-=z~;T@`Z^vEHI=S14 zM`Z!q63Tnp3~PVI(zfp{{bM& 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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