diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b50e6d98..49855cdb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,13 +22,13 @@ jobs: uses: actions/cache@v3 with: path: | - ./unicorn/build + ./diffmips/unicorn/build key: unicorn-build-{{ hashFiles('/tmp/unicorn-commit-hash.txt') }} restore-keys: | unicorn-build-{{ hashFiles('/tmp/unicorn-commit-hash.txt') }} - name: install libunicorn - working-directory: . + working-directory: ./diffmips run: make libunicorn - uses: actions/cache@v3 with: @@ -45,11 +45,17 @@ jobs: key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go-${{ matrix.go-version }}- - - name: golangci-lint + - name: main golangci-lint uses: golangci/golangci-lint-action@v3 with: version: v1.52 - working-directory: mipsevm + working-directory: ./ + skip-cache: true # we already have go caching + - name: diffmips golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.52 + working-directory: ./diffmips skip-cache: true # we already have go caching - name: Build examples working-directory: ./example @@ -60,3 +66,6 @@ jobs: - name: mipsevm tests working-directory: ./mipsevm run: go test ./... + - name: diffmips tests + working-directory: ./diffmips + run: go test ./... diff --git a/.gitmodules b/.gitmodules index e113c984..28cf387c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "unicorn"] - path = unicorn + path = diffmips/unicorn url = https://github.com/unicorn-engine/unicorn.git diff --git a/Makefile b/Makefile index 6f048c8e..3fc495b4 100644 --- a/Makefile +++ b/Makefile @@ -1,62 +1,12 @@ SHELL := /bin/bash -build: submodules libunicorn contracts +build: contracts .PHONY: build -submodules: - # CI will checkout submodules on its own (and fails on these commands) - if [[ -z "$$GITHUB_ENV" ]]; then \ - git submodule init; \ - git submodule update; \ - fi -.PHONY: submodules - -# Approximation, use `make libunicorn_rebuild` to force. -unicorn/build: unicorn/CMakeLists.txt - mkdir -p unicorn/build - cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release - # Not sure why, but the second invocation is needed for fresh installs on MacOS. - if [ "$(shell uname)" == "Darwin" ]; then \ - cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release; \ - fi - -# Rebuild whenever anything in the unicorn/ directory changes. -unicorn/build/libunicorn.so: unicorn/build unicorn - cd unicorn/build && make -j8 - # The Go linker / runtime expects dynamic libraries in the unicorn/ dir. - find ./unicorn/build -name "libunicorn.*" | xargs -L 1 -I {} cp {} ./unicorn/ - # Update timestamp on libunicorn.so to make it more recent than the build/ dir. - # On Mac this will create a new empty file (dyn libraries are .dylib), but works - # fine for the purpose of avoiding recompilation. - touch unicorn/build/libunicorn.so - -libunicorn: unicorn/build/libunicorn.so -.PHONY: libunicorn - -libunicorn_rebuild: - touch unicorn/CMakeLists.txt - make libunicorn -.PHONY: libunicorn_rebuild - -# Must be a definition and not a rule, otherwise it gets only called once and -# not before each test as we wish. -define clear_cache - rm -rf /tmp/cannon - mkdir -p /tmp/cannon -endef - -clear_cache: - $(call clear_cache) -.PHONY: clear_cache - -clean: - rm -f unicorn/libunicorn.* -.PHONY: clean - contracts: cd contracts && forge build .PHONY: contracts -test: libunicorn +test: cd mipsevm && go test -v ./... .PHONY: test diff --git a/README.md b/README.md index 59eb17f0..5d7a663d 100644 --- a/README.md +++ b/README.md @@ -24,18 +24,11 @@ contracts -- A MIPS emulator implementation, using merkleized state and a pre-im example -- Example programs that can be run and proven with Cannon. extra -- Extra scripts and legacy contracts, deprecated. mipsevm -- Go tooling to test the onchain MIPS implementation, and generate proof data. -unicorn -- Sub-module, used by mipsevm for offchain MIPS emulation. +diffmips -- MIPS diff testing, to ensure correctness of the main Cannon implementation, with isolated dependencies. ``` ## Building -### `unicorn` - -To build unicorn from source (git sub-module), run: -``` -make libunicorn -``` - ### `contracts` The contracts are compiled with [`forge`](https://github.com/foundry-rs/foundry). @@ -43,17 +36,6 @@ The contracts are compiled with [`forge`](https://github.com/foundry-rs/foundry) make contracts ``` -### `mipsevm` - -This requires `unicorn` to be built, as well as the `contracts` for testing. - -To test: -``` -make test -``` - -Also see notes in `mipsevm/go.mod` about the Unicorn dependency, if you wish to use Cannon as a Go library. - ## License MIT, see [`LICENSE`](./LICENSE) file. diff --git a/cmd/load_elf.go b/cmd/load_elf.go index 1700864d..d226c6bc 100644 --- a/cmd/load_elf.go +++ b/cmd/load_elf.go @@ -6,7 +6,7 @@ import ( "github.com/urfave/cli/v2" - "cannon/mipsevm" + "github.com/ethereum-optimism/cannon/mipsevm" ) var ( diff --git a/cmd/matcher.go b/cmd/matcher.go index fdf84f71..a383ce43 100644 --- a/cmd/matcher.go +++ b/cmd/matcher.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "cannon/mipsevm" + "github.com/ethereum-optimism/cannon/mipsevm" ) type StepMatcher func(st *mipsevm.State) bool diff --git a/cmd/run.go b/cmd/run.go index 0e91adf4..f2dbd5d7 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -12,7 +12,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli/v2" - "cannon/mipsevm" + "github.com/ethereum-optimism/cannon/mipsevm" "github.com/ethereum-optimism/cannon/preimage" ) @@ -182,13 +182,7 @@ func Run(ctx *cli.Context) error { if err != nil { return err } - //mu, err := mipsevm.NewUnicorn() - //if err != nil { - // return fmt.Errorf("failed to create unicorn emulator: %w", err) - //} - //if err := mipsevm.LoadUnicorn(state, mu); err != nil { - // return fmt.Errorf("failed to load state into unicorn emulator: %w", err) - //} + l := Logger(os.Stderr, log.LvlInfo) outLog := &mipsevm.LoggingWriter{Name: "program std-out", Log: l} errLog := &mipsevm.LoggingWriter{Name: "program std-err", Log: l} @@ -232,15 +226,11 @@ func Run(ctx *cli.Context) error { } } - //us, err := mipsevm.NewUnicornState(mu, state, po, outLog, errLog) - //if err != nil { - // return fmt.Errorf("failed to setup instrumented VM state: %w", err) - //} - us := mipsevm.NewNonUnicornState(state, po, outLog, errLog) + us := mipsevm.NewInstrumentedState(state, po, outLog, errLog) proofFmt := ctx.String(RunProofFmtFlag.Name) snapshotFmt := ctx.String(RunSnapshotFmtFlag.Name) - stepFn := us.NonUnicornStep + stepFn := us.Step if po.cmd != nil { stepFn = Guard(po.cmd.ProcessState, stepFn) } diff --git a/diffmips/Makefile b/diffmips/Makefile new file mode 100644 index 00000000..9c269068 --- /dev/null +++ b/diffmips/Makefile @@ -0,0 +1,47 @@ +SHELL := /bin/bash + +build: submodules libunicorn +.PHONY: build + +submodules: + # CI will checkout submodules on its own (and fails on these commands) + if [[ -z "$$GITHUB_ENV" ]]; then \ + git submodule init; \ + git submodule update; \ + fi +.PHONY: submodules + +# Approximation, use `make libunicorn_rebuild` to force. +unicorn/build: unicorn/CMakeLists.txt + mkdir -p unicorn/build + cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release + # Not sure why, but the second invocation is needed for fresh installs on MacOS. + if [ "$(shell uname)" == "Darwin" ]; then \ + cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release; \ + fi + +# Rebuild whenever anything in the unicorn/ directory changes. +unicorn/build/libunicorn.so: unicorn/build unicorn + cd unicorn/build && make -j8 + # The Go linker / runtime expects dynamic libraries in the unicorn/ dir. + find ./unicorn/build -name "libunicorn.*" | xargs -L 1 -I {} cp {} ./unicorn/ + # Update timestamp on libunicorn.so to make it more recent than the build/ dir. + # On Mac this will create a new empty file (dyn libraries are .dylib), but works + # fine for the purpose of avoiding recompilation. + touch unicorn/build/libunicorn.so + +libunicorn: unicorn/build/libunicorn.so +.PHONY: libunicorn + +libunicorn_rebuild: + touch unicorn/CMakeLists.txt + make libunicorn +.PHONY: libunicorn_rebuild + +clean: + rm -f unicorn/libunicorn.* +.PHONY: clean + +test: + cd unicorntest && go test -v ./... +.PHONY: test diff --git a/diffmips/README.md b/diffmips/README.md new file mode 100644 index 00000000..0d9d2791 --- /dev/null +++ b/diffmips/README.md @@ -0,0 +1,28 @@ +# diffmips + +This is a collection of MIPS testing tools. +The Unicorn emulator first backed Cannon directly, but has been separated as a testing-only tool, +and is replaced with a Go implementation of the minimal MIPS functionality. + +Directory layout +``` +unicorn -- Sub-module, used by mipsevm for offchain MIPS emulation. +unicorntest -- Go module with Go tests, diffed against the Cannon state. [Work in Progress] +``` + +### `unicorn` + +To build unicorn from source (git sub-module), run: +``` +make libunicorn +``` + +### `unicorntest` + +This requires `unicorn` to be built, as well as the `contracts` for testing. + +To test: +``` +make test +``` + diff --git a/unicorn b/diffmips/unicorn similarity index 100% rename from unicorn rename to diffmips/unicorn diff --git a/diffmips/unicorntest/diff_test.go b/diffmips/unicorntest/diff_test.go new file mode 100644 index 00000000..82f0c552 --- /dev/null +++ b/diffmips/unicorntest/diff_test.go @@ -0,0 +1,68 @@ +package unicorntest + +import ( + "bytes" + "os" + "path" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/cannon/mipsevm" +) + +// baseAddrStart - baseAddrEnd is used in tests to write the results to +const baseAddrEnd = 0xbf_ff_ff_f0 +const baseAddrStart = 0xbf_c0_00_00 + +// endAddr is used as return-address for tests +const endAddr = 0xa7ef00d0 + +func TestState(t *testing.T) { + testFiles, err := os.ReadDir("../../mipsevm/open_mips_tests/test/bin") + require.NoError(t, err) + + for _, f := range testFiles { + t.Run(f.Name(), func(t *testing.T) { + if f.Name() == "oracle.bin" { + t.Skip("oracle test needs to be updated to use syscall pre-image oracle") + } + fn := path.Join("../../mipsevm/open_mips_tests/test/bin", f.Name()) + + programMem, err := os.ReadFile(fn) + require.NoError(t, err) + state := &mipsevm.State{PC: 0, NextPC: 4, Memory: mipsevm.NewMemory()} + err = state.Memory.SetMemoryRange(0, bytes.NewReader(programMem)) + require.NoError(t, err, "load program into state") + + // set the return address ($ra) to jump into when test completes + state.Registers[31] = endAddr + + mu, err := NewUnicorn() + require.NoError(t, err, "load unicorn") + defer mu.Close() + + require.NoError(t, mu.MemMap(baseAddrStart, ((baseAddrEnd-baseAddrStart)&^mipsevm.PageAddrMask)+mipsevm.PageSize)) + require.NoError(t, mu.MemMap(endAddr&^mipsevm.PageAddrMask, mipsevm.PageSize)) + + err = LoadUnicorn(state, mu) + require.NoError(t, err, "load state into unicorn") + + us, err := NewUnicornState(mu, state, nil, os.Stdout, os.Stderr) + require.NoError(t, err, "hook unicorn to state") + + for i := 0; i < 1000; i++ { + if us.state.PC == endAddr { + break + } + _, err := us.Step(false) + require.NoError(t, err) + } + require.Equal(t, uint32(endAddr), us.state.PC, "must reach end") + // inspect test result + done, result := state.Memory.GetMemory(baseAddrEnd+4), state.Memory.GetMemory(baseAddrEnd+8) + require.Equal(t, done, uint32(1), "must be done") + require.Equal(t, result, uint32(1), "must have success result") + }) + } +} diff --git a/diffmips/unicorntest/go.mod b/diffmips/unicorntest/go.mod new file mode 100644 index 00000000..bf9b73c9 --- /dev/null +++ b/diffmips/unicorntest/go.mod @@ -0,0 +1,76 @@ +module unicorntest + +go 1.20 + +require ( + github.com/ethereum-optimism/cannon v0.0.0 + github.com/stretchr/testify v1.8.2 + github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650 +) + +require ( + github.com/DataDog/zstd v1.5.2 // indirect + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/VictoriaMetrics/fastcache v1.6.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect + github.com/cockroachdb/redact v1.1.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/edsrzf/mmap-go v1.0.0 // indirect + github.com/ethereum-optimism/cannon/preimage v0.0.0 // indirect + github.com/ethereum/go-ethereum v1.11.5 // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.0 // indirect + github.com/klauspost/compress v1.15.15 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.39.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect + golang.org/x/crypto v0.8.0 // indirect + golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/ethereum-optimism/cannon v0.0.0 => ../../ + +replace github.com/ethereum-optimism/cannon/preimage v0.0.0 => ../../preimage + +// We need to point to our local Unicorn clone for the shared object to be located correctly in all our Go commands. +// See https://github.com/unicorn-engine/unicorn/blob/7b8c63dfe650b5d4d2bf684526161971925e6350/bindings/go/unicorn/unicorn.go#L11 +// The -L../../../ -lunicorn points to the unicorn root directory relative to the unicorn Go bindings. +// Run make libunicorn in the Cannon repo root to create this libunicorn.so dependency. +// +// If you are importing this as a library you will need to also point it to a unicorn clone with a `replace` +// in your `go.mod` (or `go.work`), or use `go build -ldflags="-L../path/to/my/unicorn/build -lunicorn`, +// or simply have it installed globally so Go can find it. The `replace` here will be ignored as library-user. +replace github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650 => ../unicorn diff --git a/diffmips/unicorntest/go.sum b/diffmips/unicorntest/go.sum new file mode 100644 index 00000000..76fd5c35 --- /dev/null +++ b/diffmips/unicorntest/go.sum @@ -0,0 +1,451 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +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/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/go-ethereum v1.11.5 h1:3M1uan+LAUvdn+7wCEFrcMM4LJTeuxDrPTg/f31a5QQ= +github.com/ethereum/go-ethereum v1.11.5/go.mod h1:it7x0DWnTDMfVFdXcU6Ti4KEFQynLHVRarcSlPr0HBo= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +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= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +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= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +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/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +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= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +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/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +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= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +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= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/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-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-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-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/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-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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.3/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-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +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= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +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/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +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.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.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +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= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/mipsevm/unicorn.go b/diffmips/unicorntest/unicorn.go similarity index 88% rename from mipsevm/unicorn.go rename to diffmips/unicorntest/unicorn.go index aea9b560..4867c86f 100644 --- a/mipsevm/unicorn.go +++ b/diffmips/unicorntest/unicorn.go @@ -1,4 +1,4 @@ -package mipsevm +package unicorntest import ( "encoding/binary" @@ -6,7 +6,8 @@ import ( "io" "log" "math" - "sync" + + "github.com/ethereum-optimism/cannon/mipsevm" uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn" ) @@ -17,11 +18,9 @@ type PreimageOracle interface { } type UnicornState struct { - sync.Mutex - mu uc.Unicorn - state *State + state *mipsevm.State stdOut io.Writer stdErr io.Writer @@ -55,16 +54,7 @@ const ( MipsEINVAL = 0x16 ) -func NewNonUnicornState(state *State, po PreimageOracle, stdOut, stdErr io.Writer) *UnicornState { - return &UnicornState{ - state: state, - stdOut: stdOut, - stdErr: stdErr, - preimageOracle: po, - } -} - -func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, stdErr io.Writer) (*UnicornState, error) { +func NewUnicornState(mu uc.Unicorn, state *mipsevm.State, po PreimageOracle, stdOut, stdErr io.Writer) (*UnicornState, error) { m := &UnicornState{ mu: mu, state: state, @@ -118,8 +108,8 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std switch syscallNum { case 4090: // mmap sz := a1 - if sz&pageAddrMask != 0 { // adjust size to align with page size - sz += pageSize - (sz & pageAddrMask) + if sz&mipsevm.PageAddrMask != 0 { // adjust size to align with page size + sz += mipsevm.PageSize - (sz & mipsevm.PageAddrMask) } if a0 == 0 { v0 = st.Heap @@ -308,35 +298,7 @@ func NewUnicornState(mu uc.Unicorn, state *State, po PreimageOracle, stdOut, std return m, nil } -func (m *UnicornState) NonUnicornStep(proof bool) (wit *StepWitness, err error) { - m.memProofEnabled = proof - m.lastMemAccess = ^uint32(0) - m.lastPreimageOffset = ^uint32(0) - - if proof { - insnProof := m.state.Memory.MerkleProof(m.state.PC) - wit = &StepWitness{ - state: m.state.EncodeWitness(), - memProof: insnProof[:], - } - } - err = m.mipsStep() - if err != nil { - return nil, err - } - - if proof { - wit.memProof = append(wit.memProof, m.memProof[:]...) - if m.lastPreimageOffset != ^uint32(0) { - wit.preimageOffset = m.lastPreimageOffset - wit.preimageKey = m.lastPreimageKey - wit.preimageValue = m.lastPreimage - } - } - return -} - -func (m *UnicornState) Step(proof bool) (wit *StepWitness, err error) { +func (m *UnicornState) Step(proof bool) (wit *mipsevm.StepWitness, err error) { defer func() { // pre-image oracle or emulator hooks might panic if a := recover(); a != nil { if ae, ok := a.(error); ok { @@ -353,9 +315,9 @@ func (m *UnicornState) Step(proof bool) (wit *StepWitness, err error) { if proof { insnProof := m.state.Memory.MerkleProof(m.state.PC) - wit = &StepWitness{ - state: m.state.EncodeWitness(), - memProof: insnProof[:], + wit = &mipsevm.StepWitness{ + State: m.state.EncodeWitness(), + MemProof: insnProof[:], } } @@ -408,11 +370,11 @@ func (m *UnicornState) Step(proof bool) (wit *StepWitness, err error) { } if proof { - wit.memProof = append(wit.memProof, m.memProof[:]...) + wit.MemProof = append(wit.MemProof, m.memProof[:]...) if m.lastPreimageOffset != ^uint32(0) { - wit.preimageOffset = m.lastPreimageOffset - wit.preimageKey = m.lastPreimageKey - wit.preimageValue = m.lastPreimage + wit.PreimageOffset = m.lastPreimageOffset + wit.PreimageKey = m.lastPreimageKey + wit.PreimageValue = m.lastPreimage } } @@ -452,11 +414,11 @@ func NewUnicorn() (uc.Unicorn, error) { return uc.NewUnicorn(uc.ARCH_MIPS, uc.MODE_32|uc.MODE_BIG_ENDIAN) } -func LoadUnicorn(st *State, mu uc.Unicorn) error { +func LoadUnicorn(st *mipsevm.State, mu uc.Unicorn) error { // mmap and write each page of memory state into unicorn for pageIndex, page := range st.Memory.Pages { - addr := uint64(pageIndex) << pageAddrSize - if err := mu.MemMap(addr, pageSize); err != nil { + addr := uint64(pageIndex) << mipsevm.PageAddrSize + if err := mu.MemMap(addr, mipsevm.PageSize); err != nil { return fmt.Errorf("failed to mmap page at addr 0x%x: %w", addr, err) } if err := mu.MemWrite(addr, page.Data[:]); err != nil { diff --git a/mipsevm/unicorn_test.go b/diffmips/unicorntest/unicorn_test.go similarity index 99% rename from mipsevm/unicorn_test.go rename to diffmips/unicorntest/unicorn_test.go index 5c4c8c49..89dc4cab 100644 --- a/mipsevm/unicorn_test.go +++ b/diffmips/unicorntest/unicorn_test.go @@ -1,4 +1,4 @@ -package mipsevm +package unicorntest import ( "testing" diff --git a/go.mod b/go.mod index da09d07d..0d9db6b7 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module cannon +module github.com/ethereum-optimism/cannon go 1.20 @@ -6,7 +6,6 @@ require ( github.com/ethereum-optimism/cannon/preimage v0.0.0 github.com/ethereum/go-ethereum v1.11.5 github.com/stretchr/testify v1.8.2 - github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650 github.com/urfave/cli/v2 v2.25.3 ) @@ -65,13 +64,3 @@ require ( ) replace github.com/ethereum-optimism/cannon/preimage v0.0.0 => ./preimage - -// We need to point to our local Unicorn clone for the shared object to be located correctly in all our Go commands. -// See https://github.com/unicorn-engine/unicorn/blob/7b8c63dfe650b5d4d2bf684526161971925e6350/bindings/go/unicorn/unicorn.go#L11 -// The -L../../../ -lunicorn points to the unicorn root directory relative to the unicorn Go bindings. -// Run make libunicorn in the Cannon repo root to create this libunicorn.so dependency. -// -// If you are importing Cannon as a library you will need to also point it to a unicorn clone with a `replace` -// in your `go.mod` (or `go.work`), or use `go build -ldflags="-L../path/to/my/unicorn/build -lunicorn`, -// or simply have it installed globally so Go can find it. The `replace` here will be ignored as library-user. -replace github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650 => ./unicorn diff --git a/go.sum b/go.sum index 517e456b..79f5912c 100644 --- a/go.sum +++ b/go.sum @@ -275,8 +275,6 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY= github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= diff --git a/main.go b/main.go index f9334047..000dcef2 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ import ( "github.com/urfave/cli/v2" - "cannon/cmd" + "github.com/ethereum-optimism/cannon/cmd" ) func main() { diff --git a/mipsevm/README.md b/mipsevm/README.md index c18f6611..bb74267c 100644 --- a/mipsevm/README.md +++ b/mipsevm/README.md @@ -16,9 +16,8 @@ Supported 55 instructions: To run: 1. Load a program into a state, e.g. using `LoadELF`. 2. Patch the program if necessary: e.g. using `PatchGo` for Go programs, `PatchStack` for empty initial stack, etc. -3. Load the state into a MIPS-32 configured unicorn instance, using `NewUnicorn`, `LoadUnicorn` 4. Implement the `PreimageOracle` interface -5. Instrument the emulator with the state, and pre-image oracle, using `NewUnicornState` +5. Instrument the emulator with the state, and pre-image oracle, using `NewInstrumentedState` 6. Step through the instrumented state with `Step(proof)`, where `proof==true` if witness data should be generated. Steps are faster with `proof==false`. 7. Optionally repeat the step on-chain by calling `MIPS.sol` and `Oracle.sol`, using the above witness data. diff --git a/mipsevm/evm_test.go b/mipsevm/evm_test.go index eada82de..da1ee646 100644 --- a/mipsevm/evm_test.go +++ b/mipsevm/evm_test.go @@ -64,18 +64,7 @@ func TestEVM(t *testing.T) { // set the return address ($ra) to jump into when test completes state.Registers[31] = endAddr - mu, err := NewUnicorn() - require.NoError(t, err, "load unicorn") - defer mu.Close() - - require.NoError(t, mu.MemMap(baseAddrStart, ((baseAddrEnd-baseAddrStart)&^pageAddrMask)+pageSize)) - require.NoError(t, mu.MemMap(endAddr&^pageAddrMask, pageSize)) - - err = LoadUnicorn(state, mu) - require.NoError(t, err, "load state into unicorn") - - us, err := NewUnicornState(mu, state, nil, os.Stdout, os.Stderr) - require.NoError(t, err, "hook unicorn to state") + us := NewInstrumentedState(state, nil, os.Stdout, os.Stderr) for i := 0; i < 1000; i++ { if us.state.PC == endAddr { @@ -84,7 +73,7 @@ func TestEVM(t *testing.T) { insn := state.Memory.GetMemory(state.PC) t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.Step, state.PC, insn) - stepWitness, err := us.NonUnicornStep(true) + stepWitness, err := us.Step(true) require.NoError(t, err) input := stepWitness.EncodeStepInput() startingGas := uint64(30_000_000) @@ -133,14 +122,8 @@ func TestHelloEVM(t *testing.T) { require.NoError(t, err, "apply Go runtime patches") require.NoError(t, PatchStack(state), "add initial stack") - mu, err := NewUnicorn() - require.NoError(t, err, "load unicorn") - defer mu.Close() - err = LoadUnicorn(state, mu) - require.NoError(t, err, "load state into unicorn") var stdOutBuf, stdErrBuf bytes.Buffer - us, err := NewUnicornState(mu, state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) - require.NoError(t, err, "hook unicorn to state") + us := NewInstrumentedState(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) env, evmState := NewEVMEnv(contracts, addrs) env.Config.Debug = false @@ -156,7 +139,7 @@ func TestHelloEVM(t *testing.T) { t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.Step, state.PC, insn) } - stepWitness, err := us.NonUnicornStep(true) + stepWitness, err := us.Step(true) require.NoError(t, err) input := stepWitness.EncodeStepInput() startingGas := uint64(30_000_000) @@ -206,17 +189,10 @@ func TestClaimEVM(t *testing.T) { require.NoError(t, err, "apply Go runtime patches") require.NoError(t, PatchStack(state), "add initial stack") - mu, err := NewUnicorn() - require.NoError(t, err, "load unicorn") - defer mu.Close() - err = LoadUnicorn(state, mu) - require.NoError(t, err, "load state into unicorn") - oracle, expectedStdOut, expectedStdErr := claimTestOracle(t) var stdOutBuf, stdErrBuf bytes.Buffer - us, err := NewUnicornState(mu, state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) - require.NoError(t, err, "hook unicorn to state") + us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) env, evmState := NewEVMEnv(contracts, addrs) env.Config.Debug = false @@ -232,7 +208,7 @@ func TestClaimEVM(t *testing.T) { t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.Step, state.PC, insn) } - stepWitness, err := us.NonUnicornStep(true) + stepWitness, err := us.Step(true) require.NoError(t, err) input := stepWitness.EncodeStepInput() startingGas := uint64(30_000_000) diff --git a/mipsevm/instrumented.go b/mipsevm/instrumented.go new file mode 100644 index 00000000..4e090b80 --- /dev/null +++ b/mipsevm/instrumented.go @@ -0,0 +1,82 @@ +package mipsevm + +import ( + "io" +) + +type PreimageOracle interface { + Hint(v []byte) + GetPreimage(k [32]byte) []byte +} + +type InstrumentedState struct { + state *State + + stdOut io.Writer + stdErr io.Writer + + lastMemAccess uint32 + memProofEnabled bool + memProof [28 * 32]byte + + preimageOracle PreimageOracle + + // cached pre-image data, including 8 byte length prefix + lastPreimage []byte + // key for above preimage + lastPreimageKey [32]byte + // offset we last read from, or max uint32 if nothing is read this step + lastPreimageOffset uint32 +} + +const ( + fdStdin = 0 + fdStdout = 1 + fdStderr = 2 + fdHintRead = 3 + fdHintWrite = 4 + fdPreimageRead = 5 + fdPreimageWrite = 6 +) + +const ( + MipsEBADF = 0x9 + MipsEINVAL = 0x16 +) + +func NewInstrumentedState(state *State, po PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState { + return &InstrumentedState{ + state: state, + stdOut: stdOut, + stdErr: stdErr, + preimageOracle: po, + } +} + +func (m *InstrumentedState) Step(proof bool) (wit *StepWitness, err error) { + m.memProofEnabled = proof + m.lastMemAccess = ^uint32(0) + m.lastPreimageOffset = ^uint32(0) + + if proof { + insnProof := m.state.Memory.MerkleProof(m.state.PC) + wit = &StepWitness{ + State: m.state.EncodeWitness(), + MemProof: insnProof[:], + } + } + err = m.mipsStep() + if err != nil { + return nil, err + } + + if proof { + wit.MemProof = append(wit.MemProof, m.memProof[:]...) + if m.lastPreimageOffset != ^uint32(0) { + wit.PreimageOffset = m.lastPreimageOffset + wit.PreimageKey = m.lastPreimageKey + wit.PreimageValue = m.lastPreimage + } + } + return +} diff --git a/mipsevm/memory.go b/mipsevm/memory.go index 55bdf65f..f127da41 100644 --- a/mipsevm/memory.go +++ b/mipsevm/memory.go @@ -11,15 +11,15 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) +// Note: 2**12 = 4 KiB, the minimum page-size in Unicorn for mmap +// as well as the Go runtime min phys page size. const ( - // Note: 2**12 = 4 KiB, the minimum page-size in Unicorn for mmap - // as well as the Go runtime min phys page size. - pageAddrSize = 12 - pageKeySize = 32 - pageAddrSize - pageSize = 1 << pageAddrSize - pageAddrMask = pageSize - 1 - maxPageCount = 1 << pageKeySize - pageKeyMask = maxPageCount - 1 + PageAddrSize = 12 + PageKeySize = 32 - PageAddrSize + PageSize = 1 << PageAddrSize + PageAddrMask = PageSize - 1 + MaxPageCount = 1 << PageKeySize + PageKeyMask = MaxPageCount - 1 ) func HashPair(left, right [32]byte) [32]byte { @@ -62,12 +62,12 @@ func (m *Memory) Invalidate(addr uint32) { } // find page, and invalidate addr within it - if p, ok := m.Pages[addr>>pageAddrSize]; ok { - p.Invalidate(addr & pageAddrMask) + if p, ok := m.Pages[addr>>PageAddrSize]; ok { + p.Invalidate(addr & PageAddrMask) } // find the gindex of the first page covering the address - gindex := ((uint64(1) << 32) | uint64(addr)) >> pageAddrSize + gindex := ((uint64(1) << 32) | uint64(addr)) >> PageAddrSize for gindex > 0 { m.Nodes[gindex] = nil @@ -80,9 +80,9 @@ func (m *Memory) MerkleizeSubtree(gindex uint64) [32]byte { if l > 28 { panic("gindex too deep") } - if l > pageKeySize { - depthIntoPage := l - 1 - pageKeySize - pageIndex := (gindex >> depthIntoPage) & pageKeyMask + if l > PageKeySize { + depthIntoPage := l - 1 - PageKeySize + pageIndex := (gindex >> depthIntoPage) & PageKeyMask if p, ok := m.Pages[uint32(pageIndex)]; ok { pageGindex := (1 << depthIntoPage) | (gindex & ((1 << depthIntoPage) - 1)) return p.MerkleizeSubtree(pageGindex) @@ -90,7 +90,7 @@ func (m *Memory) MerkleizeSubtree(gindex uint64) [32]byte { return zeroHashes[28-l] // page does not exist } } - if l > pageKeySize+1 { + if l > PageKeySize+1 { panic("cannot jump into intermediate node of page") } n, ok := m.Nodes[gindex] @@ -147,8 +147,8 @@ func (m *Memory) SetMemory(addr uint32, v uint32) { panic(fmt.Errorf("unaligned memory access: %x", addr)) } - pageIndex := addr >> pageAddrSize - pageAddr := addr & pageAddrMask + pageIndex := addr >> PageAddrSize + pageAddr := addr & PageAddrMask p, ok := m.Pages[pageIndex] if !ok { // allocate the page if we have not already. @@ -165,11 +165,11 @@ func (m *Memory) GetMemory(addr uint32) uint32 { if addr&0x3 != 0 { panic(fmt.Errorf("unaligned memory access: %x", addr)) } - p, ok := m.Pages[addr>>pageAddrSize] + p, ok := m.Pages[addr>>PageAddrSize] if !ok { return 0 } - pageAddr := addr & pageAddrMask + pageAddr := addr & PageAddrMask return binary.BigEndian.Uint32(p.Data[pageAddr : pageAddr+4]) } @@ -177,7 +177,7 @@ func (m *Memory) AllocPage(pageIndex uint32) *CachedPage { p := &CachedPage{Data: new(Page)} m.Pages[pageIndex] = p // make nodes to root - k := (1 << pageKeySize) | uint64(pageIndex) + k := (1 << PageKeySize) | uint64(pageIndex) for k > 0 { m.Nodes[k] = nil k >>= 1 @@ -222,8 +222,8 @@ func (m *Memory) UnmarshalJSON(data []byte) error { func (m *Memory) SetMemoryRange(addr uint32, r io.Reader) error { for { - pageIndex := addr >> pageAddrSize - pageAddr := addr & pageAddrMask + pageIndex := addr >> PageAddrSize + pageAddr := addr & PageAddrMask p, ok := m.Pages[pageIndex] if !ok { p = m.AllocPage(pageIndex) @@ -255,12 +255,12 @@ func (r *memReader) Read(dest []byte) (n int, err error) { // It may wrap around the address range, and may not be aligned endAddr := r.addr + r.count - pageIndex := r.addr >> pageAddrSize - start := r.addr & pageAddrMask - end := uint32(pageSize) + pageIndex := r.addr >> PageAddrSize + start := r.addr & PageAddrMask + end := uint32(PageSize) - if pageIndex == (endAddr >> pageAddrSize) { - end = endAddr & pageAddrMask + if pageIndex == (endAddr >> PageAddrSize) { + end = endAddr & PageAddrMask } p, ok := r.m.Pages[pageIndex] if ok { diff --git a/mipsevm/memory_test.go b/mipsevm/memory_test.go index 56938377..a8b84055 100644 --- a/mipsevm/memory_test.go +++ b/mipsevm/memory_test.go @@ -72,20 +72,20 @@ func TestMemoryMerkleRoot(t *testing.T) { }) t.Run("two empty pages", func(t *testing.T) { m := NewMemory() - m.SetMemory(pageSize*3, 0) - m.SetMemory(pageSize*10, 0) + m.SetMemory(PageSize*3, 0) + m.SetMemory(PageSize*10, 0) root := m.MerkleRoot() require.Equal(t, zeroHashes[32-5], root, "zero still") }) t.Run("random few pages", func(t *testing.T) { m := NewMemory() - m.SetMemory(pageSize*3, 1) - m.SetMemory(pageSize*5, 42) - m.SetMemory(pageSize*6, 123) - p3 := m.MerkleizeSubtree((1 << pageKeySize) | 3) - p5 := m.MerkleizeSubtree((1 << pageKeySize) | 5) - p6 := m.MerkleizeSubtree((1 << pageKeySize) | 6) - z := zeroHashes[pageAddrSize-5] + m.SetMemory(PageSize*3, 1) + m.SetMemory(PageSize*5, 42) + m.SetMemory(PageSize*6, 123) + p3 := m.MerkleizeSubtree((1 << PageKeySize) | 3) + p5 := m.MerkleizeSubtree((1 << PageKeySize) | 5) + p6 := m.MerkleizeSubtree((1 << PageKeySize) | 6) + z := zeroHashes[PageAddrSize-5] r1 := HashPair( HashPair( HashPair(z, z), // 0,1 @@ -96,7 +96,7 @@ func TestMemoryMerkleRoot(t *testing.T) { HashPair(p6, z), // 6,7 ), ) - r2 := m.MerkleizeSubtree(1 << (pageKeySize - 3)) + r2 := m.MerkleizeSubtree(1 << (PageKeySize - 3)) require.Equal(t, r1, r2, "expecting manual page combination to match subtree merkle func") }) t.Run("invalidate page", func(t *testing.T) { diff --git a/mipsevm/mips.go b/mipsevm/mips.go index b4781406..f1c60e06 100644 --- a/mipsevm/mips.go +++ b/mipsevm/mips.go @@ -6,7 +6,7 @@ import ( "io" ) -func (m *UnicornState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) { +func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) { preimage := m.lastPreimage if key != m.lastPreimageKey { m.lastPreimageKey = key @@ -22,7 +22,7 @@ func (m *UnicornState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, return } -func (m *UnicornState) trackMemAccess(effAddr uint32) { +func (m *InstrumentedState) trackMemAccess(effAddr uint32) { if m.memProofEnabled && m.lastMemAccess != effAddr { if m.lastMemAccess != ^uint32(0) { panic(fmt.Errorf("unexpected different mem access at %08x, already have access at %08x buffered", effAddr, m.lastMemAccess)) @@ -32,7 +32,7 @@ func (m *UnicornState) trackMemAccess(effAddr uint32) { } } -func (m *UnicornState) handleSyscall() error { +func (m *InstrumentedState) handleSyscall() error { syscallNum := m.state.Registers[2] // v0 v0 := uint32(0) v1 := uint32(0) @@ -45,8 +45,8 @@ func (m *UnicornState) handleSyscall() error { switch syscallNum { case 4090: // mmap sz := a1 - if sz&pageAddrMask != 0 { // adjust size to align with page size - sz += pageSize - (sz & pageAddrMask) + if sz&PageAddrMask != 0 { // adjust size to align with page size + sz += PageSize - (sz & PageAddrMask) } if a0 == 0 { v0 = m.state.Heap @@ -178,7 +178,7 @@ func (m *UnicornState) handleSyscall() error { return nil } -func (m *UnicornState) handleBranch(opcode uint32, insn uint32, rtReg uint32, rs uint32) error { +func (m *InstrumentedState) handleBranch(opcode uint32, insn uint32, rtReg uint32, rs uint32) error { shouldBranch := false if opcode == 4 || opcode == 5 { // beq/bne rt := m.state.Registers[rtReg] @@ -208,7 +208,7 @@ func (m *UnicornState) handleBranch(opcode uint32, insn uint32, rtReg uint32, rs return nil } -func (m *UnicornState) handleHiLo(fun uint32, rs uint32, rt uint32, storeReg uint32) error { +func (m *InstrumentedState) handleHiLo(fun uint32, rs uint32, rt uint32, storeReg uint32) error { val := uint32(0) switch fun { case 0x10: // mfhi @@ -244,7 +244,7 @@ func (m *UnicornState) handleHiLo(fun uint32, rs uint32, rt uint32, storeReg uin return nil } -func (m *UnicornState) handleJump(linkReg uint32, dest uint32) error { +func (m *InstrumentedState) handleJump(linkReg uint32, dest uint32) error { prevPC := m.state.PC m.state.PC = m.state.NextPC m.state.NextPC = dest @@ -254,7 +254,7 @@ func (m *UnicornState) handleJump(linkReg uint32, dest uint32) error { return nil } -func (m *UnicornState) handleRd(storeReg uint32, val uint32, conditional bool) error { +func (m *InstrumentedState) handleRd(storeReg uint32, val uint32, conditional bool) error { if storeReg >= 32 { panic("invalid register") } @@ -266,7 +266,7 @@ func (m *UnicornState) handleRd(storeReg uint32, val uint32, conditional bool) e return nil } -func (m *UnicornState) mipsStep() error { +func (m *InstrumentedState) mipsStep() error { if m.state.Exited { return nil } diff --git a/mipsevm/page.go b/mipsevm/page.go index 6fc62dbd..8e14e7ca 100644 --- a/mipsevm/page.go +++ b/mipsevm/page.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -type Page [pageSize]byte +type Page [PageSize]byte func (p *Page) MarshalText() ([]byte, error) { dst := make([]byte, hex.EncodedLen(len(p))) @@ -16,8 +16,8 @@ func (p *Page) MarshalText() ([]byte, error) { } func (p *Page) UnmarshalText(dat []byte) error { - if len(dat) != pageSize*2 { - return fmt.Errorf("expected %d hex chars, but got %d", pageSize*2, len(dat)) + if len(dat) != PageSize*2 { + return fmt.Errorf("expected %d hex chars, but got %d", PageSize*2, len(dat)) } _, err := hex.Decode(p[:], dat) return err @@ -26,16 +26,16 @@ func (p *Page) UnmarshalText(dat []byte) error { type CachedPage struct { Data *Page // intermediate nodes only - Cache [pageSize / 32][32]byte + Cache [PageSize / 32][32]byte // true if the intermediate node is valid - Ok [pageSize / 32]bool + Ok [PageSize / 32]bool } func (p *CachedPage) Invalidate(pageAddr uint32) { - if pageAddr >= pageSize { + if pageAddr >= PageSize { panic("invalid page addr") } - k := (1 << pageAddrSize) | pageAddr + k := (1 << PageAddrSize) | pageAddr // first cache layer caches nodes that has two 32 byte leaf nodes. k >>= 5 + 1 for k > 0 { @@ -45,13 +45,13 @@ func (p *CachedPage) Invalidate(pageAddr uint32) { } func (p *CachedPage) InvalidateFull() { - p.Ok = [pageSize / 32]bool{} // reset everything to false + p.Ok = [PageSize / 32]bool{} // reset everything to false } func (p *CachedPage) MerkleRoot() [32]byte { // hash the bottom layer - for i := uint64(0); i < pageSize; i += 64 { - j := pageSize/32/2 + i/64 + for i := uint64(0); i < PageSize; i += 64 { + j := PageSize/32/2 + i/64 if p.Ok[j] { continue } @@ -61,7 +61,7 @@ func (p *CachedPage) MerkleRoot() [32]byte { } // hash the cache layers - for i := pageSize/32 - 2; i > 0; i -= 2 { + for i := PageSize/32 - 2; i > 0; i -= 2 { j := i >> 1 if p.Ok[j] { continue @@ -75,12 +75,12 @@ func (p *CachedPage) MerkleRoot() [32]byte { func (p *CachedPage) MerkleizeSubtree(gindex uint64) [32]byte { _ = p.MerkleRoot() // fill cache - if gindex >= pageSize/32 { - if gindex >= pageSize/32*2 { + if gindex >= PageSize/32 { + if gindex >= PageSize/32*2 { panic("gindex too deep") } // it's pointing to a bottom node - nodeIndex := gindex & (pageAddrMask >> 5) + nodeIndex := gindex & (PageAddrMask >> 5) return *(*[32]byte)(p.Data[nodeIndex*32 : nodeIndex*32+32]) } return p.Cache[gindex] diff --git a/mipsevm/page_test.go b/mipsevm/page_test.go index df07bebf..8fba0645 100644 --- a/mipsevm/page_test.go +++ b/mipsevm/page_test.go @@ -11,7 +11,7 @@ func TestCachedPage(t *testing.T) { p := &CachedPage{Data: new(Page)} p.Data[42] = 0xab - gindex := ((uint64(1) << pageAddrSize) | 42) >> 5 + gindex := ((uint64(1) << PageAddrSize) | 42) >> 5 node := common.Hash(p.MerkleizeSubtree(gindex)) expectedLeaf := common.Hash{10: 0xab} require.Equal(t, expectedLeaf, node, "leaf nodes should not be hashed") diff --git a/mipsevm/patch.go b/mipsevm/patch.go index 4ded340c..92b1de74 100644 --- a/mipsevm/patch.go +++ b/mipsevm/patch.go @@ -99,7 +99,7 @@ func PatchStack(st *State) error { // setup stack pointer sp := uint32(0x7f_ff_d0_00) // allocate 1 page for the initial stack data, and 16KB = 4 pages for the stack to grow - if err := st.Memory.SetMemoryRange(sp-4*pageSize, bytes.NewReader(make([]byte, 5*pageSize))); err != nil { + if err := st.Memory.SetMemoryRange(sp-4*PageSize, bytes.NewReader(make([]byte, 5*PageSize))); err != nil { return fmt.Errorf("failed to allocate page for stack content") } st.Registers[29] = sp diff --git a/mipsevm/state_test.go b/mipsevm/state_test.go index 10c593d5..430ee784 100644 --- a/mipsevm/state_test.go +++ b/mipsevm/state_test.go @@ -19,9 +19,8 @@ import ( "github.com/ethereum-optimism/cannon/preimage" ) -// baseAddrStart - baseAddrEnd is used in tests to write the results to +// 0xbf_c0_00_00 ... baseAddrEnd is used in tests to write the results to const baseAddrEnd = 0xbf_ff_ff_f0 -const baseAddrStart = 0xbf_c0_00_00 // endAddr is used as return-address for tests const endAddr = 0xa7ef00d0 @@ -51,30 +50,13 @@ func TestState(t *testing.T) { // set the return address ($ra) to jump into when test completes state.Registers[31] = endAddr - //err = state.SetMemoryRange(baseAddr&^pageAddrMask, bytes.NewReader(make([]byte, pageSize))) - //require.NoError(t, err, "must allocate page for the result data") - // - //err = state.SetMemoryRange(endAddr&^pageAddrMask, bytes.NewReader(make([]byte, pageSize))) - //require.NoError(t, err, "must allocate page to return to") - - mu, err := NewUnicorn() - require.NoError(t, err, "load unicorn") - defer mu.Close() - - require.NoError(t, mu.MemMap(baseAddrStart, ((baseAddrEnd-baseAddrStart)&^pageAddrMask)+pageSize)) - require.NoError(t, mu.MemMap(endAddr&^pageAddrMask, pageSize)) - - err = LoadUnicorn(state, mu) - require.NoError(t, err, "load state into unicorn") - - us, err := NewUnicornState(mu, state, nil, os.Stdout, os.Stderr) - require.NoError(t, err, "hook unicorn to state") + us := NewInstrumentedState(state, nil, os.Stdout, os.Stderr) for i := 0; i < 1000; i++ { if us.state.PC == endAddr { break } - _, err := us.NonUnicornStep(false) + _, err := us.Step(false) require.NoError(t, err) } require.Equal(t, uint32(endAddr), us.state.PC, "must reach end") @@ -97,20 +79,14 @@ func TestHello(t *testing.T) { require.NoError(t, err, "apply Go runtime patches") require.NoError(t, PatchStack(state), "add initial stack") - mu, err := NewUnicorn() - require.NoError(t, err, "load unicorn") - defer mu.Close() - err = LoadUnicorn(state, mu) - require.NoError(t, err, "load state into unicorn") var stdOutBuf, stdErrBuf bytes.Buffer - us, err := NewUnicornState(mu, state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) - require.NoError(t, err, "hook unicorn to state") + us := NewInstrumentedState(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) for i := 0; i < 400_000; i++ { if us.state.Exited { break } - _, err := us.NonUnicornStep(false) + _, err := us.Step(false) require.NoError(t, err) } @@ -201,23 +177,16 @@ func TestClaim(t *testing.T) { require.NoError(t, err, "apply Go runtime patches") require.NoError(t, PatchStack(state), "add initial stack") - mu, err := NewUnicorn() - require.NoError(t, err, "load unicorn") - defer mu.Close() - err = LoadUnicorn(state, mu) - require.NoError(t, err, "load state into unicorn") - oracle, expectedStdOut, expectedStdErr := claimTestOracle(t) var stdOutBuf, stdErrBuf bytes.Buffer - us, err := NewUnicornState(mu, state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) - require.NoError(t, err, "hook unicorn to state") + us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr)) for i := 0; i < 2000_000; i++ { if us.state.Exited { break } - _, err := us.NonUnicornStep(false) + _, err := us.Step(false) require.NoError(t, err) } diff --git a/mipsevm/witness.go b/mipsevm/witness.go index bad3c04d..60cabaf3 100644 --- a/mipsevm/witness.go +++ b/mipsevm/witness.go @@ -11,13 +11,14 @@ import ( ) type StepWitness struct { - state []byte + // encoded state witness + State []byte - memProof []byte + MemProof []byte - preimageKey [32]byte // zeroed when no pre-image is accessed - preimageValue []byte // including the 8-byte length prefix - preimageOffset uint32 + PreimageKey [32]byte // zeroed when no pre-image is accessed + PreimageValue []byte // including the 8-byte length prefix + PreimageOffset uint32 } func uint32ToBytes32(v uint32) []byte { @@ -27,30 +28,30 @@ func uint32ToBytes32(v uint32) []byte { } func (wit *StepWitness) EncodeStepInput() []byte { - stateHash := crypto.Keccak256Hash(wit.state) + stateHash := crypto.Keccak256Hash(wit.State) var input []byte input = append(input, StepBytes4...) input = append(input, stateHash[:]...) input = append(input, uint32ToBytes32(32*3)...) // state data offset in bytes - input = append(input, uint32ToBytes32(32*3+32+uint32(len(wit.state)))...) // proof data offset in bytes + input = append(input, uint32ToBytes32(32*3+32+uint32(len(wit.State)))...) // proof data offset in bytes - input = append(input, uint32ToBytes32(uint32(len(wit.state)))...) // state data length in bytes - input = append(input, wit.state[:]...) - input = append(input, uint32ToBytes32(uint32(len(wit.memProof)))...) // proof data length in bytes - input = append(input, wit.memProof[:]...) + input = append(input, uint32ToBytes32(uint32(len(wit.State)))...) // state data length in bytes + input = append(input, wit.State[:]...) + input = append(input, uint32ToBytes32(uint32(len(wit.MemProof)))...) // proof data length in bytes + input = append(input, wit.MemProof[:]...) return input } func (wit *StepWitness) HasPreimage() bool { - return wit.preimageKey != ([32]byte{}) + return wit.PreimageKey != ([32]byte{}) } func (wit *StepWitness) EncodePreimageOracleInput() ([]byte, error) { - if wit.preimageKey == ([32]byte{}) { + if wit.PreimageKey == ([32]byte{}) { return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof") } - switch preimage.KeyType(wit.preimageKey[0]) { + switch preimage.KeyType(wit.PreimageKey[0]) { case preimage.LocalKeyType: // We have no on-chain form of preparing the bootstrap pre-images onchain yet. // So instead we cheat them in. @@ -58,25 +59,25 @@ func (wit *StepWitness) EncodePreimageOracleInput() ([]byte, error) { // rather than going through the global keccak256 oracle. var input []byte input = append(input, CheatBytes4...) - input = append(input, uint32ToBytes32(wit.preimageOffset)...) - input = append(input, wit.preimageKey[:]...) + input = append(input, uint32ToBytes32(wit.PreimageOffset)...) + input = append(input, wit.PreimageKey[:]...) var tmp [32]byte - copy(tmp[:], wit.preimageValue[wit.preimageOffset:]) + copy(tmp[:], wit.PreimageValue[wit.PreimageOffset:]) input = append(input, tmp[:]...) - input = append(input, uint32ToBytes32(uint32(len(wit.preimageValue))-8)...) + input = append(input, uint32ToBytes32(uint32(len(wit.PreimageValue))-8)...) // TODO: do we want to pad the end to a multiple of 32 bytes? return input, nil case preimage.Keccak256KeyType: var input []byte input = append(input, LoadKeccak256PreimagePartBytes4...) - input = append(input, uint32ToBytes32(wit.preimageOffset)...) + input = append(input, uint32ToBytes32(wit.PreimageOffset)...) input = append(input, uint32ToBytes32(32+32)...) // partOffset, calldata offset - input = append(input, uint32ToBytes32(uint32(len(wit.preimageValue))-8)...) - input = append(input, wit.preimageValue[8:]...) + input = append(input, uint32ToBytes32(uint32(len(wit.PreimageValue))-8)...) + input = append(input, wit.PreimageValue[8:]...) // TODO: do we want to pad the end to a multiple of 32 bytes? return input, nil default: return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle", - wit.preimageKey[0], wit.preimageKey, wit.preimageOffset) + wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset) } }