diff --git a/core/file.go b/core/file.go index 9096e55..8fe220d 100644 --- a/core/file.go +++ b/core/file.go @@ -1,9 +1,11 @@ package core import ( - "errors" "io" "os" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" ) var ( @@ -74,6 +76,24 @@ func Open(name string) (*File, error) { }, nil } +// MerkleRoot returns the merkle root hash of a file on disk +func MerkleRoot(filename string) (common.Hash, error) { + file, err := Open(filename) + if err != nil { + return common.Hash{}, errors.WithMessage(err, "failed to open file") + } + defer file.Close() + + // Generate the Merkle tree from the file content + tree, err := MerkleTree(file) + if err != nil { + return common.Hash{}, errors.WithMessage(err, "failed to create merkle tree") + } + + // Return the root hash of the Merkle tree + return tree.Root(), nil +} + func (file *File) Close() error { return file.underlying.Close() } diff --git a/go.mod b/go.mod index c9522c1..106534f 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ require ( github.com/gin-contrib/cors v1.7.2 github.com/gin-gonic/gin v1.10.0 github.com/go-playground/validator/v10 v10.22.0 + github.com/google/btree v1.1.2 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/ipfs/go-unixfsnode v1.9.0 github.com/openweb3/go-rpc-provider v0.3.3 github.com/openweb3/web3go v0.2.9 github.com/pkg/errors v0.9.1 @@ -24,7 +24,6 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/andybalholm/brotli v1.0.5 // indirect - github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd v0.24.0 // indirect @@ -76,13 +75,6 @@ require ( github.com/holiman/uint256 v1.3.0 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/ipfs/go-bitfield v1.1.0 // indirect - github.com/ipfs/go-cid v0.4.1 // indirect - github.com/ipfs/go-ipfs-chunker v0.0.5 // indirect - github.com/ipfs/go-log v1.0.5 // indirect - github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/ipld/go-codec-dagpb v1.6.0 // indirect - github.com/ipld/go-ipld-prime v0.21.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.9 // indirect @@ -90,27 +82,17 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mcuadros/go-defaults v1.2.0 // indirect - github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.9.0 // indirect - github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-varint v0.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openweb3/go-ethereum-hdwallet v0.1.0 // indirect github.com/openweb3/go-sdk-common v0.0.0-20240627072707-f78f0155ab34 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect @@ -124,7 +106,6 @@ require ( github.com/rs/cors v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/status-im/keycard-go v0.2.0 // indirect github.com/supranational/blst v0.3.11 // indirect @@ -137,12 +118,7 @@ require ( github.com/urfave/cli/v2 v2.25.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.40.0 // indirect - github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/goleak v1.1.12 // indirect - go.uber.org/multierr v1.9.0 // indirect - go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect @@ -154,6 +130,5 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.3.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 314505b..4ff71d5 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -13,9 +12,6 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= @@ -109,8 +105,6 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -129,10 +123,6 @@ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -148,7 +138,6 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= @@ -163,6 +152,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -171,19 +162,14 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= -github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= @@ -197,73 +183,13 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= -github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= -github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA= -github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= -github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= -github.com/ipfs/go-block-format v0.1.1 h1:129vSO3zwbsYADcyQWcOYiuCpAqt462SFfqFHdFJhhI= -github.com/ipfs/go-block-format v0.1.1/go.mod h1:+McEIT+g52p+zz5xGAABGSOKrzmrdX97bc0USBdWPUs= -github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY= -github.com/ipfs/go-blockservice v0.5.0/go.mod h1:W6brZ5k20AehbmERplmERn8o2Ni3ZZubvAxaIUeaT6w= -github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= -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-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= -github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= -github.com/ipfs/go-ipfs-blockstore v1.2.0 h1:n3WTeJ4LdICWs/0VSfjHrlqpPpl6MZ+ySd3j8qz0ykw= -github.com/ipfs/go-ipfs-blockstore v1.2.0/go.mod h1:eh8eTFLiINYNSNawfZOC7HOxNTxpB1PFuA5E1m/7exE= -github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8= -github.com/ipfs/go-ipfs-chunker v0.0.5/go.mod h1:jhgdF8vxRHycr00k13FM8Y0E+6BoalYeobXmUyTreP8= -github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q= -github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0 h1:8lMSJmKogZYNo2jjhUs0izT+dck05pqUw4mWNW9Pw6Y= -github.com/ipfs/go-ipfs-exchange-interface v0.2.0/go.mod h1:z6+RhJuDQbqKguVyslSOuVDhqF9JtTrO3eptSAiW2/Y= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA= -github.com/ipfs/go-ipfs-exchange-offline v0.3.0/go.mod h1:MOdJ9DChbb5u37M1IcbrRB02e++Z7521fMxqCNRrz9s= -github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= -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.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0= -github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= -github.com/ipfs/go-ipld-format v0.4.0 h1:yqJSaJftjmjc9jEOFYlpkwOLVKv68OD27jFLlSghBlQ= -github.com/ipfs/go-ipld-format v0.4.0/go.mod h1:co/SdBE8h99968X0hViiw1MNlh6fvxxnHpvVLnH7jSM= -github.com/ipfs/go-ipld-legacy v0.1.1 h1:BvD8PEuqwBHLTKqlGFTHSwrwFOMkVESEvwIYwR2cdcc= -github.com/ipfs/go-ipld-legacy v0.1.1/go.mod h1:8AyKFCjgRPsQFf15ZQgDB8Din4DML/fOmKZkkFkrIEg= -github.com/ipfs/go-libipfs v0.6.0 h1:3FuckAJEm+zdHbHbf6lAyk0QUzc45LsFcGw102oBCZM= -github.com/ipfs/go-libipfs v0.6.0/go.mod h1:UjjDIuehp2GzlNP0HEr5I9GfFT7zWgst+YfpUEIThtw= -github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= -github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= -github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= -github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/ipfs/go-merkledag v0.10.0 h1:IUQhj/kzTZfam4e+LnaEpoiZ9vZF6ldimVlby+6OXL4= -github.com/ipfs/go-merkledag v0.10.0/go.mod h1:zkVav8KiYlmbzUzNM6kENzkdP5+qR7+2mCwxkQ6GIj8= -github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg= -github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY= -github.com/ipfs/go-unixfs v0.4.4 h1:D/dLBOJgny5ZLIur2vIXVQVW0EyDHdOMBDEhgHrt6rY= -github.com/ipfs/go-unixfs v0.4.4/go.mod h1:TSG7G1UuT+l4pNj91raXAPkX0BhJi3jST1FDTfQ5QyM= -github.com/ipfs/go-unixfsnode v1.9.0 h1:ubEhQhr22sPAKO2DNsyVBW7YB/zA8Zkif25aBvz8rc8= -github.com/ipfs/go-unixfsnode v1.9.0/go.mod h1:HxRu9HYHOjK6HUqFBAi++7DVoWAHn0o4v/nZ/VA+0g8= -github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= -github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU= -github.com/ipld/go-car/v2 v2.8.0 h1:8tUI+VM1mAQ2Qa7ScK++lfyuZYcGQ70bZ6NpGOcJj5o= -github.com/ipld/go-car/v2 v2.8.0/go.mod h1:a+BnAxUqgr7wcWxW/lI6ctyEQ2v9gjBChPytwFMp2f4= -github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc= -github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= -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/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= -github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= @@ -274,7 +200,6 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -287,14 +212,8 @@ github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -303,10 +222,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= -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/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -319,24 +234,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -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.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= -github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= -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.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= -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.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= -github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -356,9 +253,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openweb3/go-ethereum-hdwallet v0.1.0 h1:q1W82vIw5QVrotnzgowu63AqcO/ERD7LMr9UxEoFJIs= github.com/openweb3/go-ethereum-hdwallet v0.1.0/go.mod h1:ISDWwl+xpbvGbAfsZKfvW+LjHGjPzmdJQXbwi/ckzUE= github.com/openweb3/go-rpc-provider v0.3.3 h1:aNelA69cJ9pk9lo7Z8ukYz/qPyZUGNU3IF1600A8riI= @@ -369,18 +263,13 @@ github.com/openweb3/web3go v0.2.9 h1:RjCYVr3oBUeuPtX3Cwzz3pjg6qn91Ut3VuO/Li/XOeg github.com/openweb3/web3go v0.2.9/go.mod h1:SHcfq7LpXx4y2IH63QrqSXSkU0DTL981lDHtMR30+aw= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= -github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= -github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -391,7 +280,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -403,8 +291,6 @@ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -416,7 +302,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -445,47 +330,15 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc= github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= -github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0= -github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= -github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= -github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= -github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= -github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.opentelemetry.io/otel v1.13.0 h1:1ZAKnNQKwBBxFtww/GwxNUyTf0AxkZzrukO8MeXqe4Y= -go.opentelemetry.io/otel v1.13.0/go.mod h1:FH3RtdZCzRkJYFTCsAKDy9l/XYjMdNv6QrkFFB8DvVg= -go.opentelemetry.io/otel/trace v1.13.0 h1:CBgRZ6ntv+Amuj1jDsMhZtlAPT6gbyIRdaIzFhfBSdY= -go.opentelemetry.io/otel/trace v1.13.0/go.mod h1:muCvmmO9KKpvuXSf3KKAXXB2ygNYHQ+ZfI5X08d3tds= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -493,22 +346,16 @@ 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/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -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/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= @@ -522,8 +369,6 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -534,11 +379,8 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -563,22 +405,14 @@ golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/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 v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -588,11 +422,9 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 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= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= @@ -601,21 +433,15 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/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= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= -lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/transfer/dir/codec.go b/transfer/dir/codec.go new file mode 100644 index 0000000..3a57452 --- /dev/null +++ b/transfer/dir/codec.go @@ -0,0 +1,83 @@ +package dir + +import ( + "bytes" + "encoding/binary" + "encoding/json" + "io" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/pkg/errors" +) + +var ( + CodecVersion = uint16(1) + CodecMagicBytes = crypto.Keccak256([]byte("0g-storage-client-dir-codec")) +) + +// EncodeFsNode serializes an FsNode into a custom binary format with magic bytes and versioning. +func EncodeFsNode(node *FsNode) ([]byte, error) { + // Serialize the FsNode to JSON + mdata, err := json.Marshal(node) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal FsNode to JSON") + } + + // Prepare the buffer for the final binary data + buf := new(bytes.Buffer) + + // Write magic bytes + if _, err := buf.Write(CodecMagicBytes); err != nil { + return nil, errors.Wrap(err, "failed to write magic bytes") + } + + // Write codec version + if err := binary.Write(buf, binary.BigEndian, CodecVersion); err != nil { + return nil, errors.Wrap(err, "failed to write codec version") + } + + // Write the JSON data + if _, err := buf.Write(mdata); err != nil { + return nil, errors.Wrap(err, "failed to write JSON data") + } + + return buf.Bytes(), nil +} + +// DecodeFsNode deserializes an FsNode from a custom binary format with magic bytes and versioning. +func DecodeFsNode(data []byte) (*FsNode, error) { + // Create a reader from the input data + buf := bytes.NewReader(data) + + // Verify magic bytes + magicBytes := make([]byte, len(CodecMagicBytes)) + if _, err := io.ReadFull(buf, magicBytes); err != nil { + return nil, errors.Wrap(err, "failed to read magic bytes") + } + if !bytes.Equal(magicBytes, CodecMagicBytes) { + return nil, errors.New("invalid magic bytes") + } + + // Verify codec version + var version uint16 + if err := binary.Read(buf, binary.BigEndian, &version); err != nil { + return nil, errors.Wrap(err, "failed to read codec version") + } + if version != CodecVersion { + return nil, errors.Errorf("unsupported codec version: got %d, expected %d", version, CodecVersion) + } + + // Read the remaining data (the JSON-encoded FsNode) + mdata, err := io.ReadAll(buf) + if err != nil { + return nil, errors.Wrap(err, "failed to read JSON data") + } + + // Deserialize the FsNode from JSON data + var node FsNode + if err := json.Unmarshal(mdata, &node); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal FsNode from JSON") + } + + return &node, nil +} diff --git a/transfer/dir/codec_test.go b/transfer/dir/codec_test.go new file mode 100644 index 0000000..b022af8 --- /dev/null +++ b/transfer/dir/codec_test.go @@ -0,0 +1,83 @@ +package dir_test + +import ( + "bytes" + "reflect" + "testing" + + "github.com/0glabs/0g-storage-client/transfer/dir" + "github.com/ethereum/go-ethereum/common" +) + +func TestEncodeDecodeFsNode(t *testing.T) { + // Create a sample FsNode structure + originalNode := &dir.FsNode{ + Name: "testfile.txt", + Type: dir.File, + Hash: common.HexToHash("0x1234"), + Size: 1024, + } + + // Encode the FsNode to bytes + encodedData, err := dir.EncodeFsNode(originalNode) + if err != nil { + t.Fatalf("EncodeFsNode failed: %v", err) + } + + // Decode the bytes back into an FsNode + decodedNode, err := dir.DecodeFsNode(encodedData) + if err != nil { + t.Fatalf("DecodeFsNode failed: %v", err) + } + + // Compare the original and decoded FsNode to ensure they are the same + if !reflect.DeepEqual(originalNode, decodedNode) { + t.Errorf("expected FsNode to be equal, but got %v and %v", originalNode, decodedNode) + } +} + +func TestInvalidMagicBytes(t *testing.T) { + // Create a sample FsNode structure and encode it + originalNode := &dir.FsNode{ + Name: "testfile.txt", + Type: dir.File, + Hash: common.HexToHash("0x1234"), + Size: 1024, + } + encodedData, err := dir.EncodeFsNode(originalNode) + if err != nil { + t.Fatalf("EncodeFsNode failed: %v", err) + } + + // Modify the magic bytes to simulate corruption + encodedData[0] ^= 0xFF + + // Attempt to decode the corrupted data + _, err = dir.DecodeFsNode(encodedData) + if err == nil || err.Error() != "invalid magic bytes" { + t.Fatalf("expected error 'invalid magic bytes', got %v", err) + } +} + +func TestInvalidVersion(t *testing.T) { + // Create a sample FsNode structure and encode it + originalNode := &dir.FsNode{ + Name: "testfile.txt", + Type: dir.File, + Hash: common.HexToHash("0x1234"), + Size: 1024, + } + encodedData, err := dir.EncodeFsNode(originalNode) + if err != nil { + t.Fatalf("EncodeFsNode failed: %v", err) + } + + // Modify the version bytes to simulate an unsupported version + encodedData[len(dir.CodecMagicBytes)] ^= 0xFF + + // Attempt to decode the data with the modified version + _, err = dir.DecodeFsNode(encodedData) + if err == nil || !bytes.Contains([]byte(err.Error()), []byte("unsupported codec version")) { + t.Fatalf("expected version error, got %v", err) + } +} diff --git a/transfer/dir/diff.go b/transfer/dir/diff.go new file mode 100644 index 0000000..14b0e77 --- /dev/null +++ b/transfer/dir/diff.go @@ -0,0 +1,86 @@ +package dir + +import ( + "github.com/google/btree" + "github.com/pkg/errors" +) + +// DiffStatus represents the status of a node in the diff. +type DiffStatus string + +const ( + Added DiffStatus = "added" + Removed DiffStatus = "removed" + Modified DiffStatus = "modified" + Unchanged DiffStatus = "unchanged" +) + +// DiffNode represents a node in the diff structure with its status. +type DiffNode struct { + Node *FsNode // The original node + Status DiffStatus // Diff status of the node + Entries *btree.BTreeG[*DiffNode] // Directory entries as a B-Tree +} + +// NewDiffNode creates a new DiffNode. +func NewDiffNode(node *FsNode, status DiffStatus) *DiffNode { + diffNode := &DiffNode{ + Node: node, + Status: status, + } + + if node.Type == Directory { + diffNode.Entries = btree.NewG(2, func(a, b *DiffNode) bool { + return a.Node.Name < b.Node.Name + }) + } + + return diffNode +} + +// Diff compares two directories and returns a DiffNode tree with the differences. +func Diff(current, next *FsNode, recursive bool) (*DiffNode, error) { + if current.Type != Directory || next.Type != Directory { + return nil, errors.New("diff is only supported for directories") + } + + return diff(current, next, recursive), nil +} + +// diff is a recursive function that computes the differences between two directory nodes. +func diff(current, next *FsNode, recursive bool) *DiffNode { + root := NewDiffNode(current, Unchanged) + + // processes entries from the current directory. + for _, currentEntry := range current.Entries { + nextEntry, found := next.Search(currentEntry.Name) + if !found { + root.Entries.ReplaceOrInsert(NewDiffNode(currentEntry, Removed)) + root.Status = Modified + continue + } + + if currentEntry.Hash == nextEntry.Hash { + root.Entries.ReplaceOrInsert(NewDiffNode(currentEntry, Unchanged)) + continue + } + + root.Status = Modified + if recursive && currentEntry.Type == Directory && nextEntry.Type == Directory { + subDiff := diff(currentEntry, nextEntry, recursive) + root.Entries.ReplaceOrInsert(subDiff) + } else { + root.Entries.ReplaceOrInsert(NewDiffNode(currentEntry, Modified)) + } + } + + // processes entries from the next directory that were not found in the current directory. + for _, nextEntry := range next.Entries { + if _, found := current.Search(nextEntry.Name); !found { + root.Status = Modified + root.Entries.ReplaceOrInsert(NewDiffNode(nextEntry, Added)) + } + } + + return root +} diff --git a/transfer/dir/diff_test.go b/transfer/dir/diff_test.go new file mode 100644 index 0000000..546f2e2 --- /dev/null +++ b/transfer/dir/diff_test.go @@ -0,0 +1,129 @@ +package dir_test + +import ( + "testing" + + "github.com/0glabs/0g-storage-client/transfer/dir" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" +) + +func TestDiffIdenticalDirectories(t *testing.T) { + dir1 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + dir.NewFileFsNode("file2.txt", common.HexToHash("0x2"), 200), + }) + + dir2 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + dir.NewFileFsNode("file2.txt", common.HexToHash("0x2"), 200), + }) + + diffNode, err := dir.Diff(dir1, dir2, true) + assert.NoError(t, err) + assert.Equal(t, dir.Unchanged, diffNode.Status) + assert.Equal(t, 2, diffNode.Entries.Len()) +} + +func TestDiffFileAdded(t *testing.T) { + dir1 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + }) + + dir2 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + dir.NewFileFsNode("file2.txt", common.HexToHash("0x2"), 200), + }) + + diffNode, err := dir.Diff(dir1, dir2, true) + assert.NoError(t, err) + assert.Equal(t, dir.Modified, diffNode.Status) + assert.Equal(t, 2, diffNode.Entries.Len()) + + // Check that the added file is correctly identified + addedNode := findDiffNodeByName(diffNode, "file2.txt") + assert.NotNil(t, addedNode) + assert.Equal(t, dir.Added, addedNode.Status) +} + +func TestDiffFileRemoved(t *testing.T) { + dir1 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + dir.NewFileFsNode("file2.txt", common.HexToHash("0x2"), 200), + }) + + dir2 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + }) + + diffNode, err := dir.Diff(dir1, dir2, true) + assert.NoError(t, err) + assert.Equal(t, dir.Modified, diffNode.Status) + assert.Equal(t, 2, diffNode.Entries.Len()) + + // Check that the removed file is correctly identified + removedNode := findDiffNodeByName(diffNode, "file2.txt") + assert.NotNil(t, removedNode) + assert.Equal(t, dir.Removed, removedNode.Status) +} + +func TestDiffFileModified(t *testing.T) { + dir1 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + }) + + dir2 := dir.NewDirFsNode("root", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x2"), 150), + }) + + diffNode, err := dir.Diff(dir1, dir2, true) + assert.NoError(t, err) + assert.Equal(t, dir.Modified, diffNode.Status) + assert.Equal(t, 1, diffNode.Entries.Len()) + + // Check that the modified file is correctly identified + modifiedNode := findDiffNodeByName(diffNode, "file1.txt") + assert.NotNil(t, modifiedNode) + assert.Equal(t, dir.Modified, modifiedNode.Status) +} + +func TestDiffSubdirectoryChanges(t *testing.T) { + subDir1 := dir.NewDirFsNode("subdir", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x1"), 100), + }) + + subDir2 := dir.NewDirFsNode("subdir", []*dir.FsNode{ + dir.NewFileFsNode("file1.txt", common.HexToHash("0x2"), 150), + }) + + dir1 := dir.NewDirFsNode("root", []*dir.FsNode{subDir1}) + dir2 := dir.NewDirFsNode("root", []*dir.FsNode{subDir2}) + + diffNode, err := dir.Diff(dir1, dir2, true) + assert.NoError(t, err) + assert.Equal(t, dir.Modified, diffNode.Status) + assert.Equal(t, 1, diffNode.Entries.Len()) + + // Check the subdirectory for changes + subDirDiffNode := findDiffNodeByName(diffNode, "subdir") + assert.NotNil(t, subDirDiffNode) + assert.Equal(t, dir.Modified, subDirDiffNode.Status) + + // Check that the modified file is correctly identified + modifiedNode := findDiffNodeByName(subDirDiffNode, "file1.txt") + assert.NotNil(t, modifiedNode) + assert.Equal(t, dir.Modified, modifiedNode.Status) +} + +// Utility function to find a DiffNode by name +func findDiffNodeByName(root *dir.DiffNode, name string) *dir.DiffNode { + var result *dir.DiffNode + root.Entries.Ascend(func(n *dir.DiffNode) bool { + if n.Node.Name == name { + result = n + return false + } + return true + }) + return result +} diff --git a/transfer/dir/doc.go b/transfer/dir/doc.go new file mode 100644 index 0000000..2d12961 --- /dev/null +++ b/transfer/dir/doc.go @@ -0,0 +1,18 @@ +// Package dir provides support for folder operations within the 0g storage client. Since the 0g storage +// node does not natively support folder operations, this package introduces a way to represent and manage +// hierarchical directory structures, including encoding, decoding, and comparing directories and files. +// The folder structure is serialized into a binary format that includes a JSON representation of the data, +// which can be stored on and retrieved from the 0g storage node. +// +// The main features of this package include: +// +// - Defining the FsNode structure, which models files and directories in a nested, hierarchical format. +// - Serializing an FsNode structure into a binary format that includes a JSON representation, suitable +// for storage on a 0g storage node. +// - Deserializing the binary format back into an FsNode structure for further manipulation and operations. +// - Supporting the comparison of two directory structures to identify differences such as added, removed, +// or modified files. +// +// This package enables the 0g storage client to manage complex directory structures using an efficient +// and extensible data format, facilitating advanced file system operations beyond single file storage. +package dir diff --git a/transfer/dir/fs.go b/transfer/dir/fs.go new file mode 100644 index 0000000..35c13f1 --- /dev/null +++ b/transfer/dir/fs.go @@ -0,0 +1,153 @@ +package dir + +import ( + "os" + "path/filepath" + "sort" + "strings" + + "github.com/0glabs/0g-storage-client/core" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/pkg/errors" +) + +// FileType represents the file type in the FsNode structure. +type FileType string + +const ( + File FileType = "file" + Directory FileType = "directory" + Symbolic FileType = "symbolic" +) + +// FsNode represents a node in the filesystem hierarchy. +type FsNode struct { + Name string `json:"name"` // File or directory name + Type FileType `json:"type"` // File type of the node + Hash common.Hash `json:"hash,omitempty"` // Merkle hash + Size int64 `json:"size,omitempty"` // File size in bytes (only for files) + Link string `json:"link,omitempty"` // Symbolic link target + Entries []*FsNode `json:"entries,omitempty"` // Directory entries (only for directories) +} + +// NewDirFsNode creates a new FsNode representing a directory. +func NewDirFsNode(name string, entryNodes []*FsNode) *FsNode { + sort.Slice(entryNodes, func(i, j int) bool { + return entryNodes[i].Name < entryNodes[j].Name + }) + + rootHash := calculateRootHash(entryNodes) + + return &FsNode{ + Name: name, + Type: Directory, + Hash: rootHash, + Entries: entryNodes, + } +} + +// calculateRootHash computes the Merkle root hash for a list of FsNode entries. +func calculateRootHash(entries []*FsNode) common.Hash { + var root common.Hash + + if len(entries) == 0 { + return root + } + + root = crypto.Keccak256Hash(entries[len(entries)-1].Hash[:]) + for i := len(entries) - 2; i >= 0; i-- { + root = crypto.Keccak256Hash(entries[i].Hash[:], root[:]) + } + + return root +} + +// NewFileFsNode creates a new FsNode representing a file. +func NewFileFsNode(name string, hash common.Hash, size int64) *FsNode { + return &FsNode{ + Name: name, + Type: File, + Hash: hash, + Size: size, + } +} + +// NewSymbolicFsNode creates a new FsNode representing a symbolic link. +func NewSymbolicFsNode(name, link string) *FsNode { + return &FsNode{ + Name: name, + Type: Symbolic, + Hash: crypto.Keccak256Hash([]byte(link)), + Link: link, + } +} + +// Search looks for a file by name in the current directory node's entries. +func (node *FsNode) Search(fileName string) (*FsNode, bool) { + i, found := sort.Find(len(node.Entries), func(i int) int { + return strings.Compare(fileName, node.Entries[i].Name) + }) + + if found { + return node.Entries[i], true + } + return nil, false +} + +// BuildFileTree recursively builds a file tree starting from the specified path. +func BuildFileTree(path string) (*FsNode, error) { + info, err := os.Lstat(path) + if err != nil { + return nil, errors.WithMessagef(err, "failed to stat file %s", path) + } + + switch { + case info.IsDir(): + return buildDirectoryNode(path, info) + case info.Mode()&os.ModeSymlink != 0: + return buildSymbolicNode(path, info) + case info.Mode().IsRegular(): + return buildFileNode(path, info) + default: + return nil, errors.New("unsupported file type") + } +} + +// buildDirectoryNode creates an FsNode for a directory, including its contents. +func buildDirectoryNode(path string, info os.FileInfo) (*FsNode, error) { + entries, err := os.ReadDir(path) + if err != nil { + return nil, errors.WithMessagef(err, "failed to read directory %s", path) + } + + var entryNodes []*FsNode + for _, entry := range entries { + entryPath := filepath.Join(path, entry.Name()) + entryNode, err := BuildFileTree(entryPath) + if err != nil { + return nil, err + } + entryNodes = append(entryNodes, entryNode) + } + return NewDirFsNode(info.Name(), entryNodes), nil +} + +// buildSymbolicNode creates an FsNode for a symbolic link. +func buildSymbolicNode(path string, info os.FileInfo) (*FsNode, error) { + link, err := os.Readlink(path) + if err != nil { + return nil, errors.WithMessage(err, "invalid symbolic link") + } + + return NewSymbolicFsNode(info.Name(), link), nil +} + +// buildFileNode creates an FsNode for a regular file, including its Merkle root hash. +func buildFileNode(path string, info os.FileInfo) (*FsNode, error) { + hash, err := core.MerkleRoot(path) + if err != nil { + return nil, errors.WithMessagef(err, "failed to calculate merkle root for %s", path) + } + return NewFileFsNode(info.Name(), hash, info.Size()), nil +} diff --git a/transfer/dir/fs_test.go b/transfer/dir/fs_test.go new file mode 100644 index 0000000..07e278e --- /dev/null +++ b/transfer/dir/fs_test.go @@ -0,0 +1,109 @@ +package dir_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/0glabs/0g-storage-client/core" + "github.com/0glabs/0g-storage-client/transfer/dir" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" +) + +func TestNewDirFsNode(t *testing.T) { + child1 := &dir.FsNode{Name: "child1", Hash: common.HexToHash("0x01")} + child2 := &dir.FsNode{Name: "child2", Hash: common.HexToHash("0x02")} + children := []*dir.FsNode{child1, child2} + + node := dir.NewDirFsNode("root", children) + + assert.Equal(t, "root", node.Name) + assert.Equal(t, dir.Directory, node.Type) + assert.NotEqual(t, common.Hash{}, node.Hash) + assert.Len(t, node.Entries, 2) + assert.Equal(t, "child1", node.Entries[0].Name) + assert.Equal(t, "child2", node.Entries[1].Name) +} + +func TestNewFileFsNode(t *testing.T) { + hash := common.HexToHash("0x12345") + node := dir.NewFileFsNode("file.txt", hash, 1024) + + assert.Equal(t, "file.txt", node.Name) + assert.Equal(t, dir.File, node.Type) + assert.Equal(t, hash, node.Hash) + assert.Equal(t, int64(1024), node.Size) +} + +func TestNewSymbolicFsNode(t *testing.T) { + link := "/some/path" + node := dir.NewSymbolicFsNode("symlink", link) + + assert.Equal(t, "symlink", node.Name) + assert.Equal(t, dir.Symbolic, node.Type) + assert.Equal(t, crypto.Keccak256Hash([]byte(link)), node.Hash) + assert.Equal(t, link, node.Link) +} + +func TestSearch(t *testing.T) { + child1 := &dir.FsNode{Name: "child1"} + child2 := &dir.FsNode{Name: "child2"} + children := []*dir.FsNode{child1, child2} + + node := dir.NewDirFsNode("root", children) + + result, found := node.Search("child1") + assert.True(t, found) + assert.Equal(t, child1, result) + + result, found = node.Search("nonexistent") + assert.False(t, found) + assert.Nil(t, result) +} + +func TestBuildFileTree(t *testing.T) { + tempDir := t.TempDir() + + // create test file + filePath := filepath.Join(tempDir, "testfile.txt") + err := os.WriteFile(filePath, []byte("content"), 0644) + assert.NoError(t, err) + + // create symbolic link + linkPath := filepath.Join(tempDir, "symlink") + err = os.Symlink(filePath, linkPath) + assert.NoError(t, err) + + // create test directory + dirPath := filepath.Join(tempDir, "subdir") + err = os.Mkdir(dirPath, 0755) + assert.NoError(t, err) + + t.Run("test directory node", func(t *testing.T) { + node, err := dir.BuildFileTree(tempDir) + assert.NoError(t, err) + assert.Equal(t, dir.Directory, node.Type) + assert.Len(t, node.Entries, 3) // "testfile.txt", "symlink", "subdir" + }) + + t.Run("test file node", func(t *testing.T) { + node, err := dir.BuildFileTree(filePath) + assert.NoError(t, err) + assert.Equal(t, dir.File, node.Type) + assert.Equal(t, int64(len("content")), node.Size) + + // Calculate expected hash using core.MerkleRoot + expectedHash, err := core.MerkleRoot(filePath) + assert.NoError(t, err) + assert.Equal(t, expectedHash, node.Hash) + }) + + t.Run("test symbolic link node", func(t *testing.T) { + node, err := dir.BuildFileTree(linkPath) + assert.NoError(t, err) + assert.Equal(t, dir.Symbolic, node.Type) + assert.Equal(t, filePath, node.Link) + }) +} diff --git a/transfer/unixfs/codec.go b/transfer/unixfs/codec.go deleted file mode 100644 index 97c260f..0000000 --- a/transfer/unixfs/codec.go +++ /dev/null @@ -1,56 +0,0 @@ -package unixfs - -import ( - "encoding/json" - - "github.com/ipfs/go-unixfsnode/data" - "github.com/ipfs/go-unixfsnode/data/builder" - "github.com/pkg/errors" -) - -// EncodeFsNode serializes an FsNode to bytes, embedding it in a UnixFS structure. -func EncodeFsNode(node *FsNode) ([]byte, error) { - // Serialize the FsNode to JSON - mdata, err := json.Marshal(node) - if err != nil { - return nil, errors.WithMessage(err, "failed to marshal FsNode to JSON") - } - - // Build a UnixFS node containing the serialized FsNode - ufs, err := builder.BuildUnixFS(func(b *builder.Builder) { - // Set the data type to raw data - builder.DataType(b, data.Data_Raw) - // Set the serialized FsNode data - builder.Data(b, mdata) - }) - if err != nil { - return nil, errors.WithMessage(err, "failed to build UnixFS node") - } - - // Encode the UnixFS node to bytes - encodedData := data.EncodeUnixFSData(ufs) - return encodedData, nil -} - -// DecodeFsNode deserializes a FsNode from bytes, extracting it from a UnixFS structure. -func DecodeFsNode(b []byte) (*FsNode, error) { - // Decode the UnixFS data from the byte slice - ufs, err := data.DecodeUnixFSData(b) - if err != nil { - return nil, errors.WithMessage(err, "failed to decode UnixFS data") - } - - // Verify the data type is raw as expected - if ufs.FieldDataType().Int() != data.Data_Raw { - return nil, errors.New("unexpected data type, expected raw data") - } - - // Deserialize the FsNode from the UnixFS data - var node FsNode - err = json.Unmarshal(ufs.FieldData().Must().Bytes(), &node) - if err != nil { - return nil, errors.WithMessage(err, "failed to unmarshal FsNode from JSON") - } - - return &node, nil -} diff --git a/transfer/unixfs/codec_test.go b/transfer/unixfs/codec_test.go deleted file mode 100644 index 9411bb3..0000000 --- a/transfer/unixfs/codec_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package unixfs_test - -import ( - "reflect" - "testing" - - "github.com/0glabs/0g-storage-client/transfer/unixfs" - "github.com/stretchr/testify/assert" -) - -var ( - // Example usage - exampleFsNode = &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{ - { - Name: "file1.txt", - Type: unixfs.File, - Size: 1234, - }, - { - Name: "file2.txt", - Type: unixfs.File, - Size: 5678, - }, - { - Name: "subdir", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{ - { - Name: "file3.txt", - Type: unixfs.File, - Size: 91011, - }, - }, - }, - }, - } -) - -func TestCodec(t *testing.T) { - - // Encode the FsNode to bytes - encoded, err := unixfs.EncodeFsNode(exampleFsNode) - assert.NoError(t, err) - - // Decode the bytes back to an FsNode - decodedNode, err := unixfs.DecodeFsNode(encoded) - assert.NoError(t, err) - - assert.True(t, reflect.DeepEqual(exampleFsNode, decodedNode)) -} - -// BenchmarkEncodeFsNode benchmarks the performance of the EncodeFsNode function. -func BenchmarkEncodeFsNode(b *testing.B) { - // Run the benchmark loop - for i := 0; i < b.N; i++ { - _, err := unixfs.EncodeFsNode(exampleFsNode) - if err != nil { - b.Fatalf("Error encoding FsNode: %v", err) - } - } -} - -// BenchmarkDecodeFsNode benchmarks the performance of the DecodeFsNode function. -func BenchmarkDecodeFsNode(b *testing.B) { - // Pre-encode the FsNode to use as input for decoding benchmark - encodedData, err := unixfs.EncodeFsNode(exampleFsNode) - if err != nil { - b.Fatalf("Error encoding FsNode for decoding benchmark: %v", err) - } - - // Run the benchmark loop - for i := 0; i < b.N; i++ { - _, err := unixfs.DecodeFsNode(encodedData) - if err != nil { - b.Fatalf("Error decoding FsNode: %v", err) - } - } -} diff --git a/transfer/unixfs/doc.go b/transfer/unixfs/doc.go deleted file mode 100644 index ff26740..0000000 --- a/transfer/unixfs/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -// Package unixfs implements a data format to add support for folder operations within the 0g storage client. -// The 0g storage node has no built-in support for folder operations, so this package provides a way to -// represent folder hierarchies and perform operations such as adding, updating, and deleting files -// within a directory structure. The folder structure is serialized as JSON, merged into a protocol buffer -// based format (UnixFs), which can be stored and retrieved from the 0g storage node. -// -// The main features of this package include: -// -// - Defining the FileNode structure, which represents files and directories in a nested hierarchical format. -// - Serializing a FileNode structure into a JSON representation, assembled into a UnixFS raw file that can be -// uploaded to a 0g storage node. -// - Deserializing the JSON representation back into a FileNode structure for further operations. -// - Supporting operations such as adding, updating, and deleting files within the directory structure. -// - Providing methods to traverse and visualize the directory structure. -// -// This package enables the 0g storage client to handle complex directory structures by using a simple and -// extensible data format, allowing for more advanced file system operations beyond single file storage. -package unixfs diff --git a/transfer/unixfs/fs.go b/transfer/unixfs/fs.go deleted file mode 100644 index 35b6d33..0000000 --- a/transfer/unixfs/fs.go +++ /dev/null @@ -1,232 +0,0 @@ -package unixfs - -import ( - "os" - "path/filepath" - "sort" - "strings" - - "github.com/pkg/errors" -) - -// FileType represents the type of a file in the FsNode structure. -type FileType string - -const ( - File FileType = "file" - Directory FileType = "directory" -) - -var ( - ErrDirectoryRequired = errors.New("operation supported only on directories") - ErrEntryNotFound = errors.New("directory entry not found") - ErrFileNotFound = errors.New("file not found") -) - -// FsNode represents a node in the filesystem hierarchy. -type FsNode struct { - Name string `json:"name"` // File or directory name - Type FileType `json:"type"` // Type of the node (file or directory) - Size int64 `json:"size,omitempty"` // File size in bytes (omitted for directories) - Hash string `json:"hash,omitempty"` // Merkle root hash (only for files) - Entries []*FsNode `json:"entries,omitempty"` // Directory entries (only for directories) -} - -// Add adds a new file to the directory and keeps the entries sorted by name. -func (node *FsNode) Add(file *FsNode) error { - if node.Type != Directory { - return ErrDirectoryRequired - } - - // Find the index where the file should be inserted - index, found := node.Search(file.Name) - - // If the file already exists, replace it - if found { - node.Entries[index] = file - return nil - } - - // Insert and sort the new file at the correct position - node.Entries = append(node.Entries, file) - node.sort() - - return nil -} - -// BatchAdd adds multiple files or directories to the current directory and sorts once. -func (node *FsNode) BatchAdd(entries []*FsNode) error { - if node.Type != Directory { - return ErrDirectoryRequired - } - - // Append all new entries - node.Entries = append(node.Entries, entries...) - - // Sort the entries after all additions - node.sort() - return nil -} - -// Update updates an existing file's metadata within the directory. -func (node *FsNode) Update(file *FsNode) error { - if node.Type != Directory { - return ErrDirectoryRequired - } - - index, found := node.Search(file.Name) - if !found { - return ErrFileNotFound - } - - // Update the existing entry - node.Entries[index] = file - return nil -} - -// Rename renames a file or directory within the directory and keeps the entries sorted. -func (node *FsNode) Rename(oldName, newName string) error { - if node.Type != Directory { - return ErrDirectoryRequired - } - - // Find the index of the old file/directory - index, found := node.Search(oldName) - if !found { - return ErrFileNotFound - } - - // Retrieve the existing entry - entry := node.Entries[index] - - // If the name is the same, there's nothing to rename - if entry.Name == newName { - return nil - } - - // Just in case new name already exists - if _, found := node.Search(newName); found { - return errors.New("file with the new name already exists") - } - - // Remove the old entry - node.Entries = append(node.Entries[:index], node.Entries[index+1:]...) - - // Update the entry's name - entry.Name = newName - - // Re-insert the renamed entry at the correct position - return node.Add(entry) -} - -// Delete removes a file from the directory. -func (node *FsNode) Delete(fileName string) error { - if node.Type != Directory { - return ErrDirectoryRequired - } - - index, found := node.Search(fileName) - if !found { - return ErrFileNotFound - } - - // Remove the file - node.Entries = append(node.Entries[:index], node.Entries[index+1:]...) - return nil -} - -// Locate locates a child node by its path within the FsNode. -func (node *FsNode) Locate(path string) (parent, current *FsNode, found bool) { - // Normalize the path and split it into parts - parts := strings.Split(filepath.Clean(path), string(os.PathSeparator)) - - // Start from the current node - current = node - - // Traverse the path - for _, part := range parts { - if current.Type != Directory { - return nil, nil, false // Cannot traverse a non-directory node - } - - index, found := current.Search(part) - if !found { - return nil, nil, false // Part not found in current directory - } - - parent = current // Save the parent node - current = current.Entries[index] // Move to the next level - } - - return parent, current, true -} - -// Search finds the index of an entry by name using binary search. -// It returns the index and a boolean indicating if the entry was found. -func (node *FsNode) Search(name string) (int, bool) { - index := sort.Search(len(node.Entries), func(i int) bool { - return node.Entries[i].Name >= name - }) - if index < len(node.Entries) && node.Entries[index].Name == name { - return index, true - } - return index, false -} - -// sort sorts the entries slice by the name field in alphabetical order. -func (node *FsNode) sort() { - sort.Slice(node.Entries, func(i, j int) bool { - return node.Entries[i].Name < node.Entries[j].Name - }) -} - -// BuildFileTree recursively builds a file tree from the given file path. -func BuildFileTree(path string) (*FsNode, error) { - info, err := os.Stat(path) - if err != nil { - return nil, err - } - - // Handle file case - if !info.IsDir() { - merkleRoot, err := GetMerkleTreeRootOfFile(path) - if err != nil { - return nil, err - } - - return &FsNode{ - Name: info.Name(), - Type: File, - Size: info.Size(), - Hash: merkleRoot, - }, nil - } - - // Handle directory case - node := &FsNode{ - Name: info.Name(), - Type: Directory, - Entries: []*FsNode{}, - } - - entries, err := os.ReadDir(path) - if err != nil { - return nil, err - } - - var children []*FsNode - for _, entry := range entries { - entryPath := filepath.Join(path, entry.Name()) - entryNode, err := BuildFileTree(entryPath) - if err != nil { - return nil, err - } - children = append(children, entryNode) - } - - if len(children) > 0 { - return node, node.BatchAdd(children) - } - - return node, nil -} diff --git a/transfer/unixfs/fs_test.go b/transfer/unixfs/fs_test.go deleted file mode 100644 index 4ffbae8..0000000 --- a/transfer/unixfs/fs_test.go +++ /dev/null @@ -1,287 +0,0 @@ -package unixfs_test - -import ( - "os" - "path/filepath" - "testing" - - "github.com/0glabs/0g-storage-client/transfer/unixfs" - "github.com/stretchr/testify/assert" -) - -func setupTestFixtures(t *testing.T) string { - /* - Create a temporary directory to hold the test fixtures: - fixtures/ - ├── file1.txt - ├── file2.txt - └── subdir/ - └── file3.txt - */ - tempDir, err := os.MkdirTemp("", "buildfiletree_test") - assert.NoError(t, err) - - assert.NoError(t, os.Mkdir(filepath.Join(tempDir, "subdir"), 0755)) - assert.NoError(t, os.WriteFile(filepath.Join(tempDir, "file1.txt"), []byte("This is file 1"), 0644)) - assert.NoError(t, os.WriteFile(filepath.Join(tempDir, "file2.txt"), []byte("This is file 2"), 0644)) - assert.NoError(t, os.WriteFile(filepath.Join(tempDir, "subdir/file3.txt"), []byte("This is file 3"), 0644)) - - return tempDir -} - -func cleanupTestFixtures(t *testing.T, tempDir string) { - assert.NoError(t, os.RemoveAll(tempDir)) -} - -func TestBuildFileTree(t *testing.T) { - // Setup the test fixtures - tempDir := setupTestFixtures(t) - defer cleanupTestFixtures(t, tempDir) - - // Build the file tree from the fixtures directory - tree, err := unixfs.BuildFileTree(tempDir) - assert.NoError(t, err) - assert.NotNil(t, tree) - - // Validate the root node - assert.Equal(t, filepath.Base(tempDir), tree.Name) - assert.Equal(t, unixfs.Directory, tree.Type) - assert.Empty(t, tree.Hash) - - // Validate the root node has 3 entries - assert.Len(t, tree.Entries, 3) - - // Validate the files and subdirectory - var file1, file2, subdir *unixfs.FsNode - for _, entry := range tree.Entries { - switch entry.Name { - case "file1.txt": - file1 = entry - case "file2.txt": - file2 = entry - case "subdir": - subdir = entry - } - } - - assert.NotNil(t, file1) - assert.Equal(t, unixfs.File, file1.Type) - assert.Equal(t, int64(14), file1.Size) // "This is file 1" length is 14 - assert.NotEmpty(t, file1.Hash) - - assert.NotNil(t, file2) - assert.Equal(t, unixfs.File, file2.Type) - assert.Equal(t, int64(14), file2.Size) // "This is file 2" length is 14 - assert.NotEmpty(t, file2.Hash) - - assert.NotNil(t, subdir) - assert.Equal(t, unixfs.Directory, subdir.Type) - assert.Len(t, subdir.Entries, 1) // subdir should contain 1 file - assert.Empty(t, subdir.Hash) - - // Validate the file in subdir - subfile := subdir.Entries[0] - assert.Equal(t, "file3.txt", subfile.Name) - assert.Equal(t, unixfs.File, subfile.Type) - assert.Equal(t, int64(14), subfile.Size) // "This is file 3" length is 14 - assert.NotEmpty(t, subfile.Hash) -} - -func TestAddFile(t *testing.T) { - dir := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Add a file - err := dir.Add(&unixfs.FsNode{Name: "file1.txt", Type: unixfs.File, Size: 1234}) - assert.NoError(t, err) - assert.Len(t, dir.Entries, 1) - assert.Equal(t, "file1.txt", dir.Entries[0].Name) - - // Add another file and check if it's sorted - err = dir.Add(&unixfs.FsNode{Name: "file2.txt", Type: unixfs.File, Size: 5678}) - assert.NoError(t, err) - assert.Len(t, dir.Entries, 2) - assert.Equal(t, "file1.txt", dir.Entries[0].Name) - assert.Equal(t, "file2.txt", dir.Entries[1].Name) - - // Add a file with the same name to replace it - err = dir.Add(&unixfs.FsNode{Name: "file1.txt", Type: unixfs.File, Size: 4321}) - assert.NoError(t, err) - assert.Len(t, dir.Entries, 2) - assert.Equal(t, "file1.txt", dir.Entries[0].Name) - assert.Equal(t, int64(4321), dir.Entries[0].Size) -} - -func TestBatchAddFiles(t *testing.T) { - dir := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Batch add files - err := dir.BatchAdd([]*unixfs.FsNode{ - {Name: "file2.txt", Type: unixfs.File, Size: 5678}, - {Name: "file1.txt", Type: unixfs.File, Size: 1234}, - {Name: "file3.txt", Type: unixfs.File, Size: 91011}, - }) - assert.NoError(t, err) - assert.Len(t, dir.Entries, 3) - - // Check if files are sorted - assert.Equal(t, "file1.txt", dir.Entries[0].Name) - assert.Equal(t, "file2.txt", dir.Entries[1].Name) - assert.Equal(t, "file3.txt", dir.Entries[2].Name) -} - -func TestUpdateFile(t *testing.T) { - dir := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Add a file - err := dir.Add(&unixfs.FsNode{Name: "file1.txt", Type: unixfs.File, Size: 1234}) - assert.NoError(t, err) - - // Update the file - err = dir.Update(&unixfs.FsNode{Name: "file1.txt", Type: unixfs.File, Size: 5678}) - assert.NoError(t, err) - assert.Len(t, dir.Entries, 1) - assert.Equal(t, "file1.txt", dir.Entries[0].Name) - assert.Equal(t, int64(5678), dir.Entries[0].Size) - - // Try to update a non-existent file - err = dir.Update(&unixfs.FsNode{Name: "file2.txt", Type: unixfs.File, Size: 91011}) - assert.ErrorIs(t, err, unixfs.ErrFileNotFound) -} - -func TestRenameFile(t *testing.T) { - dir := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Add a file - err := dir.Add(&unixfs.FsNode{Name: "file1.txt", Type: unixfs.File, Size: 1234}) - assert.NoError(t, err) - - // Rename the file - err = dir.Rename("file1.txt", "file2.txt") - assert.NoError(t, err) - assert.Len(t, dir.Entries, 1) - assert.Equal(t, "file2.txt", dir.Entries[0].Name) - - // Rename to an existing name (not allowed) - err = dir.Add(&unixfs.FsNode{Name: "file3.txt", Type: unixfs.File, Size: 5678}) - assert.NoError(t, err) - err = dir.Rename("file2.txt", "file3.txt") - assert.Error(t, err) -} - -func TestDeleteFile(t *testing.T) { - dir := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Add a file - err := dir.Add(&unixfs.FsNode{Name: "file1.txt", Type: unixfs.File, Size: 1234}) - assert.NoError(t, err) - - // Delete the file - err = dir.Delete("file1.txt") - assert.NoError(t, err) - assert.Len(t, dir.Entries, 0) - - // Try to delete a non-existent file - err = dir.Delete("file2.txt") - assert.ErrorIs(t, err, unixfs.ErrFileNotFound) -} - -func TestLocate(t *testing.T) { - root := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Build a directory structure - root.BatchAdd([]*unixfs.FsNode{ - {Name: "dir1", Type: unixfs.Directory, Entries: []*unixfs.FsNode{ - {Name: "file1.txt", Type: unixfs.File, Size: 1234}, - {Name: "file2.txt", Type: unixfs.File, Size: 5678}, - }}, - {Name: "dir2", Type: unixfs.Directory, Entries: []*unixfs.FsNode{ - {Name: "subdir1", Type: unixfs.Directory, Entries: []*unixfs.FsNode{ - {Name: "file3.txt", Type: unixfs.File, Size: 91011}, - }}, - }}, - {Name: "file4.txt", Type: unixfs.File, Size: 4321}, - }) - - // Locate a file in the root directory - parent, node, found := root.Locate("file4.txt") - assert.True(t, found) - assert.NotNil(t, node) - assert.Equal(t, "file4.txt", node.Name) - assert.Equal(t, root, parent) - - // Locate a file in a subdirectory - parent, node, found = root.Locate("dir1/file1.txt") - assert.True(t, found) - assert.NotNil(t, node) - assert.Equal(t, "file1.txt", node.Name) - assert.Equal(t, root.Entries[0], parent) - - // Locate a file in a nested subdirectory - parent, node, found = root.Locate("dir2/subdir1/file3.txt") - assert.True(t, found) - assert.NotNil(t, node) - assert.Equal(t, "file3.txt", node.Name) - assert.Equal(t, root.Entries[1].Entries[0], parent) - - // Try to locate a non-existent file - parent, node, found = root.Locate("dir2/subdir1/fileX.txt") - assert.False(t, found) - assert.Nil(t, node) - assert.Nil(t, parent) - - // Try to locate a file through a non-directory path - parent, node, found = root.Locate("file4.txt/fileX.txt") - assert.False(t, found) - assert.Nil(t, node) - assert.Nil(t, parent) -} - -func TestSearchFile(t *testing.T) { - dir := &unixfs.FsNode{ - Name: "root", - Type: unixfs.Directory, - Entries: []*unixfs.FsNode{}, - } - - // Add files - err := dir.BatchAdd([]*unixfs.FsNode{ - {Name: "file1.txt", Type: unixfs.File, Size: 1234}, - {Name: "file2.txt", Type: unixfs.File, Size: 5678}, - {Name: "file3.txt", Type: unixfs.File, Size: 91011}, - }) - assert.NoError(t, err) - - // Search for an existing file - index, found := dir.Search("file2.txt") - assert.True(t, found) - assert.Equal(t, 1, index) - - // Search for a non-existent file - index, found = dir.Search("file4.txt") - assert.False(t, found) - assert.Equal(t, 3, index) // index is where the file would be inserted -} diff --git a/transfer/unixfs/util.go b/transfer/unixfs/util.go deleted file mode 100644 index f48ad45..0000000 --- a/transfer/unixfs/util.go +++ /dev/null @@ -1,26 +0,0 @@ -package unixfs - -import ( - "github.com/0glabs/0g-storage-client/core" - "github.com/pkg/errors" -) - -// GetMerkleTreeRootOfFile calculates and returns the Merkle tree root hash of a given file. -// It opens the file, generates the Merkle tree, and returns the root hash as a hexadecimal string. -func GetMerkleTreeRootOfFile(filename string) (string, error) { - // Attempt to open the file - file, err := core.Open(filename) - if err != nil { - return "", errors.WithMessagef(err, "failed to open file %s", filename) - } - defer file.Close() - - // Generate the Merkle tree from the file content - tree, err := core.MerkleTree(file) - if err != nil { - return "", errors.WithMessagef(err, "failed to create Merkle tree for file %s", filename) - } - - // Return the root hash of the Merkle tree as a hexadecimal string - return tree.Root().Hex(), nil -}