├── .gitignore ├── ipfs-snapshot ├── snapshot_iterator.go ├── verkle_snapshot.go ├── mainnet.go └── snapshot.go ├── verkle ├── visited_map.go ├── storage.go ├── account.go └── tree.go ├── README.md ├── go.mod ├── main.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | precomp 2 | verkleipfs -------------------------------------------------------------------------------- /ipfs-snapshot/snapshot_iterator.go: -------------------------------------------------------------------------------- 1 | package ipfssnapshot 2 | 3 | import "io" 4 | 5 | type SnapshotIterator interface { 6 | // Parse snapshot and return preimages one by one 7 | Next(r io.Reader) ([]byte, []byte, error) // Return next kv pair 8 | } 9 | -------------------------------------------------------------------------------- /verkle/visited_map.go: -------------------------------------------------------------------------------- 1 | package verkle 2 | 3 | import lru "github.com/hashicorp/golang-lru" 4 | 5 | const cacheSize = 500_000 6 | 7 | type VisitedMap lru.Cache 8 | 9 | func NewVisitedMap() *VisitedMap { 10 | c, err := lru.New(cacheSize) 11 | if err != nil { 12 | panic(err) 13 | } 14 | return (*VisitedMap)(c) 15 | } 16 | 17 | func (v *VisitedMap) Visited(singularity interface{}) bool { 18 | return (*lru.Cache)(v).Contains(singularity) 19 | } 20 | 21 | func (v *VisitedMap) Visit(singularity interface{}) { 22 | (*lru.Cache)(v).Add(singularity, true) 23 | } 24 | -------------------------------------------------------------------------------- /ipfs-snapshot/verkle_snapshot.go: -------------------------------------------------------------------------------- 1 | package ipfssnapshot 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | "io" 7 | ) 8 | 9 | type VerkleSnapshotIterator struct{} 10 | 11 | // Read Erigon/Geth Verkle snapshot format 12 | func (VerkleSnapshotIterator) Next(r io.Reader) ([]byte, []byte, error) { 13 | key := make([]byte, 32) // Key is committment hash 14 | _, err := r.Read(key) 15 | if err == io.EOF { 16 | return nil, nil, nil 17 | } 18 | if err != nil { 19 | return nil, nil, err 20 | } 21 | nodeLengthBytes := make([]byte, 8) 22 | if _, err := r.Read(nodeLengthBytes); err != nil { 23 | return nil, nil, err 24 | } 25 | nodeLength := binary.BigEndian.Uint64(nodeLengthBytes) 26 | // Read Verkle node 27 | value := make([]byte, nodeLength) 28 | var bytesRead int 29 | if bytesRead, err = r.Read(value); err != nil { 30 | return nil, nil, err 31 | } 32 | if bytesRead != int(nodeLength) { 33 | return nil, nil, fmt.Errorf("EOF Truncated") 34 | } 35 | return key, value, nil 36 | } 37 | -------------------------------------------------------------------------------- /ipfs-snapshot/mainnet.go: -------------------------------------------------------------------------------- 1 | package ipfssnapshot 2 | 3 | import "github.com/ledgerwatch/erigon/common" 4 | 5 | const DefaultSize uint64 = 10523560000 6 | const HalfSize uint64 = 7507572000 7 | 8 | const MainnetVerkleUpdateBlock = uint64(16061713) 9 | 10 | var MainnetVerkleUpdateRoot = common.BytesToHash(common.Hex2Bytes("048ac0e036f02f4b4572502dbd506d9673bff18462ba6c587c8e9e9b9aa3304c")) 11 | 12 | func MainnetVerkleIpfsSnapshot() []*IPFSSnapshotSztd { 13 | return []*IPFSSnapshotSztd{ 14 | NewIpfsSnapshotSztd("Qmb15kNqrb9nk5BMbZDUXHzDbUde13HcsmFJeMcLFcU1aw", DefaultSize, VerkleSnapshotIterator{}), 15 | NewIpfsSnapshotSztd("QmcVKx3HZpMunFSyogy4vbH1jZ91xXZfBJyKUJ9sYbMAw6", DefaultSize, VerkleSnapshotIterator{}), 16 | NewIpfsSnapshotSztd("QmZuqJpsu71ZqW5VVMxBJwGZPzqqV8AcNg9JW1pa3Y1wPg", DefaultSize, VerkleSnapshotIterator{}), 17 | NewIpfsSnapshotSztd("QmRvpJWC4XjP7XiLYpkk1CepCVvCgis4DQmSo43Tc3oSPi", DefaultSize, VerkleSnapshotIterator{}), 18 | 19 | NewIpfsSnapshotSztd("QmRvpJWC4XjP7XiLYpkk1CepCVvCgis4DQmSo43Tc3oSPi", DefaultSize, VerkleSnapshotIterator{}), 20 | NewIpfsSnapshotSztd("Qmea37QzxcwxnM1sLkJnF5SUCC5d9njdRFmSwG8QTj7bgt", DefaultSize, VerkleSnapshotIterator{}), 21 | NewIpfsSnapshotSztd("QmUdHXAkuvuLfMiTor4Ea2zNgYVxyY6FE19MAbmveHVgu4", DefaultSize, VerkleSnapshotIterator{}), 22 | NewIpfsSnapshotSztd("QmXWkwNq8q649yxxinr3fk6yTYZtyf9T8GsbDk3ypjSozo", DefaultSize, VerkleSnapshotIterator{}), 23 | NewIpfsSnapshotSztd("QmNUTXa4zSRoreqz1ptsV2ivFnH5NNA3fLAFT8zWXLNLt5", DefaultSize, VerkleSnapshotIterator{}), 24 | NewIpfsSnapshotSztd("QmRrEY4yP3cxGdJ5aSNxNaQVyRfnqnPayxfNhbueywfeGw", HalfSize, VerkleSnapshotIterator{}), 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /verkle/storage.go: -------------------------------------------------------------------------------- 1 | package verkle 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/holiman/uint256" 7 | "github.com/ledgerwatch/erigon-lib/kv" 8 | "github.com/ledgerwatch/erigon/common/changeset" 9 | "github.com/ledgerwatch/erigon/common/dbutils" 10 | "github.com/ledgerwatch/erigon/turbo/trie/vtree" 11 | "github.com/ledgerwatch/log/v3" 12 | ) 13 | 14 | func DoStorage(tx kv.Tx, tree *Tree, from, to uint64) error { 15 | cursor, err := tx.CursorDupSort(kv.StorageChangeSet) 16 | if err != nil { 17 | return err 18 | } 19 | defer cursor.Close() 20 | startKey := dbutils.EncodeBlockNumber(from) 21 | visited := NewVisitedMap() 22 | var key, value []byte 23 | logInterval := time.NewTicker(30 * time.Second) 24 | defer logInterval.Stop() 25 | for key, value, err = cursor.Seek(startKey); key != nil; key, value, err = cursor.Next() { 26 | if err != nil { 27 | return err 28 | } 29 | block, dbKey, _, err := changeset.DecodeStorage(key, value) 30 | if err != nil { 31 | return err 32 | } 33 | if block > to { 34 | break 35 | } 36 | if visited.Visited(string(dbKey)) { 37 | continue 38 | } 39 | visited.Visit(string(dbKey)) 40 | storageValue, err := tx.GetOne(kv.PlainState, dbKey) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | if block%7000 == 0 { 46 | _, err := tree.Commit() 47 | if err != nil { 48 | return err 49 | } 50 | } 51 | 52 | storageKey := new(uint256.Int).SetBytes(dbKey[28:]) 53 | var storageValueFormatted []byte 54 | 55 | if len(storageValue) > 0 { 56 | storageValueFormatted = make([]byte, 32) 57 | int256ToVerkleFormat(new(uint256.Int).SetBytes(storageValue), storageValueFormatted) 58 | if err := tree.Insert(vtree.GetTreeKeyStorageSlot(dbKey[:20], storageKey), storageValueFormatted); err != nil { 59 | return err 60 | } 61 | } else { 62 | if err := tree.Insert(vtree.GetTreeKeyStorageSlot(dbKey[:20], storageKey), []byte{0}); err != nil { 63 | return err 64 | } 65 | } 66 | 67 | select { 68 | case <-logInterval.C: 69 | log.Info("Current Storage Progress", "num", block, "remaining", to-block) 70 | default: 71 | } 72 | } 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /ipfs-snapshot/snapshot.go: -------------------------------------------------------------------------------- 1 | package ipfssnapshot 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "os" 8 | "os/exec" 9 | "time" 10 | 11 | "github.com/c2h5oh/datasize" 12 | shell "github.com/ipfs/go-ipfs-api" 13 | "github.com/ledgerwatch/log/v3" 14 | ) 15 | 16 | type IPFSSnapshotSztd struct { 17 | cid string 18 | size uint64 19 | r io.Reader 20 | fname string 21 | it SnapshotIterator 22 | } 23 | 24 | func NewIpfsSnapshotSztd(cid string, size uint64, it SnapshotIterator) *IPFSSnapshotSztd { 25 | return &IPFSSnapshotSztd{ 26 | cid: cid, 27 | size: size, 28 | it: it, 29 | } 30 | } 31 | 32 | func (i *IPFSSnapshotSztd) LoadFile(sh *shell.Shell, path string, id uint64, ctx context.Context) error { 33 | out := fmt.Sprintf("%s%d.txt", path, id) 34 | file, err := os.Create(out) 35 | if err != nil { 36 | return err 37 | } 38 | file.Close() 39 | doneCh := make(chan struct{}) 40 | 41 | go func() { 42 | logInterval := time.NewTicker(10 * time.Second) 43 | for { 44 | select { 45 | case <-doneCh: 46 | return 47 | case <-ctx.Done(): 48 | return 49 | case <-logInterval.C: 50 | file, err := os.Open(out) 51 | if err != nil { 52 | panic(err) 53 | } 54 | fi, err := file.Stat() 55 | if err != nil { 56 | panic(err) 57 | } 58 | log.Info("Downloading Snapshot Progress", "id", id, "cid", i.cid, "progress", 59 | datasize.ByteSize(fi.Size()).HumanReadable()+"/"+datasize.ByteSize(i.size).HumanReadable()) 60 | } 61 | } 62 | }() 63 | err = sh.Get(i.cid, out) 64 | if err != nil { 65 | fmt.Fprintf(os.Stderr, "error: %s", err) 66 | os.Exit(1) 67 | } 68 | doneCh <- struct{}{} 69 | log.Info("Now start decompression of snapshot", "id", id) 70 | i.fname = out + ".dec" 71 | // Generation of decompressed object (I am sorry, this is a sin) 72 | if err := exec.Command("unzstd", out, "-o", i.fname).Run(); err != nil { 73 | return err 74 | } 75 | 76 | i.r, err = os.Open(i.fname) 77 | if err != nil { 78 | return err 79 | } 80 | // Get rid of compressed snapshot 81 | return os.Remove(out) 82 | } 83 | 84 | func (i *IPFSSnapshotSztd) Next() ([]byte, []byte, error) { 85 | return i.it.Next(i.r) 86 | } 87 | 88 | func (i *IPFSSnapshotSztd) Close() { 89 | os.Remove(i.fname) 90 | } 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VerkleIPFS 2 | 3 | VerkleIPFS is a proof-of-concept tool that allows to generate and retrieve Mainnet Verkle trees in significantly reduced time by using snapshot compressed and stored on the IPFS network. 4 | 5 | ## Rationale 6 | 7 | Computation Times of Verkle Trees is one of the main bottlenecks behind why it is unfeasible at current dates to switch the Ethereum Protocol from Merkle Trees to Verkle Trees, simply the chain would have to be stopped for 4-9 days so that all nodes can convert their data over to the other format. Verkle Trees are larger and takes more time to compute by nature than Merkle Patricia Trees, as a matter of fact, on Erigon Merkle Computation takes 40 Minutes and take 80 GB of disk, while Verkle Trees takes 18 Hours and 200 GB of disk, still not optimal. so the solution is to have a powerful machine generate the Verkle Tree, upload it as snapshot on IPFS, and then have common nodes operator download those snapshot for transiton the Verkle Tree from IPFS/Bittorent/Arweave/Etc... 8 | 9 | ## Technical Implementation Information 10 | 11 | So Geth and Erigon for now shares the same Database format and Erigon, for testing purposes so these snapshots are theorically compatible for both. the snapshots are ZSTD compressed by using the `zstd` cli of the dump format of verkle trees. The dump format just consist of a series of bytes that denotes Verkle trees as key/value pair: `Verkle Root => Rlp Node` and are a concatenation of the following: Verkle Root(32 bytes) + 8 bytes that repressent Big endian encoded node length + node RLP. Quite simple. 12 | 13 | ## Buidling and Runling 14 | 15 | ``` 16 | ipfs daemon 17 | go build 18 | ./verkleipfs --state-chaindata= 19 | ``` 20 | 21 | if you cannot specify `--state-chaindata` it will not catch up to chain tip and stop whenever snapshots ends. 22 | 23 | ## Disclaimer 24 | 25 | This is just going to work as long as I keep my daemon running, when I stop it the implementation will stop working, However I yoloed the snapshots on Pinata so worst thing that happens it will be slow to retrieve them but still will not take 18 hours :). Also Disk Requirement are just 250 GB of disk Avaiablem and 16 of RAM, otherwise you wont have enough storage to store this marvelous tree. 26 | 27 | ## Rough Benchmarks (probably not realistic but almost there) 28 | 29 | | Geth Default | 4-7 Days | 30 | |------------------------------- |------------------------------------------------------------ | 31 | | Erigon Default (Regeneration) | 17:52 Hours | 32 | | Geth (Preimages) | 17:52 Hours (untested but likely to be on par with Erigon) | 33 | | Erigon Default (Incremental) | 27:32 Hours | 34 | | Erigon (Snapshots) | 6:39 Hours | 35 | 36 | This a POC developed at an Hackathon so dont expect too much if it does not work for you or whatever, please dont be mad at me :(. 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Giulio2002/verkleipfs 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b 7 | github.com/gballet/go-verkle v0.0.0-20220829125900-a702d458d33c 8 | github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d 9 | github.com/holiman/uint256 v1.2.1 10 | github.com/ipfs/go-ipfs-api v0.3.0 11 | github.com/ledgerwatch/erigon v1.9.7-0.20221027082253-5a321d624093 12 | github.com/ledgerwatch/erigon-lib v0.0.0-20221026081821-45647a5e4231 13 | github.com/ledgerwatch/log/v3 v3.6.0 14 | ) 15 | 16 | require ( 17 | github.com/VictoriaMetrics/metrics v1.22.2 // indirect 18 | github.com/benbjohnson/clock v1.3.0 // indirect 19 | github.com/btcsuite/btcd v0.22.0-beta // indirect 20 | github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect 21 | github.com/crate-crypto/go-ipa v0.0.0-20220916134416-c5abbdbdf644 // indirect 22 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect 23 | github.com/go-stack/stack v1.8.1 // indirect 24 | github.com/gogo/protobuf v1.3.2 // indirect 25 | github.com/ipfs/go-cid v0.3.2 // indirect 26 | github.com/ipfs/go-ipfs-files v0.0.9 // indirect 27 | github.com/klauspost/cpuid/v2 v2.1.2 // indirect 28 | github.com/ledgerwatch/secp256k1 v1.0.0 // indirect 29 | github.com/libp2p/go-buffer-pool v0.1.0 // indirect 30 | github.com/libp2p/go-flow-metrics v0.1.0 // indirect 31 | github.com/libp2p/go-libp2p v0.23.2 // indirect 32 | github.com/libp2p/go-libp2p-core v0.20.1 // indirect 33 | github.com/libp2p/go-openssl v0.1.0 // indirect 34 | github.com/mattn/go-colorable v0.1.13 // indirect 35 | github.com/mattn/go-isatty v0.0.16 // indirect 36 | github.com/mattn/go-pointer v0.0.1 // indirect 37 | github.com/minio/sha256-simd v1.0.0 // indirect 38 | github.com/mitchellh/go-homedir v1.1.0 // indirect 39 | github.com/mr-tron/base58 v1.2.0 // indirect 40 | github.com/multiformats/go-base32 v0.1.0 // indirect 41 | github.com/multiformats/go-base36 v0.1.0 // indirect 42 | github.com/multiformats/go-multiaddr v0.7.0 // indirect 43 | github.com/multiformats/go-multibase v0.1.1 // indirect 44 | github.com/multiformats/go-multicodec v0.6.0 // indirect 45 | github.com/multiformats/go-multihash v0.2.1 // indirect 46 | github.com/multiformats/go-varint v0.0.6 // indirect 47 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect 48 | github.com/spaolacci/murmur3 v1.1.0 // indirect 49 | github.com/torquem-ch/mdbx-go v0.26.2 // indirect 50 | github.com/ugorji/go/codec v1.1.13 // indirect 51 | github.com/valyala/fastjson v1.6.3 // indirect 52 | github.com/valyala/fastrand v1.1.0 // indirect 53 | github.com/valyala/histogram v1.2.0 // indirect 54 | github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c // indirect 55 | go.uber.org/atomic v1.10.0 // indirect 56 | golang.org/x/crypto v0.1.0 // indirect 57 | golang.org/x/exp v0.0.0-20221018221608-02f3b879a704 // indirect 58 | golang.org/x/sync v0.1.0 // indirect 59 | golang.org/x/sys v0.1.0 // indirect 60 | google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e // indirect 61 | google.golang.org/protobuf v1.28.1 // indirect 62 | lukechampine.com/blake3 v1.1.7 // indirect 63 | ) 64 | -------------------------------------------------------------------------------- /verkle/account.go: -------------------------------------------------------------------------------- 1 | package verkle 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/holiman/uint256" 7 | "github.com/ledgerwatch/erigon-lib/kv" 8 | "github.com/ledgerwatch/erigon/common" 9 | "github.com/ledgerwatch/erigon/common/changeset" 10 | "github.com/ledgerwatch/erigon/common/dbutils" 11 | "github.com/ledgerwatch/erigon/core/rawdb" 12 | "github.com/ledgerwatch/erigon/core/types/accounts" 13 | "github.com/ledgerwatch/erigon/turbo/trie/vtree" 14 | "github.com/ledgerwatch/log/v3" 15 | ) 16 | 17 | func DoAccountAndCode(tx kv.Tx, tree *Tree, from, to uint64) error { 18 | cursor, err := tx.CursorDupSort(kv.AccountChangeSet) 19 | if err != nil { 20 | return err 21 | } 22 | defer cursor.Close() 23 | startKey := dbutils.EncodeBlockNumber(from) 24 | visited := NewVisitedMap() 25 | var key, value []byte 26 | logInterval := time.NewTicker(30 * time.Second) 27 | defer logInterval.Stop() 28 | for key, value, err = cursor.Seek(startKey); key != nil; key, value, err = cursor.Next() { 29 | if err != nil { 30 | return err 31 | } 32 | block, dbKey, _, err := changeset.DecodeAccounts(key, value) 33 | if err != nil { 34 | return err 35 | } 36 | if block > to { 37 | break 38 | } 39 | address := common.BytesToAddress(dbKey) 40 | if visited.Visited(address) { 41 | continue 42 | } 43 | visited.Visit(address) 44 | 45 | var account accounts.Account 46 | decoded, err := rawdb.ReadAccount(tx, address, &account) 47 | if err != nil { 48 | return err 49 | } 50 | versionKey := vtree.GetTreeKeyVersion(dbKey) 51 | if !decoded { 52 | if err := tree.DeleteAccount(versionKey, true); err != nil { 53 | return err 54 | } 55 | continue 56 | } 57 | isContract := account.Incarnation > 0 58 | codeSize := uint64(0) 59 | if isContract { 60 | code, err := tx.GetOne(kv.Code, account.CodeHash[:]) 61 | if err != nil { 62 | return err 63 | } 64 | codeSize = uint64(len(code)) 65 | // Chunkify contract code and build keys for each chunks and insert them in the tree 66 | chunkedCode := vtree.ChunkifyCode(code) 67 | offset := byte(0) 68 | offsetOverflow := false 69 | currentKey := vtree.GetTreeKeyCodeChunk(address[:], uint256.NewInt(0)) 70 | var chunks [][]byte 71 | var chunkKeys [][]byte 72 | // Write code chunks 73 | for i := 0; i < len(chunkedCode); i += 32 { 74 | chunks = append(chunks, common.CopyBytes(chunkedCode[i:i+32])) 75 | if currentKey[31]+offset < currentKey[31] || offsetOverflow { 76 | currentKey = vtree.GetTreeKeyCodeChunk(dbKey, uint256.NewInt(uint64(i)/32)) 77 | chunkKeys = append(chunkKeys, common.CopyBytes(currentKey)) 78 | offset = 1 79 | offsetOverflow = false 80 | } else { 81 | codeKey := common.CopyBytes(currentKey) 82 | codeKey[31] += offset 83 | chunkKeys = append(chunkKeys, common.CopyBytes(codeKey)) 84 | offset += 1 85 | // If offset overflows, handle it. 86 | offsetOverflow = offset == 0 87 | } 88 | } 89 | if err := tree.WriteContractCodeChunks(chunkKeys, chunks); err != nil { 90 | return err 91 | } 92 | } 93 | 94 | if err := tree.UpdateAccount(versionKey, codeSize, isContract, account); err != nil { 95 | return err 96 | } 97 | select { 98 | case <-logInterval.C: 99 | log.Info("Current Account Progress", "num", block, "remaining", to-block) 100 | default: 101 | } 102 | } 103 | return nil 104 | } 105 | -------------------------------------------------------------------------------- /verkle/tree.go: -------------------------------------------------------------------------------- 1 | package verkle 2 | 3 | import ( 4 | "encoding/binary" 5 | "time" 6 | 7 | "github.com/gballet/go-verkle" 8 | "github.com/holiman/uint256" 9 | "github.com/ledgerwatch/erigon-lib/kv" 10 | "github.com/ledgerwatch/erigon/common" 11 | "github.com/ledgerwatch/erigon/core/rawdb" 12 | "github.com/ledgerwatch/erigon/core/types/accounts" 13 | "github.com/ledgerwatch/erigon/turbo/trie/vtree" 14 | "github.com/ledgerwatch/log/v3" 15 | ) 16 | 17 | const maxInsertions = 20_000_000 18 | 19 | func int256ToVerkleFormat(x *uint256.Int, buffer []byte) { 20 | bbytes := x.ToBig().Bytes() 21 | if len(bbytes) > 0 { 22 | for i, b := range bbytes { 23 | buffer[len(bbytes)-i-1] = b 24 | } 25 | } 26 | } 27 | 28 | type Tree struct { 29 | db kv.RwTx 30 | node verkle.VerkleNode 31 | insertions uint64 32 | } 33 | 34 | func NewTree(db kv.RwTx, node verkle.VerkleNode) *Tree { 35 | return &Tree{ 36 | db: db, 37 | node: node, 38 | } 39 | } 40 | 41 | func (tree *Tree) flushVerkleNode(logInterval *time.Ticker) error { 42 | defer func() { 43 | if err := recover(); err != nil { 44 | return 45 | } 46 | tree.node = verkle.New() 47 | }() 48 | var err error 49 | totalInserted := 0 50 | tree.node.(*verkle.InternalNode).Flush(func(node verkle.VerkleNode) { 51 | if err != nil { 52 | return 53 | } 54 | 55 | err = rawdb.WriteVerkleNode(tree.db, node) 56 | if err != nil { 57 | return 58 | } 59 | totalInserted++ 60 | select { 61 | case <-logInterval.C: 62 | log.Info("Flushing Verkle nodes", "inserted", totalInserted) 63 | default: 64 | } 65 | }) 66 | return err 67 | } 68 | 69 | func (tree *Tree) UpdateAccount(versionKey []byte, codeSize uint64, isContract bool, acc accounts.Account) error { 70 | defer tree.commitIfPossible() 71 | 72 | resolverFunc := func(root []byte) ([]byte, error) { 73 | return tree.db.GetOne(kv.VerkleTrie, root) 74 | } 75 | 76 | var codeHashKey, nonceKey, balanceKey, codeSizeKey, nonce, balance, cs [32]byte 77 | copy(codeHashKey[:], versionKey[:31]) 78 | copy(nonceKey[:], versionKey[:31]) 79 | copy(balanceKey[:], versionKey[:31]) 80 | copy(codeSizeKey[:], versionKey[:31]) 81 | codeHashKey[31] = vtree.CodeKeccakLeafKey 82 | nonceKey[31] = vtree.NonceLeafKey 83 | balanceKey[31] = vtree.BalanceLeafKey 84 | codeSizeKey[31] = vtree.CodeSizeLeafKey 85 | // Process values 86 | int256ToVerkleFormat(&acc.Balance, balance[:]) 87 | binary.LittleEndian.PutUint64(nonce[:], acc.Nonce) 88 | 89 | // Insert in the tree 90 | if err := tree.node.Insert(versionKey, []byte{0}, resolverFunc); err != nil { 91 | return err 92 | } 93 | 94 | if err := tree.node.Insert(nonceKey[:], nonce[:], resolverFunc); err != nil { 95 | return err 96 | } 97 | 98 | if err := tree.node.Insert(balanceKey[:], balance[:], resolverFunc); err != nil { 99 | return err 100 | } 101 | 102 | if isContract { 103 | binary.LittleEndian.PutUint64(cs[:], codeSize) 104 | if err := tree.node.Insert(codeHashKey[:], acc.CodeHash[:], resolverFunc); err != nil { 105 | return err 106 | } 107 | if err := tree.node.Insert(codeSizeKey[:], cs[:], resolverFunc); err != nil { 108 | return err 109 | } 110 | } 111 | tree.insertions += 6 112 | return nil 113 | } 114 | 115 | func (tree *Tree) DeleteAccount(versionKey []byte, isContract bool) error { 116 | defer tree.commitIfPossible() 117 | 118 | resolverFunc := func(root []byte) ([]byte, error) { 119 | return tree.db.GetOne(kv.VerkleTrie, root) 120 | } 121 | 122 | var codeHashKey, nonceKey, balanceKey, codeSizeKey [32]byte 123 | copy(codeHashKey[:], versionKey[:31]) 124 | copy(nonceKey[:], versionKey[:31]) 125 | copy(balanceKey[:], versionKey[:31]) 126 | copy(codeSizeKey[:], versionKey[:31]) 127 | codeHashKey[31] = vtree.CodeKeccakLeafKey 128 | nonceKey[31] = vtree.NonceLeafKey 129 | balanceKey[31] = vtree.BalanceLeafKey 130 | codeSizeKey[31] = vtree.CodeSizeLeafKey 131 | 132 | // Insert in the tree 133 | if err := tree.node.Insert(versionKey, []byte{0}, resolverFunc); err != nil { 134 | return err 135 | } 136 | 137 | if err := tree.node.Insert(nonceKey[:], []byte{0}, resolverFunc); err != nil { 138 | return err 139 | } 140 | 141 | if err := tree.node.Insert(balanceKey[:], []byte{0}, resolverFunc); err != nil { 142 | return err 143 | } 144 | 145 | if isContract { 146 | if err := tree.node.Insert(codeHashKey[:], []byte{0}, resolverFunc); err != nil { 147 | return err 148 | } 149 | if err := tree.node.Insert(codeSizeKey[:], []byte{0}, resolverFunc); err != nil { 150 | return err 151 | } 152 | tree.insertions += 2 153 | } 154 | tree.insertions++ 155 | return nil 156 | } 157 | 158 | func (tree *Tree) Insert(key, value []byte) error { 159 | resolverFunc := func(root []byte) ([]byte, error) { 160 | return tree.db.GetOne(kv.VerkleTrie, root) 161 | } 162 | defer tree.commitIfPossible() 163 | tree.insertions += 3 164 | return tree.node.Insert(key, value, resolverFunc) 165 | } 166 | 167 | func (tree *Tree) WriteContractCodeChunks(codeKeys [][]byte, chunks [][]byte) error { 168 | resolverFunc := func(root []byte) ([]byte, error) { 169 | return tree.db.GetOne(kv.VerkleTrie, root) 170 | } 171 | defer tree.commitIfPossible() 172 | for i, codeKey := range codeKeys { 173 | if err := tree.node.Insert(codeKey, chunks[i], resolverFunc); err != nil { 174 | return err 175 | } 176 | tree.insertions++ 177 | } 178 | return nil 179 | } 180 | 181 | func (tree *Tree) Commit() (common.Hash, error) { 182 | logInterval := time.NewTicker(30 * time.Second) 183 | defer logInterval.Stop() 184 | 185 | commitment := tree.node.ComputeCommitment().Bytes() 186 | return common.BytesToHash(commitment[:]), tree.flushVerkleNode(logInterval) 187 | } 188 | 189 | func (tree *Tree) commitIfPossible() { 190 | if tree.insertions >= maxInsertions { 191 | if _, err := tree.Commit(); err != nil { 192 | panic(err) 193 | } 194 | tree.insertions = 0 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // "context" 5 | 6 | "context" 7 | "encoding/hex" 8 | "flag" 9 | "sync/atomic" 10 | "time" 11 | 12 | ipfssnapshot "github.com/Giulio2002/verkleipfs/ipfs-snapshot" 13 | "github.com/Giulio2002/verkleipfs/verkle" 14 | shell "github.com/ipfs/go-ipfs-api" 15 | "github.com/ledgerwatch/erigon-lib/kv" 16 | "github.com/ledgerwatch/erigon-lib/kv/mdbx" 17 | "github.com/ledgerwatch/erigon/common" 18 | "github.com/ledgerwatch/erigon/core/rawdb" 19 | "github.com/ledgerwatch/erigon/eth/stagedsync/stages" 20 | "github.com/ledgerwatch/log/v3" 21 | ) 22 | 23 | const workers = 3 24 | 25 | func IncrementVerkleTree(verkleDb kv.RwDB, stateChaindata string) error { 26 | start := time.Now() 27 | 28 | stateDb, err := mdbx.Open(stateChaindata, log.Root(), true) 29 | if err != nil { 30 | log.Error("Error while opening database", "err", err.Error()) 31 | return err 32 | } 33 | defer stateDb.Close() 34 | ctx := context.Background() 35 | vTx, err := verkleDb.BeginRw(ctx) 36 | if err != nil { 37 | return err 38 | } 39 | defer vTx.Rollback() 40 | 41 | tx, err := stateDb.BeginRo(ctx) 42 | if err != nil { 43 | return err 44 | } 45 | defer tx.Rollback() 46 | ticker := time.NewTicker(4 * time.Second) 47 | Loop: 48 | for { 49 | select { 50 | case <-ticker.C: 51 | 52 | from, err := stages.GetStageProgress(vTx, stages.VerkleTrie) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | to, err := stages.GetStageProgress(tx, stages.Execution) 58 | if err != nil { 59 | return err 60 | } 61 | if from >= to { 62 | continue 63 | } 64 | 65 | rootHash, err := rawdb.ReadVerkleRoot(tx, from) 66 | if err != nil { 67 | return err 68 | } 69 | rootNode, err := rawdb.ReadVerkleNode(vTx, rootHash) 70 | if err != nil { 71 | return err 72 | } 73 | 74 | tree := verkle.NewTree(vTx, rootNode) 75 | if err := verkle.DoAccountAndCode(tx, tree, from, to); err != nil { 76 | return err 77 | } 78 | if err = verkle.DoStorage(tx, tree, from, to); err != nil { 79 | return err 80 | } 81 | var root common.Hash 82 | if root, err = tree.Commit(); err != nil { 83 | return err 84 | } 85 | if err := rawdb.WriteVerkleRoot(vTx, to, root); err != nil { 86 | return err 87 | } 88 | if err := stages.SaveStageProgress(vTx, stages.VerkleTrie, to); err != nil { 89 | return err 90 | } 91 | 92 | log.Info("Imported Verkle Segments", "root", root, "number", to, "elapesed", time.Since(start)) 93 | start = time.Now() 94 | if err := vTx.Commit(); err != nil { 95 | return err 96 | } 97 | vTx, err = verkleDb.BeginRw(ctx) 98 | if err != nil { 99 | return err 100 | } 101 | 102 | tx, err = stateDb.BeginRo(ctx) 103 | if err != nil { 104 | return err 105 | } 106 | case <-ctx.Done(): 107 | break Loop 108 | } 109 | } 110 | 111 | return vTx.Commit() 112 | } 113 | 114 | func waitUntilValue(v *atomic.Value, c int) { 115 | for v.Load().(int) > c { 116 | time.Sleep(200 * time.Millisecond) 117 | } 118 | } 119 | 120 | func main() { 121 | ctx := context.Background() 122 | start := time.Now() 123 | // Log handling 124 | log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(3), log.StderrHandler)) 125 | // Flags settings 126 | daemonUrl := flag.String("daemon-url", "localhost:5001", "IPFS Daemon url") 127 | stateDb := flag.String("state-chaindata", "", "Main erigon chain data") 128 | verkleDb := flag.String("verkle-chaindata", "verle-db", "output verkle") 129 | tmpdir := flag.String("tmpdir", "/tmp/", "temorary files dir") 130 | flag.Parse() 131 | // Load Ipfs 132 | log.Info("Disclaimer: You need good internet connection + 250 GB of free space") 133 | sh := shell.NewShell(*daemonUrl) 134 | var counter atomic.Value 135 | counter.Store(0) 136 | snapshots := ipfssnapshot.MainnetVerkleIpfsSnapshot() 137 | // Download snapshots concurrently 138 | for i, snapshot := range snapshots { 139 | counter.Store(counter.Load().(int) + 1) 140 | go func(snapshot *ipfssnapshot.IPFSSnapshotSztd, i int) { 141 | log.Info("Started Processing snapshot", "id", i) 142 | if err := snapshot.LoadFile(sh, *tmpdir, uint64(i), ctx); err != nil { 143 | panic(err) 144 | } 145 | counter.Store(counter.Load().(int) - 1) 146 | log.Info("Finished Processing snapshot", "id", i) 147 | }(snapshot, i) 148 | if counter.Load().(int) > workers-1 { 149 | waitUntilValue(&counter, workers-1) 150 | } 151 | } 152 | // Wait for snapshots to end 153 | waitUntilValue(&counter, 0) 154 | // Create new database 155 | db, err := mdbx.Open(*verkleDb, log.Root(), false) 156 | if err != nil { 157 | panic(err) 158 | } 159 | 160 | tx, err := db.BeginRw(context.Background()) 161 | if err != nil { 162 | panic(err) 163 | } 164 | log.Info("Now starting dumping process to database") 165 | // Convert snapshot format to erigon format 166 | ticker := time.NewTicker(30 * time.Second) 167 | for _, snapshot := range snapshots { 168 | for k, v, err := snapshot.Next(); k != nil; k, v, err = snapshot.Next() { 169 | if err != nil { 170 | panic(err) 171 | } 172 | if len(v) == 0 { 173 | continue 174 | } 175 | if err := tx.Put(kv.VerkleTrie, k, v); err != nil { 176 | log.Error("Error", "err", err) 177 | return 178 | } 179 | select { 180 | case <-ticker.C: 181 | log.Info("Progress", "key", hex.EncodeToString(k)) 182 | default: 183 | } 184 | } 185 | snapshot.Close() 186 | } 187 | 188 | // Write snapshot metadata 189 | if err := rawdb.WriteVerkleRoot(tx, ipfssnapshot.MainnetVerkleUpdateBlock, 190 | ipfssnapshot.MainnetVerkleUpdateRoot); err != nil { 191 | log.Error("Err", "err", err) 192 | return 193 | } 194 | 195 | if err := stages.SaveStageProgress(tx, stages.VerkleTrie, ipfssnapshot.MainnetVerkleUpdateBlock); err != nil { 196 | log.Error("Err", "err", err) 197 | return 198 | } 199 | tx.Commit() 200 | log.Info("Processed snapshot to block", "number", ipfssnapshot.MainnetVerkleUpdateBlock, "elapsed", time.Since(start)) 201 | // Catch up with chain tip. 202 | if *stateDb != "" { 203 | if err := IncrementVerkleTree(db, *stateDb); err != nil { 204 | log.Error("Err", "err", err) 205 | return 206 | } 207 | } else { 208 | log.Warn("No erigon db specified, stopping...") 209 | } 210 | 211 | } 212 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/VictoriaMetrics/metrics v1.22.2 h1:A6LsNidYwkAHetxsvNFaUWjtzu5ltdgNEoS6i7Bn+6I= 4 | github.com/VictoriaMetrics/metrics v1.22.2/go.mod h1:rAr/llLpEnAdTehiNlUxKgnjcOuROSzpw0GvjpEbvFc= 5 | github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 6 | github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= 7 | github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 8 | github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= 9 | github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= 10 | github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= 11 | github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= 12 | github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= 13 | github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= 14 | github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 15 | github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= 16 | github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= 17 | github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 18 | github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 19 | github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= 20 | github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= 21 | github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= 22 | github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= 23 | github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= 24 | github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= 25 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 26 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 27 | github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= 28 | github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= 29 | github.com/crate-crypto/go-ipa v0.0.0-20220916134416-c5abbdbdf644 h1:1BOsVjUetPH2Lqv71Dh6uKLVj9WKdDr5KY57KZBbsWU= 30 | github.com/crate-crypto/go-ipa v0.0.0-20220916134416-c5abbdbdf644/go.mod h1:gFnFS95y8HstDP6P9pPwzrxOOC5TRDkwbM+ao15ChAI= 31 | github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 32 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 33 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 34 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 35 | github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= 36 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= 37 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= 38 | github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= 39 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 40 | github.com/gballet/go-verkle v0.0.0-20220829125900-a702d458d33c h1:zN3+0FLRcsoX/lVcgGC0EBtNcBvCXJWgMDmTbEz8pnw= 41 | github.com/gballet/go-verkle v0.0.0-20220829125900-a702d458d33c/go.mod h1:o/XfIXWi4/GqbQirfRm5uTbXMG5NpqxkxblnbZ+QM9I= 42 | github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= 43 | github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= 44 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 45 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 46 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 47 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 48 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 49 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 50 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 51 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 52 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 53 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 54 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 55 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 56 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 57 | github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= 58 | github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= 59 | github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 60 | github.com/holiman/uint256 v1.2.1 h1:XRtyuda/zw2l+Bq/38n5XUoEF72aSOu/77Thd9pPp2o= 61 | github.com/holiman/uint256 v1.2.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= 62 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 63 | github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 64 | github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc= 65 | github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw= 66 | github.com/ipfs/go-ipfs-api v0.3.0 h1:ZzVrsTV31Z53ZlUare6a5UJ46lC7lW93q/s1/fXyATk= 67 | github.com/ipfs/go-ipfs-api v0.3.0/go.mod h1:A1naQGm0Jg01GxDq7oDyVSZxt20SuRTNIBFNZJgPDmg= 68 | github.com/ipfs/go-ipfs-files v0.0.9 h1:OFyOfmuVDu9c5YtjSDORmwXzE6fmZikzZpzsnNkgFEg= 69 | github.com/ipfs/go-ipfs-files v0.0.9/go.mod h1:aFv2uQ/qxWpL/6lidWvnSQmaVqCrf0TBGoUr+C1Fo84= 70 | github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= 71 | github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= 72 | github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 73 | github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 74 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 75 | github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 76 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 77 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 78 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 79 | github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 80 | github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 81 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 82 | github.com/klauspost/cpuid/v2 v2.1.2 h1:XhdX4fqAJUA0yj+kUwMavO0hHrSPAecYdYf1ZmxHvak= 83 | github.com/klauspost/cpuid/v2 v2.1.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= 84 | github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= 85 | github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= 86 | github.com/ledgerwatch/erigon v1.9.7-0.20221027082253-5a321d624093 h1:o7JpkJ/pl7Co7kuvCPcmZbgdMA6fvJbEW1M7NYRMk9g= 87 | github.com/ledgerwatch/erigon v1.9.7-0.20221027082253-5a321d624093/go.mod h1:52yJaXRqcmFxAvv1yow2ULYUXlAuhppw/xSCJyTCF24= 88 | github.com/ledgerwatch/erigon-lib v0.0.0-20221026081821-45647a5e4231 h1:ten0LCo3boEK5rQO+RKrFQWqtqT3TrK9t/55rfhEkLo= 89 | github.com/ledgerwatch/erigon-lib v0.0.0-20221026081821-45647a5e4231/go.mod h1:IP/aYFvEPlHJ1THh03i+qbHFil+N3enYhTEPVQLFJBw= 90 | github.com/ledgerwatch/log/v3 v3.6.0 h1:JBUSK1epPyutUrz7KYDTcJtQLEHnehECRpKbM1ugy5M= 91 | github.com/ledgerwatch/log/v3 v3.6.0/go.mod h1:L+Sp+ma/h205EdCjviZECjGEvYUYEyXSdiuHNZzg+xQ= 92 | github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= 93 | github.com/ledgerwatch/secp256k1 v1.0.0/go.mod h1:SPmqJFciiF/Q0mPt2jVs2dTr/1TZBTIA+kPMmKgBAak= 94 | github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= 95 | github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= 96 | github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= 97 | github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= 98 | github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= 99 | github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= 100 | github.com/libp2p/go-libp2p v0.23.2 h1:yqyTeKQJyofWXxEv/eEVUvOrGdt/9x+0PIQ4N1kaxmE= 101 | github.com/libp2p/go-libp2p v0.23.2/go.mod h1:s9DEa5NLR4g+LZS+md5uGU4emjMWFiqkZr6hBTY8UxI= 102 | github.com/libp2p/go-libp2p-core v0.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= 103 | github.com/libp2p/go-libp2p-core v0.20.1 h1:fQz4BJyIFmSZAiTbKV8qoYhEH5Dtv/cVhZbG3Ib/+Cw= 104 | github.com/libp2p/go-libp2p-core v0.20.1/go.mod h1:6zR8H7CvQWgYLsbG4on6oLNSGcyKaYFSEYyDt51+bIY= 105 | github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= 106 | github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= 107 | github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= 108 | github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc= 109 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 110 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 111 | github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= 112 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 113 | github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= 114 | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= 115 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 116 | github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 117 | github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 118 | github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= 119 | github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 120 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 121 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 122 | github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 123 | github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 124 | github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 125 | github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 126 | github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 127 | github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= 128 | github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 129 | github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= 130 | github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= 131 | github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= 132 | github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= 133 | github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc= 134 | github.com/multiformats/go-multiaddr v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= 135 | github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= 136 | github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= 137 | github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= 138 | github.com/multiformats/go-multicodec v0.6.0 h1:KhH2kSuCARyuJraYMFxrNO3DqIaYhOdS039kbhgVwpE= 139 | github.com/multiformats/go-multicodec v0.6.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw= 140 | github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 141 | github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 142 | github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= 143 | github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= 144 | github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 145 | github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= 146 | github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 147 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 148 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 149 | github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 150 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 151 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 152 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 153 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= 154 | github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= 155 | github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 156 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 157 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 158 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 159 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 160 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 161 | github.com/torquem-ch/mdbx-go v0.26.2 h1:9qpMNjZQICYVJzp3ic/9d8gfxnLA800mCY6+jkqtju4= 162 | github.com/torquem-ch/mdbx-go v0.26.2/go.mod h1:T2fsoJDVppxfAPTLd1svUgH1kpPmeXdPESmroSHcL1E= 163 | github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc= 164 | github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn4= 165 | github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU= 166 | github.com/valyala/fastjson v1.6.3 h1:tAKFnnwmeMGPbwJ7IwxcTPCNr3uIzoIj3/Fh90ra4xc= 167 | github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= 168 | github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= 169 | github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= 170 | github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= 171 | github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= 172 | github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c h1:GGsyl0dZ2jJgVT+VvWBf/cNijrHRhkrTjkmp5wg7li0= 173 | github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c/go.mod h1:xxcJeBb7SIUl/Wzkz1eVKJE/CB34YNrqX2TQI6jY9zs= 174 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 175 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 176 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 177 | go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= 178 | go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 179 | golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 180 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 181 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 182 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 183 | golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 184 | golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 185 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 186 | golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= 187 | golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= 188 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 189 | golang.org/x/exp v0.0.0-20221018221608-02f3b879a704 h1:qeTd8Mtg7Z9G839eB0/DhF2vU3ZeXcP6vwAY/IqVRPM= 190 | golang.org/x/exp v0.0.0-20221018221608-02f3b879a704/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= 191 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 192 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 193 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 194 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 195 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 196 | golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 197 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 198 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 199 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 200 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 201 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 202 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 203 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 204 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 205 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 206 | golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= 207 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 208 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 209 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 210 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 211 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 212 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 213 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 214 | golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= 215 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 216 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 217 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 218 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 219 | golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 220 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 221 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 222 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 223 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 224 | golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 225 | golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 226 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 227 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= 228 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 229 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 230 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 231 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 232 | golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= 233 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 234 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 235 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 236 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 237 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 238 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 239 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 240 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 241 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 242 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 243 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 244 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 245 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 246 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 247 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 248 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 249 | google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e h1:halCgTFuLWDRD61piiNSxPsARANGD3Xl16hPrLgLiIg= 250 | google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= 251 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 252 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 253 | google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= 254 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 255 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 256 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 257 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 258 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 259 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 260 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 261 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 262 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 263 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 264 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 265 | lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= 266 | lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= 267 | --------------------------------------------------------------------------------