diff --git a/.gitignore b/.gitignore index 863cd4d9..4fa7c0d7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ rosetta-zen zen-data zen-testnet-data cli-data +/http/ diff --git a/.travis.yml b/.travis.yml index 8153bc0e..c07caff5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ os: linux dist: bionic language: go go: - - "1.17.2" + - "1.19.1" services: - docker addons: diff --git a/Dockerfile b/Dockerfile index 3e361c85..b311f2f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,18 +14,18 @@ # limitations under the License. ## Build zend -FROM ubuntu:18.04 as zend-builder +FROM ubuntu:20.04 as zend-builder MAINTAINER cronic@horizen.io SHELL ["/bin/bash", "-c"] -# Latest release zen 3.2.0 -ARG ZEN_COMMITTISH=v3.2.0 +ARG ZEN_COMMITTISH ARG IS_RELEASE=false # cronic https://keys.openpgp.org/vks/v1/by-fingerprint/219F55740BBF7A1CE368BA45FB7053CE4991B669 # Luigi Varriale https://keys.openpgp.org/vks/v1/by-fingerprint/FC3388A460ACFAB04E8328C07BB2A1D2CFDFCD2C -ARG MAINTAINER_KEYS="219F55740BBF7A1CE368BA45FB7053CE4991B669 FC3388A460ACFAB04E8328C07BB2A1D2CFDFCD2C" +# otoumas https://keys.openpgp.org/vks/v1/by-fingerprint/2BBE2AA1A641F6147B58450BE3527B60DAACA1D8 +ARG MAINTAINER_KEYS="219F55740BBF7A1CE368BA45FB7053CE4991B669 FC3388A460ACFAB04E8328C07BB2A1D2CFDFCD2C 2BBE2AA1A641F6147B58450BE3527B60DAACA1D8" RUN set -euxo pipefail \ && export DEBIAN_FRONTEND=noninteractive \ @@ -53,18 +53,18 @@ RUN set -euxo pipefail \ && ( gpgconf --kill dirmngr || true ) \ && ( gpgconf --kill gpg-agent || true ); \ fi \ - && export MAKEFLAGS="-j $(($(nproc)+1))" && ./zcutil/build.sh $MAKEFLAGS + && export MAKEFLAGS="-j $(($(nproc)+1))" && ./zcutil/build.sh --legacy-cpu $MAKEFLAGS ## Build Rosetta Server Components -FROM ubuntu:18.04 as rosetta-builder +FROM ubuntu:20.04 as rosetta-builder MAINTAINER cronic@horizen.io SHELL ["/bin/bash", "-c"] -ARG GOLANG_VERSION=1.17.2 -ARG GOLANG_DOWNLOAD_SHA256=f242a9db6a0ad1846de7b6d94d507915d14062660616a61ef7c808a76e4f1676 +ARG GOLANG_VERSION=1.19.1 +ARG GOLANG_DOWNLOAD_SHA256=acc512fbab4f716a8f97a8b3fbaa9ddd39606a28be6c2515ef7c6c6311acffde ARG GOLANG_DOWNLOAD_URL="https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz" COPY . /go/src @@ -84,7 +84,7 @@ RUN set -euxo pipefail \ ## Build Final Image -FROM ubuntu:18.04 +FROM ubuntu:20.04 MAINTAINER cronic@horizen.io diff --git a/Makefile b/Makefile index ae106227..a0bbe294 100644 --- a/Makefile +++ b/Makefile @@ -2,38 +2,44 @@ run-testnet-offline check-comments add-license check-license shorten-lines test \ coverage spellcheck salus build-local coverage-local format check-format -ADDLICENSE_CMD=go run github.com/google/addlicense -ADDLICENCE_SCRIPT=${ADDLICENSE_CMD} -c "Coinbase, Inc." -l "apache" -v +ADDLICENSE_INSTALL=go install github.com/google/addlicense@latest +ADDLICENSE_CMD=addlicense +ADDLICENSE_IGNORE=-ignore ".github/**/*" -ignore ".idea/**/*" +ADDLICENCE_SCRIPT=${ADDLICENSE_CMD} -c "Coinbase, Inc." -l "apache" -v ${ADDLICENSE_IGNORE} SPELLCHECK_CMD=go run github.com/client9/misspell/cmd/misspell -GOLINES_CMD=go run github.com/segmentio/golines -GOLINT_CMD=go run golang.org/x/lint/golint -GOVERALLS_CMD=go run github.com/mattn/goveralls +GOLINES_INSTALL=go install github.com/segmentio/golines@latest +GOLINES_CMD=golines +GOLINT_INSTALL=go get golang.org/x/lint/golint +GOLINT_CMD=golint +GOVERALLS_INSTALL=go install github.com/mattn/goveralls@latest +GOVERALLS_CMD=goveralls GOIMPORTS_CMD=go run golang.org/x/tools/cmd/goimports GO_PACKAGES=./services/... ./indexer/... ./zen/... ./zend/... ./zenutil/... ./configuration/... GO_FOLDERS=$(shell echo ${GO_PACKAGES} | sed -e "s/\.\///g" | sed -e "s/\/\.\.\.//g") -TEST_SCRIPT=go test ${GO_PACKAGES} +TEST_SCRIPT=go test ${GO_PACKAGES} -buildmode=pie LINT_SETTINGS=golint,misspell,gocyclo,gocritic,whitespace,goconst,gocognit,bodyclose,unconvert,lll,unparam PWD=$(shell pwd) GZIP_CMD=$(shell command -v pigz || echo gzip) NOFILE=100000 +ZEND_VERSION=v3.2.0 deps: go get ./... build: - docker build --pull -t rosetta-zen:latest https://github.com/HorizenOfficial/rosetta-zen + docker build --pull --build-arg "ZEN_COMMITTISH=${ZEND_VERSION}" -t rosetta-zen:latest https://github.com/HorizenOfficial/rosetta-zen build-local: - docker build --pull -t rosetta-zen:latest . + docker build --pull --build-arg "ZEN_COMMITTISH=${ZEND_VERSION}" -t rosetta-zen:latest . build-release: # make sure to always set version with vX.X.X - docker build --pull --no-cache --build-arg IS_RELEASE=true -t rosetta-zen:$(version) .; + docker build --pull --no-cache --build-arg IS_RELEASE=true --build-arg "ZEN_COMMITTISH=${ZEND_VERSION}" -t rosetta-zen:$(version) .; docker save rosetta-zen:$(version) | ${GZIP_CMD} > rosetta-zen-$(version).tar.gz; run-mainnet-online: docker container rm rosetta-zen-mainnet-online || true - docker run --rm -v "${PWD}/zen-data:/data" ubuntu:18.04 bash -c 'chown -R nobody:nogroup /data'; + docker run --rm -v "${PWD}/zen-data:/data" ubuntu:20.04 bash -c 'chown -R nobody:nogroup /data'; docker run -d --name=rosetta-zen-mainnet-online --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 9033:9033 rosetta-zen:latest; run-mainnet-offline: @@ -42,29 +48,46 @@ run-mainnet-offline: run-testnet-online: docker container rm rosetta-zen-testnet-online || true - docker run --rm -v "${PWD}/zen-data:/data" ubuntu:18.04 bash -c 'chown -R nobody:nogroup /data'; - docker run -d --name=rosetta-zen-testnet-online --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 19033:19033 rosetta-zen:latest; + docker run --rm -v "${PWD}/zen-data:/data" ubuntu:20.04 bash -c 'chown -R nobody:nogroup /data'; + docker run -d --name=rosetta-zen-testnet-online --ulimit "nofile=${NOFILE}:${NOFILE}" -v "${PWD}/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 19033:19033 -p 18231:18231 rosetta-zen:latest; run-testnet-offline: docker container rm rosetta-zen-testnet-offline || true docker run -d --name=rosetta-zen-testnet-offline -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "PORT=8081" -p 8081:8081 rosetta-zen:latest +stop-mainnet-online: + docker container stop rosetta-zen-mainnet-online + +stop-mainnet-offline: + docker container stop rosetta-zen-mainnet-offline + +stop-testnet-online: + docker container stop rosetta-zen-testnet-online + +stop-testnet-offline: + docker container stop rosetta-zen-testnet-offline + train: ./zstd-train.sh $(network) transaction $(data-directory) check-comments: + ${GOLINT_INSTALL} ${GOLINT_CMD} -set_exit_status ${GO_FOLDERS} . + go mod tidy lint: | check-comments golangci-lint run --timeout 2m0s -v -E ${LINT_SETTINGS},gomnd add-license: + ${ADDLICENSE_INSTALL} ${ADDLICENCE_SCRIPT} . check-license: + ${ADDLICENSE_INSTALL} ${ADDLICENCE_SCRIPT} -check . shorten-lines: + ${GOLINES_INSTALL} ${GOLINES_CMD} -w --shorten-comments ${GO_FOLDERS} . format: @@ -79,6 +102,7 @@ test: ${TEST_SCRIPT} coverage: + ${GOVERALLS_INSTALL} if [ "${COVERALLS_TOKEN}" ]; then ${TEST_SCRIPT} -coverprofile=c.out -covermode=count; ${GOVERALLS_CMD} -coverprofile=c.out -repotoken ${COVERALLS_TOKEN}; fi coverage-local: @@ -94,4 +118,5 @@ mocks: rm -rf mocks; mockery --dir indexer --all --case underscore --outpkg indexer --output mocks/indexer; mockery --dir services --all --case underscore --outpkg services --output mocks/services; + ${ADDLICENSE_INSTALL} ${ADDLICENCE_SCRIPT} .; diff --git a/README.md b/README.md index fa87e907..5c37fc1b 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ You can also use a named volume which will be created with the correct ownership ```text # create /zen-data with correct ownership docker run --rm -v "$(pwd)/zen-data:/data" ubuntu:18.04 bash -c 'chown -R nobody:nogroup /data' -# start rosetta-zen -docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 9033:9033 rosetta-zen:latest +# start rosetta-zen. Zend version needs to be specified (ex. v3.2.0) +docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "NODE_VERSION=${ZEND_VERSION}" -e "PORT=8080" -p 8080:8080 -p 9033:9033 rosetta-zen:latest ``` _If you cloned the repository, you can run `make run-mainnet-online`._ @@ -64,7 +64,7 @@ The zend configuration file can be extended by setting the docker command to /ap and using the optional -extend-zen-conf="" switch. The value of -extend-zen-conf="" will be appended to /app/zen-${NETWORK}.conf, newlines can be set as "\n". ```text -docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "PORT=8080" -p 8080:8080 -p 9033:9033 rosetta-zen:latest /app/rosetta-zen -extend-zen-conf="reindexfast=1\ndebug=rpc\ndebug=net" +docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=MAINNET" -e "NODE_VERSION=${ZEND_VERSION}" -e "PORT=8080" -p 8080:8080 -p 9033:9033 rosetta-zen:latest /app/rosetta-zen -extend-zen-conf="reindexfast=1\ndebug=rpc\ndebug=net" # this command line would append the following to /app/zen-mainnet.conf reindexfast=1 debug=rpc @@ -73,7 +73,7 @@ debug=net #### Mainnet:Offline ```text -docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=MAINNET" -e "PORT=8081" -p 8081:8081 rosetta-zen:latest +docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=MAINNET" -e "NODE_VERSION=${ZEND_VERSION}" -e "PORT=8081" -p 8081:8081 rosetta-zen:latest ``` _If you cloned the repository, you can run `make run-mainnet-offline`._ @@ -82,13 +82,13 @@ _If you cloned the repository, you can run `make run-mainnet-offline`._ # create /zen-data with correct ownership docker run --rm -v "$(pwd)/zen-data:/data" ubuntu:18.04 bash -c 'chown -R nobody:nogroup /data' # start rosetta-zen -docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "PORT=8080" -p 8080:8080 -p 19033:19033 rosetta-zen:latest +docker run -d --rm --ulimit "nofile=100000:100000" -v "$(pwd)/zen-data:/data" -e "MODE=ONLINE" -e "NETWORK=TESTNET" -e "NODE_VERSION=${ZEND_VERSION}" -e "PORT=8080" -p 8080:8080 -p 19033:19033 rosetta-zen:latest ``` _If you cloned the repository, you can run `make run-testnet-online`._ #### Testnet:Offline ```text -docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "PORT=8081" -p 8081:8081 rosetta-zen:latest +docker run -d --rm -e "MODE=OFFLINE" -e "NETWORK=TESTNET" -e "NODE_VERSION=${ZEND_VERSION}" -e "PORT=8081" -p 8081:8081 rosetta-zen:latest ``` _If you cloned the repository, you can run `make run-testnet-offline`._ diff --git a/configuration/configuration.go b/configuration/configuration.go index b28ab343..ce9d01bb 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -25,7 +25,7 @@ import ( "github.com/HorizenOfficial/rosetta-zen/zen" "github.com/HorizenOfficial/rosetta-zen/zend/chaincfg" - "github.com/coinbase/rosetta-sdk-go/storage" + "github.com/coinbase/rosetta-sdk-go/storage/encoder" "github.com/coinbase/rosetta-sdk-go/types" ) @@ -88,8 +88,8 @@ const ( // persistent data. DataDirectory = "/data" - zendPath = ".zen" - indexerPath = "indexer" + zendPath = ".zen" + indexerPath = "indexer" // allFilePermissions specifies anyone can do anything // to the file. @@ -130,7 +130,8 @@ type Configuration struct { Pruning *PruningConfiguration IndexerPath string ZendPath string - Compressors []*storage.CompressorEntry + ZendVersion string + Compressors []*encoder.CompressorEntry } // LoadConfiguration attempts to create a new Configuration @@ -176,7 +177,7 @@ func LoadConfiguration(baseDirectory string) (*Configuration, error) { config.Currency = zen.MainnetCurrency config.ConfigPath = mainnetConfigPath config.RPCPort = mainnetRPCPort - config.Compressors = []*storage.CompressorEntry{ + config.Compressors = []*encoder.CompressorEntry{ { Namespace: transactionNamespace, DictionaryPath: mainnetTransactionDictionary, @@ -192,7 +193,7 @@ func LoadConfiguration(baseDirectory string) (*Configuration, error) { config.Currency = zen.TestnetCurrency config.ConfigPath = testnetConfigPath config.RPCPort = testnetRPCPort - config.Compressors = []*storage.CompressorEntry{ + config.Compressors = []*encoder.CompressorEntry{ { Namespace: transactionNamespace, DictionaryPath: testnetTransactionDictionary, @@ -208,7 +209,7 @@ func LoadConfiguration(baseDirectory string) (*Configuration, error) { config.Currency = zen.TestnetCurrency config.ConfigPath = regtestConfigPath config.RPCPort = regtestRPCPort - config.Compressors = []*storage.CompressorEntry{ + config.Compressors = []*encoder.CompressorEntry{ { Namespace: transactionNamespace, DictionaryPath: testnetTransactionDictionary, diff --git a/configuration/configuration_test.go b/configuration/configuration_test.go index 6e5e8ef7..03dd0fd3 100644 --- a/configuration/configuration_test.go +++ b/configuration/configuration_test.go @@ -22,7 +22,7 @@ import ( "github.com/HorizenOfficial/rosetta-zen/zen" - "github.com/coinbase/rosetta-sdk-go/storage" + "github.com/coinbase/rosetta-sdk-go/storage/encoder" "github.com/coinbase/rosetta-sdk-go/types" "github.com/coinbase/rosetta-sdk-go/utils" "github.com/stretchr/testify/assert" @@ -33,9 +33,8 @@ func TestLoadConfiguration(t *testing.T) { Mode string Network string Port string - - cfg *Configuration - err error + cfg *Configuration + err error }{ "no envs set": { err: errors.New("MODE must be populated"), @@ -70,7 +69,8 @@ func TestLoadConfiguration(t *testing.T) { Depth: pruneDepth, MinHeight: minPruneHeight, }, - Compressors: []*storage.CompressorEntry{ + ZendVersion: "", + Compressors: []*encoder.CompressorEntry{ { Namespace: transactionNamespace, DictionaryPath: mainnetTransactionDictionary, @@ -99,7 +99,8 @@ func TestLoadConfiguration(t *testing.T) { Depth: pruneDepth, MinHeight: minPruneHeight, }, - Compressors: []*storage.CompressorEntry{ + ZendVersion: "", + Compressors: []*encoder.CompressorEntry{ { Namespace: transactionNamespace, DictionaryPath: testnetTransactionDictionary, @@ -133,9 +134,9 @@ func TestLoadConfiguration(t *testing.T) { assert.NoError(t, err) defer utils.RemoveTempDir(newDir) - os.Setenv(ModeEnv, test.Mode) - os.Setenv(NetworkEnv, test.Network) - os.Setenv(PortEnv, test.Port) + _ = os.Setenv(ModeEnv, test.Mode) + _ = os.Setenv(NetworkEnv, test.Network) + _ = os.Setenv(PortEnv, test.Port) cfg, err := LoadConfiguration(newDir) if test.err != nil { diff --git a/go.mod b/go.mod index b730d5d0..b211043d 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,60 @@ module github.com/HorizenOfficial/rosetta-zen -go 1.13 +go 1.19 require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/coinbase/rosetta-sdk-go v0.5.8-0.20201027222031-dd9e29377d5f + github.com/coinbase/rosetta-sdk-go v0.8.1 github.com/davecgh/go-spew v1.1.1 - github.com/dgraph-io/badger/v2 v2.2007.2 - github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 - github.com/stretchr/testify v1.6.1 - go.uber.org/zap v1.16.0 - golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a - golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 - golang.org/x/tools v0.0.0-20200904185747-39188db58858 // indirect - honnef.co/go/tools v0.0.1-2020.1.5 // indirect + github.com/dgraph-io/badger/v2 v2.2007.4 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 + github.com/stretchr/testify v1.8.0 + go.uber.org/zap v1.23.0 + golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be + golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 +) + +require ( + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + github.com/DataDog/zstd v1.5.2 // indirect + github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect + github.com/bwesterb/go-ristretto v1.2.0 // indirect + github.com/cenkalti/backoff v2.2.1+incompatible // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/coinbase/kryptology v1.8.0 // indirect + github.com/consensys/gnark-crypto v0.5.3 // indirect + github.com/dgraph-io/ristretto v0.0.3 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/ethereum/go-ethereum v1.10.21 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/klauspost/compress v1.12.3 // indirect + github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/neilotoole/errgroup v0.1.6 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/segmentio/fasthash v1.0.3 // indirect + github.com/stretchr/objx v0.4.0 // indirect + github.com/tidwall/gjson v1.14.1 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/sjson v1.2.4 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect + golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + google.golang.org/grpc v1.29.1 // indirect + google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fff31759..08c3605a 100644 --- a/go.sum +++ b/go.sum @@ -1,141 +1,80 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= -github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= -github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM= -github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/HorizenOfficial/rosetta-zen/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= -github.com/HorizenOfficial/rosetta-zen/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= -github.com/HorizenOfficial/rosetta-zen/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/HorizenOfficial/rosetta-zen/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= -github.com/HorizenOfficial/rosetta-zen/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= -github.com/HorizenOfficial/rosetta-zen/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/HorizenOfficial/rosetta-zen/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= -github.com/HorizenOfficial/rosetta-zen/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/HorizenOfficial/rosetta-zen/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/HorizenOfficial/rosetta-zen/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= -github.com/HorizenOfficial/rosetta-zen/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/HorizenOfficial/rosetta-zen/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/HorizenOfficial/rosetta-zen/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= -github.com/HorizenOfficial/rosetta-zen/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/HorizenOfficial/rosetta-zen/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/HorizenOfficial/rosetta-zen/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/HorizenOfficial/rosetta-zen/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6 h1:1d9pzdbkth4D9AX6ndKSl7of3UTV0RYl3z64U2dXMGo= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= -github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/bwesterb/go-ristretto v1.2.0 h1:xxWOVbN5m8NNKiSDZXE1jtZvZnC6JSJ9cYFADiZcWtw= +github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coinbase/rosetta-sdk-go v0.5.8-0.20201027222031-dd9e29377d5f h1:aWkN9dKMkMMpZKX5QycpePxH176Fj2fNNC7jESfLZw0= -github.com/coinbase/rosetta-sdk-go v0.5.8-0.20201027222031-dd9e29377d5f/go.mod h1:l5aNeyeZKBkmWbVdkdLpWdToQ6hTwI7cZ1OU9cMbljY= +github.com/coinbase/kryptology v1.8.0 h1:Aoq4gdTsJhSU3lNWsD5BWmFSz2pE0GlmrljaOxepdYY= +github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= +github.com/coinbase/rosetta-sdk-go v0.8.1 h1:WE+Temc8iz7Ra7sCpV9ymBJx78vItqFJ2xcSiPet1Pc= +github.com/coinbase/rosetta-sdk-go v0.8.1/go.mod h1:tXPR6AIW9ogsH4tYIaFOKOgfJNanCvcyl7JKLd4DToc= +github.com/consensys/bavard v0.1.8-0.20210915155054-088da2f7f54a/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.5.3 h1:4xLFGZR3NWEH2zy+YzvzHicpToQR8FXFbfLNvpGB+rE= +github.com/consensys/gnark-crypto v0.5.3/go.mod h1:hOdPlWQV1gDLp7faZVeg8Y0iEPFaOUnCc4XeCCk96p0= 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/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= -github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= +github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI= github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 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.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.9.23 h1:SIKhg/z4Q7AbvqcxuPYvMxf36che/Rq/Pp0IdYEkbtw= -github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= -github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/ethereum/go-ethereum v1.10.21 h1:5lqsEx92ZaZzRyOqBEXux4/UR06m296RGzN3ol3teJY= +github.com/ethereum/go-ethereum v1.10.21/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 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/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/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= @@ -148,123 +87,73 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU 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 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26 h1:lMm2hD9Fy0ynom5+85/pbdkiYcBqM1JWmhpAXLmy0fw= -github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +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/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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= -github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77 h1:6xiz3+ZczT3M4+I+JLpcPGG1bQKm8067HktB17EDWEE= -github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= -github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 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/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= -github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= -github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk= -github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/neilotoole/errgroup v0.1.6 h1:PODGqPXdT5BC/zCYIMoTrwV+ujKcW+gBXM6Ye9Ve3R8= +github.com/neilotoole/errgroup v0.1.6/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/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/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -272,156 +161,117 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL 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/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= -github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= -github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= -github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws= -github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= -github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= -github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= -github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/sjson v1.1.2 h1:NC5okI+tQ8OG/oyzchvwXXxRxCV/FVdhODbPKkQ25jQ= -github.com/tidwall/sjson v1.1.2/go.mod h1:SEzaDwxiPzKzNfUEO4HbYF/m4UCSJDsGgNqsS1LvdoY= -github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo= +github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc= +github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vmihailenco/msgpack/v5 v5.0.0-beta.8 h1:R2L6zPq1pWFumpeIxAJoeiov5GxyEZUq9NyS8eus/6s= -github.com/vmihailenco/msgpack/v5 v5.0.0-beta.8/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo= -github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= -github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= +go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A= +golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= -golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 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 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b h1:GgiSbuUyC0BlbUmHQBgFqu32eiRR/CEYdjOjOd4zE6Y= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +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/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20181011144130-49bb7cea24b1/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20181107165924-66b7b1311ac8/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20200420163511-1957bb5e6d1f/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-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/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-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI= +golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41ZHy+6MKWfXCDsjSThnsPA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +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/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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 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-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -441,33 +291,20 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ 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 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= -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 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +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= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k= -honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/indexer/balance_storage_handler.go b/indexer/balance_storage_handler.go index 52460a48..e913d752 100644 --- a/indexer/balance_storage_handler.go +++ b/indexer/balance_storage_handler.go @@ -18,11 +18,12 @@ import ( "context" "github.com/coinbase/rosetta-sdk-go/parser" - "github.com/coinbase/rosetta-sdk-go/storage" + "github.com/coinbase/rosetta-sdk-go/storage/database" + "github.com/coinbase/rosetta-sdk-go/storage/modules" "github.com/coinbase/rosetta-sdk-go/types" ) -var _ storage.BalanceStorageHandler = (*BalanceStorageHandler)(nil) +var _ modules.BalanceStorageHandler = (*BalanceStorageHandler)(nil) // BalanceStorageHandler implements storage.BalanceStorageHandler. type BalanceStorageHandler struct{} @@ -44,3 +45,21 @@ func (h *BalanceStorageHandler) BlockRemoved( ) error { return nil } + +// AccountsReconciled updates the total accounts reconciled by count. +func (h *BalanceStorageHandler) AccountsReconciled( + ctx context.Context, + dbTx database.Transaction, + count int, +) error { + return nil +} + +// AccountsSeen updates the total accounts seen by count. +func (h *BalanceStorageHandler) AccountsSeen( + ctx context.Context, + dbTx database.Transaction, + count int, +) error { + return nil +} diff --git a/indexer/balance_storage_helper.go b/indexer/balance_storage_helper.go index c36699de..573d5b13 100644 --- a/indexer/balance_storage_helper.go +++ b/indexer/balance_storage_helper.go @@ -16,14 +16,21 @@ package indexer import ( "context" + "errors" + "math/big" "github.com/coinbase/rosetta-sdk-go/asserter" "github.com/coinbase/rosetta-sdk-go/parser" - "github.com/coinbase/rosetta-sdk-go/storage" + "github.com/coinbase/rosetta-sdk-go/storage/database" + "github.com/coinbase/rosetta-sdk-go/storage/modules" "github.com/coinbase/rosetta-sdk-go/types" ) -var _ storage.BalanceStorageHelper = (*BalanceStorageHelper)(nil) +var _ modules.BalanceStorageHelper = (*BalanceStorageHelper)(nil) + +var ( + errNotImplemented = errors.New("not implemented") +) // BalanceStorageHelper implements storage.BalanceStorageHelper. type BalanceStorageHelper struct { @@ -60,3 +67,19 @@ func (h *BalanceStorageHelper) ExemptFunc() parser.ExemptOperation { return false } } + +// AccountsReconciled returns the total accounts reconciled by count. +func (h *BalanceStorageHelper) AccountsReconciled( + ctx context.Context, + dbTx database.Transaction, +) (*big.Int, error) { + return nil, errNotImplemented +} + +// AccountsSeen returns the total accounts seen by count. +func (h *BalanceStorageHelper) AccountsSeen( + ctx context.Context, + dbTx database.Transaction, +) (*big.Int, error) { + return nil, errNotImplemented +} diff --git a/indexer/coin_storage_helper.go b/indexer/coin_storage_helper.go index 36a75150..38c8cf46 100644 --- a/indexer/coin_storage_helper.go +++ b/indexer/coin_storage_helper.go @@ -17,22 +17,23 @@ package indexer import ( "context" - "github.com/coinbase/rosetta-sdk-go/storage" + "github.com/coinbase/rosetta-sdk-go/storage/database" + "github.com/coinbase/rosetta-sdk-go/storage/modules" "github.com/coinbase/rosetta-sdk-go/types" ) -var _ storage.CoinStorageHelper = (*CoinStorageHelper)(nil) +var _ modules.CoinStorageHelper = (*CoinStorageHelper)(nil) // CoinStorageHelper implements storage.CoinStorageHelper. type CoinStorageHelper struct { - b *storage.BlockStorage + b *modules.BlockStorage } // CurrentBlockIdentifier returns the current head block identifier // and is used to comply with the CoinStorageHelper interface. func (h *CoinStorageHelper) CurrentBlockIdentifier( ctx context.Context, - transaction storage.DatabaseTransaction, + transaction database.Transaction, ) (*types.BlockIdentifier, error) { return h.b.GetHeadBlockIdentifierTransactional(ctx, transaction) } diff --git a/indexer/indexer.go b/indexer/indexer.go index 431f3fcf..e391f9ca 100644 --- a/indexer/indexer.go +++ b/indexer/indexer.go @@ -18,20 +18,25 @@ import ( "context" "errors" "fmt" + "runtime" + "sync" "time" - "github.com/HorizenOfficial/rosetta-zen/zen" "github.com/HorizenOfficial/rosetta-zen/configuration" "github.com/HorizenOfficial/rosetta-zen/services" "github.com/HorizenOfficial/rosetta-zen/utils" + "github.com/HorizenOfficial/rosetta-zen/zen" "github.com/coinbase/rosetta-sdk-go/asserter" - "github.com/coinbase/rosetta-sdk-go/storage" + "github.com/coinbase/rosetta-sdk-go/storage/database" + storageErrs "github.com/coinbase/rosetta-sdk-go/storage/errors" + "github.com/coinbase/rosetta-sdk-go/storage/modules" "github.com/coinbase/rosetta-sdk-go/syncer" "github.com/coinbase/rosetta-sdk-go/types" sdkUtils "github.com/coinbase/rosetta-sdk-go/utils" "github.com/dgraph-io/badger/v2" "github.com/dgraph-io/badger/v2/options" + "golang.org/x/sync/semaphore" ) const ( @@ -56,6 +61,17 @@ const ( // zeroValue is 0 as a string zeroValue = "0" + + // overclockMultiplier is the amount + // we multiply runtime.NumCPU by to determine + // how many goroutines we should + // spwan to handle block data sequencing. + overclockMultiplier = 16 + + // semaphoreWeight is the weight of each semaphore request. + semaphoreWeight = int64(1) + + blockLeftShift = 20 ) var ( @@ -70,7 +86,7 @@ type Client interface { ParseBlock( context.Context, *zen.Block, - map[string]*storage.AccountCoin, + map[string]*types.AccountCoin, ) (*types.Block, error) } @@ -88,13 +104,27 @@ type Indexer struct { client Client asserter *asserter.Asserter - database storage.Database - blockStorage *storage.BlockStorage - balanceStorage *storage.BalanceStorage - coinStorage *storage.CoinStorage - workers []storage.BlockWorker + database database.Database + blockStorage *modules.BlockStorage + balanceStorage *modules.BalanceStorage + coinStorage *modules.CoinStorage + workers []modules.BlockWorker waiter *waitTable + + // Store coins created in pre-store before persisted + // in add block so we can optimistically populate + // blocks before committed. + coinCache map[string]*types.AccountCoin + coinCacheMutex *sdkUtils.PriorityMutex + + // When populating blocks using pre-stored blocks, + // we should retry if a new block was seen (similar + // to trying again if head block changes). + seen int64 + seenMutex sync.Mutex + + seenSemaphore *semaphore.Weighted } // CloseDatabase closes a storage.Database. This should be called @@ -121,15 +151,15 @@ func defaultBadgerOptions( opts.Compression = options.None // Load tables into memory and memory map value logs. - opts.TableLoadingMode = options.MemoryMap - opts.ValueLogLoadingMode = options.MemoryMap + opts.TableLoadingMode = options.FileIO + opts.ValueLogLoadingMode = options.FileIO // Use an extended table size for larger commits. - opts.MaxTableSize = storage.DefaultMaxTableSize + opts.MaxTableSize = database.DefaultMaxTableSize // Smaller value log sizes means smaller contiguous memory allocations // and less RAM usage on cleanup. - opts.ValueLogFileSize = storage.DefaultLogValueSize + opts.ValueLogFileSize = database.DefaultLogValueSize // To allow writes at a faster speed, we create a new memtable as soon as // an existing memtable is filled up. This option determines how many @@ -154,6 +184,13 @@ func defaultBadgerOptions( // filters will be immediately discarded from the cache). opts.LoadBloomsOnOpen = false + // BlockSize sets the size of any block in SSTable. SSTable is divided into multiple blocks + // internally. We set each block to 1MB. + opts.BlockSize = 1 << blockLeftShift // 1MB + + // NumCompactors sets the number of compaction workers to run concurrently. + opts.NumCompactors = 2 + return opts } @@ -164,11 +201,11 @@ func Initialize( config *configuration.Configuration, client Client, ) (*Indexer, error) { - localStore, err := storage.NewBadgerStorage( + localStore, err := database.NewBadgerDatabase( ctx, config.IndexerPath, - storage.WithCompressorEntries(config.Compressors), - storage.WithCustomSettings(defaultBadgerOptions( + database.WithCompressorEntries(config.Compressors), + database.WithCustomSettings(defaultBadgerOptions( config.IndexerPath, )), ) @@ -176,7 +213,7 @@ func Initialize( return nil, fmt.Errorf("%w: unable to initialize storage", err) } - blockStorage := storage.NewBlockStorage(localStore) + blockStorage := modules.NewBlockStorage(localStore, runtime.NumCPU()*overclockMultiplier) asserter, err := asserter.NewClientWithOptions( config.Network, config.GenesisBlockIdentifier, @@ -184,37 +221,41 @@ func Initialize( zen.OperationStatuses, services.Errors, nil, + new(asserter.Validations), ) if err != nil { return nil, fmt.Errorf("%w: unable to initialize asserter", err) } i := &Indexer{ - cancel: cancel, - network: config.Network, - pruningConfig: config.Pruning, - client: client, - database: localStore, - blockStorage: blockStorage, - waiter: newWaitTable(), - asserter: asserter, + cancel: cancel, + network: config.Network, + pruningConfig: config.Pruning, + client: client, + database: localStore, + blockStorage: blockStorage, + waiter: newWaitTable(), + asserter: asserter, + coinCache: map[string]*types.AccountCoin{}, + coinCacheMutex: new(sdkUtils.PriorityMutex), + seenSemaphore: semaphore.NewWeighted(int64(runtime.NumCPU())), } - coinStorage := storage.NewCoinStorage( + coinStorage := modules.NewCoinStorage( localStore, &CoinStorageHelper{blockStorage}, asserter, ) i.coinStorage = coinStorage - balanceStorage := storage.NewBalanceStorage(localStore) + balanceStorage := modules.NewBalanceStorage(localStore) balanceStorage.Initialize( &BalanceStorageHelper{asserter}, &BalanceStorageHandler{}, ) i.balanceStorage = balanceStorage - i.workers = []storage.BlockWorker{coinStorage, balanceStorage} + i.workers = []modules.BlockWorker{coinStorage, balanceStorage} return i, nil } @@ -243,7 +284,7 @@ func (i *Indexer) Sync(ctx context.Context) error { if err := i.waitForNode(ctx); err != nil { return fmt.Errorf("%w: failed to wait for node", err) } - logger := utils.ExtractLogger(ctx, "indexer") + logger := utils.ExtractLogger(ctx, "indexer") logger.Infow("call blocktorage.init...") i.blockStorage.Initialize(i.workers) @@ -257,7 +298,7 @@ func (i *Indexer) Sync(ctx context.Context) error { // If previously processed blocks exist in storage, they are fetched. // Otherwise, none are provided to the cache (the syncer will not attempt // a reorg if the cache is empty). - pastBlocks := i.blockStorage.CreateBlockCache(ctx) + pastBlocks := i.blockStorage.CreateBlockCache(ctx, syncer.DefaultPastBlockLimit) syncer := syncer.New( i.network, @@ -331,34 +372,31 @@ func (i *Indexer) BlockAdded(ctx context.Context, block *types.Block) error { ops := 0 - // Close channels of all blocks waiting. - i.waiter.Lock() for _, transaction := range block.Transactions { ops += len(transaction.Operations) - txHash := transaction.TransactionIdentifier.Hash - val, ok := i.waiter.Get(txHash, false) - if !ok { - continue - } + } - if val.channelClosed { - logger.Debugw( - "channel already closed", - "hash", block.BlockIdentifier.Hash, - "index", block.BlockIdentifier.Index, - "channel", txHash, - ) - continue - } + // clean cache intermediate + i.coinCacheMutex.Lock(true) + for _, tx := range block.Transactions { + for _, op := range tx.Operations { + if op.CoinChange == nil { + continue + } - // Closing channel will cause all listeners to continue - val.channelClosed = true - close(val.channel) + if op.CoinChange.CoinAction != types.CoinCreated { + continue + } + + delete(i.coinCache, op.CoinChange.CoinIdentifier.Identifier) + } } + i.coinCacheMutex.Unlock() // Look for all remaining waiting transactions associated // with the next block that have not yet been closed. We should // abort these waits as they will never be closed by a new transaction. + i.waiter.Lock() for txHash, val := range i.waiter.table { if val.earliestBlock == block.BlockIdentifier.Index+1 && !val.channelClosed { logger.Debugw( @@ -385,6 +423,91 @@ func (i *Indexer) BlockAdded(ctx context.Context, block *types.Block) error { return nil } +// BlockSeen is called by the syncer when a block is encountered. +func (i *Indexer) BlockSeen(ctx context.Context, block *types.Block) error { + if err := i.seenSemaphore.Acquire(ctx, semaphoreWeight); err != nil { + return err + } + defer i.seenSemaphore.Release(semaphoreWeight) + + logger := utils.ExtractLogger(ctx, "indexer") + + // load intermediate + i.coinCacheMutex.Lock(false) + for _, tx := range block.Transactions { + for _, op := range tx.Operations { + if op.CoinChange == nil { + continue + } + + // We only care about newly accessible coins. + if op.CoinChange.CoinAction != types.CoinCreated { + continue + } + + i.coinCache[op.CoinChange.CoinIdentifier.Identifier] = &types.AccountCoin{ + Account: op.Account, + Coin: &types.Coin{ + CoinIdentifier: op.CoinChange.CoinIdentifier, + Amount: op.Amount, + }, + } + } + } + i.coinCacheMutex.Unlock() + + // Update so that lookers know it exists + i.seenMutex.Lock() + i.seen++ + i.seenMutex.Unlock() + + err := i.blockStorage.SeeBlock(ctx, block) + if err != nil { + return fmt.Errorf( + "%w: unable to encounter block to storage %s:%d", + err, + block.BlockIdentifier.Hash, + block.BlockIdentifier.Index, + ) + } + + ops := 0 + + // Close channels of all blocks waiting. + i.waiter.Lock() + for _, transaction := range block.Transactions { + ops += len(transaction.Operations) + txHash := transaction.TransactionIdentifier.Hash + val, ok := i.waiter.Get(txHash, false) + if !ok { + continue + } + + if val.channelClosed { + logger.Debugw( + "channel already closed", + "hash", block.BlockIdentifier.Hash, + "index", block.BlockIdentifier.Index, + "channel", txHash, + ) + continue + } + + // Closing channel will cause all listeners to continue + val.channelClosed = true + close(val.channel) + } + i.waiter.Unlock() + + logger.Debugw( + "block seen", + "hash", block.BlockIdentifier.Hash, + "index", block.BlockIdentifier.Index, + ) + + return nil +} + // BlockRemoved is called by the syncer when a block is removed. func (i *Indexer) BlockRemoved( ctx context.Context, @@ -424,14 +547,14 @@ func (i *Indexer) findCoin( coinIdentifier string, ) (*types.Coin, *types.AccountIdentifier, error) { for ctx.Err() == nil { - databaseTransaction := i.database.NewDatabaseTransaction(ctx, false) + databaseTransaction := i.database.ReadTransaction(ctx) defer databaseTransaction.Discard(ctx) coinHeadBlock, err := i.blockStorage.GetHeadBlockIdentifierTransactional( ctx, databaseTransaction, ) - if errors.Is(err, storage.ErrHeadBlockNotFound) { + if errors.Is(err, storageErrs.ErrHeadBlockNotFound) { if err := sdkUtils.ContextSleep(ctx, missingTransactionDelay); err != nil { return nil, nil, err } @@ -457,12 +580,20 @@ func (i *Indexer) findCoin( return coin, owner, nil } - if !errors.Is(err, storage.ErrCoinNotFound) { + if !errors.Is(err, storageErrs.ErrCoinNotFound) { return nil, nil, fmt.Errorf("%w: unable to lookup coin %s", err, coinIdentifier) } + // Check seen CoinCache + i.coinCacheMutex.Lock(false) + accCoin, ok := i.coinCache[coinIdentifier] + i.coinCacheMutex.Unlock() + if ok { + return accCoin.Coin, accCoin.Account, nil + } + // Locking here prevents us from adding sending any done - // signals while we are determining whether or not to add + // signals while we are determining whether to add // to the WaitTable. i.waiter.Lock() @@ -508,7 +639,7 @@ func (i *Indexer) checkHeaderMatch( btcBlock *zen.Block, ) error { headBlock, err := i.blockStorage.GetHeadBlockIdentifier(ctx) - if err != nil && !errors.Is(err, storage.ErrHeadBlockNotFound) { + if err != nil && !errors.Is(err, storageErrs.ErrHeadBlockNotFound) { return fmt.Errorf("%w: unable to lookup head block", err) } @@ -527,12 +658,12 @@ func (i *Indexer) findCoins( ctx context.Context, btcBlock *zen.Block, coins []string, -) (map[string]*storage.AccountCoin, error) { +) (map[string]*types.AccountCoin, error) { if err := i.checkHeaderMatch(ctx, btcBlock); err != nil { return nil, fmt.Errorf("%w: check header match failed", err) } - coinMap := map[string]*storage.AccountCoin{} + coinMap := map[string]*types.AccountCoin{} remainingCoins := []string{} for _, coinIdentifier := range coins { coin, owner, err := i.findCoin( @@ -541,7 +672,7 @@ func (i *Indexer) findCoins( coinIdentifier, ) if err == nil { - coinMap[coinIdentifier] = &storage.AccountCoin{ + coinMap[coinIdentifier] = &types.AccountCoin{ Account: owner, Coin: coin, } @@ -675,7 +806,7 @@ func (i *Indexer) GetScriptPubKeys( ctx context.Context, coins []*types.Coin, ) ([]*zen.ScriptPubKey, error) { - databaseTransaction := i.database.NewDatabaseTransaction(ctx, false) + databaseTransaction := i.database.ReadTransaction(ctx) defer databaseTransaction.Discard(ctx) scripts := make([]*zen.ScriptPubKey, len(coins)) @@ -788,7 +919,7 @@ func (i *Indexer) GetBalance( currency *types.Currency, blockIdentifier *types.PartialBlockIdentifier, ) (*types.Amount, *types.BlockIdentifier, error) { - dbTx := i.database.NewDatabaseTransaction(ctx, false) + dbTx := i.database.ReadTransaction(ctx) defer dbTx.Discard(ctx) blockResponse, err := i.blockStorage.GetBlockLazyTransactional( @@ -807,7 +938,7 @@ func (i *Indexer) GetBalance( currency, blockResponse.Block.BlockIdentifier.Index, ) - if errors.Is(err, storage.ErrAccountMissing) { + if errors.Is(err, storageErrs.ErrAccountMissing) { return &types.Amount{ Value: zeroValue, Currency: currency, diff --git a/indexer/indexer_test.go b/indexer/indexer_test.go index 231e066f..9c4f8d30 100644 --- a/indexer/indexer_test.go +++ b/indexer/indexer_test.go @@ -23,11 +23,10 @@ import ( "testing" "time" - "github.com/HorizenOfficial/rosetta-zen/zen" "github.com/HorizenOfficial/rosetta-zen/configuration" mocks "github.com/HorizenOfficial/rosetta-zen/mocks/indexer" + "github.com/HorizenOfficial/rosetta-zen/zen" - "github.com/coinbase/rosetta-sdk-go/storage" "github.com/coinbase/rosetta-sdk-go/types" "github.com/coinbase/rosetta-sdk-go/utils" "github.com/stretchr/testify/assert" @@ -48,7 +47,6 @@ var ( func TestIndexer_Pruning(t *testing.T) { // Create Indexer - ctx := context.Background() ctx, cancel := context.WithCancel(context.Background()) newDir, err := utils.CreateTempDir() @@ -157,7 +155,7 @@ func TestIndexer_Pruning(t *testing.T) { "ParseBlock", mock.Anything, block, - map[string]*storage.AccountCoin{}, + map[string]*types.AccountCoin{}, ).Return( blockReturn, nil, @@ -167,7 +165,7 @@ func TestIndexer_Pruning(t *testing.T) { "ParseBlock", mock.Anything, block, - map[string]*storage.AccountCoin{}, + map[string]*types.AccountCoin{}, ).Return( blockReturn, nil, @@ -215,7 +213,6 @@ func TestIndexer_Pruning(t *testing.T) { func TestIndexer_Transactions(t *testing.T) { // Create Indexer - ctx := context.Background() ctx, cancel := context.WithCancel(context.Background()) newDir, err := utils.CreateTempDir() @@ -286,7 +283,7 @@ func TestIndexer_Transactions(t *testing.T) { Index: 0, NetworkIndex: &index0, }, - Status: zen.SuccessStatus, + Status: types.String(zen.SuccessStatus), Type: zen.OutputOpType, Account: &types.AccountIdentifier{ Address: rawHash, @@ -356,9 +353,9 @@ func TestIndexer_Transactions(t *testing.T) { Transactions: transactions, } - coinMap := map[string]*storage.AccountCoin{} + coinMap := map[string]*types.AccountCoin{} for _, coinIdentifier := range requiredCoins { - coinMap[coinIdentifier] = &storage.AccountCoin{ + coinMap[coinIdentifier] = &types.AccountCoin{ Account: coinBank[coinIdentifier].Account, Coin: coinBank[coinIdentifier].Coin, } @@ -433,7 +430,6 @@ func TestIndexer_Transactions(t *testing.T) { func TestIndexer_Reorg(t *testing.T) { // Create Indexer - ctx := context.Background() ctx, cancel := context.WithCancel(context.Background()) newDir, err := utils.CreateTempDir() @@ -505,7 +501,7 @@ func TestIndexer_Reorg(t *testing.T) { Index: 0, NetworkIndex: &index0, }, - Status: zen.SuccessStatus, + Status: types.String(zen.SuccessStatus), Type: zen.OutputOpType, Account: &types.AccountIdentifier{ Address: rawHash, @@ -602,9 +598,9 @@ func TestIndexer_Reorg(t *testing.T) { Transactions: transactions, } - coinMap := map[string]*storage.AccountCoin{} + coinMap := map[string]*types.AccountCoin{} for _, coinIdentifier := range requiredCoins { - coinMap[coinIdentifier] = &storage.AccountCoin{ + coinMap[coinIdentifier] = &types.AccountCoin{ Account: coinBank[coinIdentifier].Account, Coin: coinBank[coinIdentifier].Coin, } @@ -675,7 +671,6 @@ func TestIndexer_Reorg(t *testing.T) { func TestIndexer_HeaderReorg(t *testing.T) { // Create Indexer - ctx := context.Background() ctx, cancel := context.WithCancel(context.Background()) newDir, err := utils.CreateTempDir() @@ -774,7 +769,7 @@ func TestIndexer_HeaderReorg(t *testing.T) { Transactions: transactions, } - coinMap := map[string]*storage.AccountCoin{} + coinMap := map[string]*types.AccountCoin{} if i == 400 { mockClient.On( "ParseBlock", diff --git a/main.go b/main.go index f3ba8b20..b780e69e 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,6 @@ import ( "github.com/coinbase/rosetta-sdk-go/server" "github.com/coinbase/rosetta-sdk-go/types" "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" - "go.uber.org/zap" "golang.org/x/sync/errgroup" ) @@ -113,27 +112,23 @@ func startOnlineDependencies( } func main() { - loggerRaw, err := zap.NewDevelopment() + loggerRaw, err := utils.NewLogger() if err != nil { log.Fatalf("can't initialize zap logger: %v", err) } - defer func() { _ = loggerRaw.Sync() }() - ctx := context.Background() ctx = ctxzap.ToContext(ctx, loggerRaw) ctx, cancel := context.WithCancel(ctx) go handleSignals(ctx, []context.CancelFunc{cancel}) logger := loggerRaw.Sugar().Named("main") - cfg, err := configuration.LoadConfiguration(configuration.DataDirectory) if err != nil { - logger.Fatalw("unable to load configuration", "error", err) + logger.Fatalw("Unable to load configuration", "error", err) } - logger.Infow("loaded configuration", "configuration", types.PrintStruct(cfg)) g, ctx := errgroup.WithContext(ctx) @@ -151,22 +146,24 @@ func main() { } } - // The asserter automatically rejects incorrectly formatted + // The assertServer automatically rejects incorrectly formatted // requests. - asserter, err := asserter.NewServer( + assertServer, err := asserter.NewServer( zen.OperationTypes, services.HistoricalBalanceLookup, []*types.NetworkIdentifier{cfg.Network}, nil, + services.MempoolCoins, + "", ) if err != nil { - logger.Fatalw("unable to create new server asserter", "error", err) + logger.Fatalw("unable to create new httpServer assertServer", "error", err) } - router := services.NewBlockchainRouter(cfg, client, i, asserter) + router := services.NewBlockchainRouter(cfg, client, i, assertServer) loggedRouter := services.LoggerMiddleware(loggerRaw, router) corsRouter := server.CorsMiddleware(loggedRouter) - server := &http.Server{ + httpServer := &http.Server{ Addr: fmt.Sprintf(":%d", cfg.Port), Handler: corsRouter, ReadTimeout: readTimeout, @@ -175,17 +172,17 @@ func main() { } g.Go(func() error { - logger.Infow("server listening", "port", cfg.Port) - return server.ListenAndServe() + logger.Infow("httpServer listening", "port", cfg.Port) + return httpServer.ListenAndServe() }) g.Go(func() error { - // If we don't shutdown server in errgroup, it will - // never stop because server.ListenAndServe doesn't + // If we don't shutdown httpServer in errgroup, it will + // never stop because httpServer.ListenAndServe doesn't // take any context. <-ctx.Done() - return server.Shutdown(ctx) + return httpServer.Shutdown(ctx) }) err = g.Wait() diff --git a/mocks/indexer/client.go b/mocks/indexer/client.go index ff3abf9b..0841a160 100644 --- a/mocks/indexer/client.go +++ b/mocks/indexer/client.go @@ -1,17 +1,15 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package indexer import ( context "context" - bitcoin "github.com/HorizenOfficial/rosetta-zen/zen" - mock "github.com/stretchr/testify/mock" - storage "github.com/coinbase/rosetta-sdk-go/storage" - types "github.com/coinbase/rosetta-sdk-go/types" + + zen "github.com/HorizenOfficial/rosetta-zen/zen" ) // Client is an autogenerated mock type for the Client type @@ -20,15 +18,15 @@ type Client struct { } // GetRawBlock provides a mock function with given fields: _a0, _a1 -func (_m *Client) GetRawBlock(_a0 context.Context, _a1 *types.PartialBlockIdentifier) (*bitcoin.Block, []string, error) { +func (_m *Client) GetRawBlock(_a0 context.Context, _a1 *types.PartialBlockIdentifier) (*zen.Block, []string, error) { ret := _m.Called(_a0, _a1) - var r0 *bitcoin.Block - if rf, ok := ret.Get(0).(func(context.Context, *types.PartialBlockIdentifier) *bitcoin.Block); ok { + var r0 *zen.Block + if rf, ok := ret.Get(0).(func(context.Context, *types.PartialBlockIdentifier) *zen.Block); ok { r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*bitcoin.Block) + r0 = ret.Get(0).(*zen.Block) } } @@ -75,11 +73,11 @@ func (_m *Client) NetworkStatus(_a0 context.Context) (*types.NetworkStatusRespon } // ParseBlock provides a mock function with given fields: _a0, _a1, _a2 -func (_m *Client) ParseBlock(_a0 context.Context, _a1 *bitcoin.Block, _a2 map[string]*storage.AccountCoin) (*types.Block, error) { +func (_m *Client) ParseBlock(_a0 context.Context, _a1 *zen.Block, _a2 map[string]*types.AccountCoin) (*types.Block, error) { ret := _m.Called(_a0, _a1, _a2) var r0 *types.Block - if rf, ok := ret.Get(0).(func(context.Context, *bitcoin.Block, map[string]*storage.AccountCoin) *types.Block); ok { + if rf, ok := ret.Get(0).(func(context.Context, *zen.Block, map[string]*types.AccountCoin) *types.Block); ok { r0 = rf(_a0, _a1, _a2) } else { if ret.Get(0) != nil { @@ -88,7 +86,7 @@ func (_m *Client) ParseBlock(_a0 context.Context, _a1 *bitcoin.Block, _a2 map[st } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *bitcoin.Block, map[string]*storage.AccountCoin) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *zen.Block, map[string]*types.AccountCoin) error); ok { r1 = rf(_a0, _a1, _a2) } else { r1 = ret.Error(1) @@ -117,3 +115,18 @@ func (_m *Client) PruneBlockchain(_a0 context.Context, _a1 int64) (int64, error) return r0, r1 } + +type mockConstructorTestingTNewClient interface { + mock.TestingT + Cleanup(func()) +} + +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewClient(t mockConstructorTestingTNewClient) *Client { + mock := &Client{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/services/client.go b/mocks/services/client.go index 97694c43..c6775182 100644 --- a/mocks/services/client.go +++ b/mocks/services/client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package services @@ -15,6 +15,48 @@ type Client struct { mock.Mock } +// GetBestBlock provides a mock function with given fields: _a0 +func (_m *Client) GetBestBlock(_a0 context.Context) (int64, error) { + ret := _m.Called(_a0) + + var r0 int64 + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(int64) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetHashFromIndex provides a mock function with given fields: _a0, _a1 +func (_m *Client) GetHashFromIndex(_a0 context.Context, _a1 int64) (string, error) { + ret := _m.Called(_a0, _a1) + + var r0 string + if rf, ok := ret.Get(0).(func(context.Context, int64) string); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetPeers provides a mock function with given fields: _a0 func (_m *Client) GetPeers(_a0 context.Context) ([]*types.Peer, error) { ret := _m.Called(_a0) @@ -82,43 +124,20 @@ func (_m *Client) SendRawTransaction(_a0 context.Context, _a1 string) (string, e return r0, r1 } -// SuggestedFeeRate provides a mock function with given fields: _a0, _a1 -func (_m *Client) SuggestedFeeRate(_a0 context.Context, _a1 int64) (float64, error) { - ret := _m.Called(_a0, _a1) +// SetZendNodeVersion provides a mock function with given fields: ctx +func (_m *Client) SetZendNodeVersion(ctx context.Context) (string, error) { + ret := _m.Called(ctx) - var r0 float64 - if rf, ok := ret.Get(0).(func(context.Context, int64) float64); ok { - r0 = rf(_a0, _a1) - } else { - r0 = ret.Get(0).(float64) - } - - var r1 error - if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(_a0, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetBestBlock provides a mock function with given fields: _a0 -func (_m *Client) GetBestBlock(_a0 context.Context) (int64, error) { - ret := _m.Called(_a0) - - var r0 int64 - if rf, ok := ret.Get(0).(func(context.Context) int64); ok { - r0 = rf(_a0) + var r0 string + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(ctx) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(int64) - } + r0 = ret.Get(0).(string) } var r1 error if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(_a0) + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -126,15 +145,15 @@ func (_m *Client) GetBestBlock(_a0 context.Context) (int64, error) { return r0, r1 } -// GetBestBlock provides a mock function with given fields: _a0, _a1 -func (_m *Client) GetHashFromIndex(_a0 context.Context, _a1 int64) (string, error) { +// SuggestedFeeRate provides a mock function with given fields: _a0, _a1 +func (_m *Client) SuggestedFeeRate(_a0 context.Context, _a1 int64) (float64, error) { ret := _m.Called(_a0, _a1) - var r0 string - if rf, ok := ret.Get(0).(func(context.Context, int64) string); ok { + var r0 float64 + if rf, ok := ret.Get(0).(func(context.Context, int64) float64); ok { r0 = rf(_a0, _a1) } else { - r0 = ret.Get(0).(string) + r0 = ret.Get(0).(float64) } var r1 error @@ -146,3 +165,18 @@ func (_m *Client) GetHashFromIndex(_a0 context.Context, _a1 int64) (string, erro return r0, r1 } + +type mockConstructorTestingTNewClient interface { + mock.TestingT + Cleanup(func()) +} + +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewClient(t mockConstructorTestingTNewClient) *Client { + mock := &Client{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/services/indexer.go b/mocks/services/indexer.go index a48b94af..12f50ebc 100644 --- a/mocks/services/indexer.go +++ b/mocks/services/indexer.go @@ -1,15 +1,15 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package services import ( context "context" - bitcoin "github.com/HorizenOfficial/rosetta-zen/zen" - mock "github.com/stretchr/testify/mock" types "github.com/coinbase/rosetta-sdk-go/types" + + zen "github.com/HorizenOfficial/rosetta-zen/zen" ) // Indexer is an autogenerated mock type for the Indexer type @@ -128,15 +128,15 @@ func (_m *Indexer) GetCoins(_a0 context.Context, _a1 *types.AccountIdentifier) ( } // GetScriptPubKeys provides a mock function with given fields: _a0, _a1 -func (_m *Indexer) GetScriptPubKeys(_a0 context.Context, _a1 []*types.Coin) ([]*bitcoin.ScriptPubKey, error) { +func (_m *Indexer) GetScriptPubKeys(_a0 context.Context, _a1 []*types.Coin) ([]*zen.ScriptPubKey, error) { ret := _m.Called(_a0, _a1) - var r0 []*bitcoin.ScriptPubKey - if rf, ok := ret.Get(0).(func(context.Context, []*types.Coin) []*bitcoin.ScriptPubKey); ok { + var r0 []*zen.ScriptPubKey + if rf, ok := ret.Get(0).(func(context.Context, []*types.Coin) []*zen.ScriptPubKey); ok { r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*bitcoin.ScriptPubKey) + r0 = ret.Get(0).([]*zen.ScriptPubKey) } } @@ -149,3 +149,18 @@ func (_m *Indexer) GetScriptPubKeys(_a0 context.Context, _a1 []*types.Coin) ([]* return r0, r1 } + +type mockConstructorTestingTNewIndexer interface { + mock.TestingT + Cleanup(func()) +} + +// NewIndexer creates a new instance of Indexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewIndexer(t mockConstructorTestingTNewIndexer) *Indexer { + mock := &Indexer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/server/api_logger.go b/server/api_logger.go new file mode 100644 index 00000000..1a2ea8e5 --- /dev/null +++ b/server/api_logger.go @@ -0,0 +1,69 @@ +// Copyright 2022 Coinbase, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "net/http" + "strings" + + "github.com/coinbase/rosetta-sdk-go/asserter" + "github.com/coinbase/rosetta-sdk-go/server" +) + +// LoggerAPIServicer defines the api actions for the LoggerAPI service +type LoggerAPIServicer interface { + LogLevel(w http.ResponseWriter, r *http.Request) +} + +// A LoggerApiController binds http requests to an api service and writes the service results to +// the http response +type LoggerApiController struct { + service LoggerAPIServicer + asserter *asserter.Asserter +} + +// NewLoggerApiController creates a default api controller +func NewLoggerApiController( + s LoggerAPIServicer, + asserter *asserter.Asserter, +) server.Router { + return &LoggerApiController{ + service: s, + asserter: asserter, + } +} + +// Routes returns all the api routes for the LoggerApiController +func (c *LoggerApiController) Routes() server.Routes { + return server.Routes{ + { + "LogLevel", + strings.ToUpper("Get"), + "/log/level", + c.LogLevel, + }, + { + "UpdateLogLevel", + strings.ToUpper("Put"), + "/log/level", + c.LogLevel, + }, + } +} + +// LogLevel Get the log level or update it +func (c *LoggerApiController) LogLevel(w http.ResponseWriter, r *http.Request) { + c.service.LogLevel(w, r) +} diff --git a/services/account_service.go b/services/account_service.go index 1a453b51..254ff444 100644 --- a/services/account_service.go +++ b/services/account_service.go @@ -68,7 +68,6 @@ func (s *AccountAPIService) AccountBalance( return &types.AccountBalanceResponse{ BlockIdentifier: block, - Coins: coins, Balances: []*types.Amount{ { Value: balance, @@ -97,3 +96,31 @@ func (s *AccountAPIService) AccountBalance( }, }, nil } + +// AccountCoins implements /account/coins. +func (s *AccountAPIService) AccountCoins( + ctx context.Context, + request *types.AccountCoinsRequest, +) (*types.AccountCoinsResponse, *types.Error) { + if s.config.Mode != configuration.Online { + return nil, wrapErr(ErrUnavailableOffline, nil) + } + + // TODO: filter coins by request currencies + + // TODO: support include_mempool query + // https://github.com/coinbase/rosetta-bitcoin/issues/36#issuecomment-724992022 + // Once mempoolcoins are supported also change the bool service/types.go:MempoolCoins to true + + coins, block, err := s.i.GetCoins(ctx, request.AccountIdentifier) + if err != nil { + return nil, wrapErr(ErrUnableToGetCoins, err) + } + + result := &types.AccountCoinsResponse{ + BlockIdentifier: block, + Coins: coins, + } + + return result, nil +} diff --git a/services/account_service_test.go b/services/account_service_test.go index 0b78801b..5344a5a2 100644 --- a/services/account_service_test.go +++ b/services/account_service_test.go @@ -73,25 +73,6 @@ func TestAccountBalance_Online_Current(t *testing.T) { }, } - expectedCoins := []*types.Coin{ - { - Amount: &types.Amount{ - Value: "10", - }, - CoinIdentifier: &types.CoinIdentifier{ - Identifier: "coin 1", - }, - }, - { - Amount: &types.Amount{ - Value: "15", - }, - CoinIdentifier: &types.CoinIdentifier{ - Identifier: "coin 2", - }, - }, - } - block := &types.BlockIdentifier{ Index: 1000, Hash: "block 1000", @@ -105,7 +86,6 @@ func TestAccountBalance_Online_Current(t *testing.T) { assert.Equal(t, &types.AccountBalanceResponse{ BlockIdentifier: block, - Coins: expectedCoins, Balances: []*types.Amount{ { Value: "25", @@ -161,3 +141,61 @@ func TestAccountBalance_Online_Historical(t *testing.T) { mockIndexer.AssertExpectations(t) } + +func TestAccountCoins_Online(t *testing.T) { + cfg := &configuration.Configuration{ + Mode: configuration.Online, + Currency: zen.MainnetCurrency, + } + mockIndexer := &mocks.Indexer{} + servicer := NewAccountAPIService(cfg, mockIndexer) + ctx := context.Background() + + account := &types.AccountIdentifier{ + Address: "hello", + } + + coins := []*types.Coin{ + { + Amount: &types.Amount{ + Value: "10", + }, + CoinIdentifier: &types.CoinIdentifier{ + Identifier: "coin 1", + }, + }, + { + Amount: &types.Amount{ + Value: "15", + }, + CoinIdentifier: &types.CoinIdentifier{ + Identifier: "coin 2", + }, + }, + { + Amount: &types.Amount{ + Value: "0", + }, + CoinIdentifier: &types.CoinIdentifier{ + Identifier: "coin 3", + }, + }, + } + block := &types.BlockIdentifier{ + Index: 1000, + Hash: "block 1000", + } + mockIndexer.On("GetCoins", ctx, account).Return(coins, block, nil).Once() + + bal, err := servicer.AccountCoins(ctx, &types.AccountCoinsRequest{ + AccountIdentifier: account, + }) + assert.Nil(t, err) + + assert.Equal(t, &types.AccountCoinsResponse{ + BlockIdentifier: block, + Coins: coins, + }, bal) + + mockIndexer.AssertExpectations(t) +} diff --git a/services/logger_service.go b/services/logger_service.go new file mode 100644 index 00000000..bbce8115 --- /dev/null +++ b/services/logger_service.go @@ -0,0 +1,19 @@ +package services + +import ( + "github.com/HorizenOfficial/rosetta-zen/utils" + "net/http" +) + +// LoggerAPIService implements the LoggerAPIServicer interface. +type LoggerAPIService struct{} + +// NewLoggerAPIService creates a new instance of a LoggerAPIService. +func NewLoggerAPIService() *LoggerAPIService { + return &LoggerAPIService{} +} + +// LogLevel implements the /log/level endpoint. +func (s *LoggerAPIService) LogLevel(w http.ResponseWriter, r *http.Request) { + utils.Atom.ServeHTTP(w, r) +} diff --git a/services/logger_service_test.go b/services/logger_service_test.go new file mode 100644 index 00000000..c9dc3dec --- /dev/null +++ b/services/logger_service_test.go @@ -0,0 +1,58 @@ +package services + +import ( + "github.com/HorizenOfficial/rosetta-zen/utils" + "github.com/stretchr/testify/assert" + "go.uber.org/zap" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestGetLogLevel(t *testing.T) { + logger, err := utils.NewLogger() + assert.Nil(t, err) + assert.True(t, logger.Core().Enabled(zap.DebugLevel)) + assert.Equal(t, zap.DebugLevel, utils.Atom.Level()) + loggerAPIService := NewLoggerAPIService() + req := httptest.NewRequest(http.MethodGet, "/log/level", nil) + w := httptest.NewRecorder() + loggerAPIService.LogLevel(w, req) + res := w.Result() + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + assert.True(t, false) + } + }(res.Body) + data, err := io.ReadAll(res.Body) + assert.Nil(t, err) + assert.Equal(t, "{\"level\":\"debug\"}\n", string(data)) + assert.True(t, logger.Core().Enabled(zap.DebugLevel)) + assert.Equal(t, zap.DebugLevel, utils.Atom.Level()) +} + +func TestPutLogLevel(t *testing.T) { + logger, err := utils.NewLogger() + assert.Nil(t, err) + assert.True(t, logger.Core().Enabled(zap.DebugLevel)) + assert.Equal(t, zap.DebugLevel, utils.Atom.Level()) + loggerAPIService := NewLoggerAPIService() + req := httptest.NewRequest(http.MethodPut, "/log/level", strings.NewReader("{\"level\":\"info\"}")) + w := httptest.NewRecorder() + loggerAPIService.LogLevel(w, req) + res := w.Result() + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + assert.True(t, false) + } + }(res.Body) + data, err := io.ReadAll(res.Body) + assert.Nil(t, err) + assert.Equal(t, "{\"level\":\"info\"}\n", string(data)) + assert.True(t, logger.Core().Enabled(zap.InfoLevel)) + assert.Equal(t, zap.InfoLevel, utils.Atom.Level()) +} diff --git a/services/network_service.go b/services/network_service.go index 5f29beb1..a9bee054 100644 --- a/services/network_service.go +++ b/services/network_service.go @@ -16,10 +16,8 @@ package services import ( "context" - - "github.com/HorizenOfficial/rosetta-zen/zen" "github.com/HorizenOfficial/rosetta-zen/configuration" - + "github.com/HorizenOfficial/rosetta-zen/zen" "github.com/coinbase/rosetta-sdk-go/server" "github.com/coinbase/rosetta-sdk-go/types" ) @@ -88,16 +86,22 @@ func (s *NetworkAPIService) NetworkOptions( ctx context.Context, request *types.NetworkRequest, ) (*types.NetworkOptionsResponse, *types.Error) { + if s.config.ZendVersion == "" { + version, _ := s.client.SetZendNodeVersion(ctx) + s.config.ZendVersion = version + } return &types.NetworkOptionsResponse{ Version: &types.Version{ RosettaVersion: types.RosettaAPIVersion, - NodeVersion: NodeVersion, - MiddlewareVersion: &MiddlewareVersion, + NodeVersion: s.config.ZendVersion, + MiddlewareVersion: types.String(MiddlewareVersion), }, Allow: &types.Allow{ - OperationStatuses: zen.OperationStatuses, - OperationTypes: zen.OperationTypes, - Errors: Errors, - HistoricalBalanceLookup: HistoricalBalanceLookup, }, + OperationStatuses: zen.OperationStatuses, + OperationTypes: zen.OperationTypes, + Errors: Errors, + HistoricalBalanceLookup: HistoricalBalanceLookup, + MempoolCoins: MempoolCoins, + }, }, nil } diff --git a/services/network_service_test.go b/services/network_service_test.go index 1d98998b..19d33a8d 100644 --- a/services/network_service_test.go +++ b/services/network_service_test.go @@ -30,7 +30,7 @@ var ( defaultNetworkOptions = &types.NetworkOptionsResponse{ Version: &types.Version{ RosettaVersion: types.RosettaAPIVersion, - NodeVersion: "3.2.0", + NodeVersion: "1.0.0", MiddlewareVersion: &middlewareVersion, }, Allow: &types.Allow{ @@ -48,8 +48,9 @@ var ( func TestNetworkEndpoints_Offline(t *testing.T) { cfg := &configuration.Configuration{ - Mode: configuration.Offline, - Network: networkIdentifier, + Mode: configuration.Offline, + Network: networkIdentifier, + ZendVersion: "1.0.0", } mockIndexer := &mocks.Indexer{} mockClient := &mocks.Client{} @@ -79,6 +80,7 @@ func TestNetworkEndpoints_Online(t *testing.T) { cfg := &configuration.Configuration{ Mode: configuration.Online, Network: networkIdentifier, + ZendVersion: "1.0.0", GenesisBlockIdentifier: zen.MainnetGenesisBlockIdentifier, } mockIndexer := &mocks.Indexer{} diff --git a/services/router.go b/services/router.go index 93855c8e..4e3ab649 100644 --- a/services/router.go +++ b/services/router.go @@ -18,7 +18,7 @@ import ( "net/http" "github.com/HorizenOfficial/rosetta-zen/configuration" - + rosettaZenServer "github.com/HorizenOfficial/rosetta-zen/server" "github.com/coinbase/rosetta-sdk-go/asserter" "github.com/coinbase/rosetta-sdk-go/server" ) @@ -61,11 +61,15 @@ func NewBlockchainRouter( asserter, ) + loggerAPIService := NewLoggerAPIService() + loggerAPIController := rosettaZenServer.NewLoggerApiController(loggerAPIService, asserter) + return server.NewRouter( networkAPIController, blockAPIController, accountAPIController, constructionAPIController, mempoolAPIController, + loggerAPIController, ) } diff --git a/services/types.go b/services/types.go index 9eeab67f..62ec6d48 100644 --- a/services/types.go +++ b/services/types.go @@ -22,14 +22,15 @@ import ( ) const ( - // NodeVersion is the version of - // zend core we are using. - NodeVersion = "3.2.0" - // HistoricalBalanceLookup indicates // that historical balance lookup is supported. HistoricalBalanceLookup = true + // MempoolCoins indicates that + // including mempool coins in the /account/coins + // response is not supported. + MempoolCoins = false + // inlineFetchLimit is the maximum number // of transactions to fetch inline. inlineFetchLimit = 100 @@ -51,8 +52,9 @@ type Client interface { SendRawTransaction(context.Context, string) (string, error) SuggestedFeeRate(context.Context, int64) (float64, error) RawMempool(context.Context) ([]string, error) - GetBestBlock (context.Context) (int64, error) + GetBestBlock(context.Context) (int64, error) GetHashFromIndex(context.Context, int64) (string, error) + SetZendNodeVersion(ctx context.Context) (string, error) } // Indexer is used by the servicers to get block and account data. @@ -96,10 +98,9 @@ type preprocessOptions struct { } type constructionMetadata struct { - ScriptPubKeys []*zen.ScriptPubKey `json:"script_pub_keys"` - ReplayBlockHeight int64 `json:"replay_block_height"` - ReplayBlockHash string `json:"replay_block_hash"` - + ScriptPubKeys []*zen.ScriptPubKey `json:"script_pub_keys"` + ReplayBlockHeight int64 `json:"replay_block_height"` + ReplayBlockHash string `json:"replay_block_hash"` } type signedTransaction struct { diff --git a/utils/utils.go b/utils/utils.go index 4ad429b1..a14336cc 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -29,6 +29,15 @@ const ( monitorMemorySleep = 50 * time.Millisecond ) +var ( + LoggerConfig = zap.NewDevelopmentConfig() + Atom = LoggerConfig.Level +) + +func NewLogger(options ...zap.Option) (*zap.Logger, error) { + return LoggerConfig.Build(options...) +} + // ExtractLogger returns a sugared logger with the origin // tag added. func ExtractLogger(ctx context.Context, origin string) *zap.SugaredLogger { diff --git a/zen/client.go b/zen/client.go index e189f6fb..bd17e0c8 100644 --- a/zen/client.go +++ b/zen/client.go @@ -20,16 +20,17 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net" "net/http" "strconv" + "strings" "time" + "github.com/HorizenOfficial/rosetta-zen/utils" "github.com/HorizenOfficial/rosetta-zen/zenutil" - "github.com/coinbase/rosetta-sdk-go/storage" "github.com/coinbase/rosetta-sdk-go/types" - "github.com/coinbase/rosetta-sdk-go/utils" + sdkUtils "github.com/coinbase/rosetta-sdk-go/utils" ) const ( @@ -50,6 +51,8 @@ const ( // * 1 returns the JSON representation // * 2 returns the JSON representation with included Transaction data blockVerbosity = 2 + + nodeWaitSleep = 3 * time.Second ) type requestMethod string @@ -64,6 +67,9 @@ const ( // https://bitcoin.org/en/developer-reference#getblockchaininfo requestMethodGetBlockchainInfo requestMethod = "getblockchaininfo" + // https://bitcoin.org/en/developer-reference#getnetworkinfo + requestMethodGetNetworkInfo requestMethod = "getnetworkinfo" + // https://developer.bitcoin.org/reference/rpc/getpeerinfo.html requestMethodGetPeerInfo requestMethod = "getpeerinfo" @@ -159,6 +165,21 @@ func newHTTPClient(timeout time.Duration) *http.Client { return httpClient } +func (b *Client) SetZendNodeVersion(ctx context.Context) (string, error) { + logger := utils.ExtractLogger(ctx, "client") + networkInfo, err := b.NetworkInfo(ctx) + if err != nil { + logger.Warnw("unable to retrieve network info", "error", err) + return "", nil + } + needsSplit := strings.Contains(networkInfo.Subversion, "zen:") + versionArray := strings.Split(strings.Trim(networkInfo.Subversion, "/"), ":") + if needsSplit { + return versionArray[1], nil + } + return versionArray[0], nil +} + // NetworkStatus returns the *types.NetworkStatusResponse for // bitcoind. func (b *Client) NetworkStatus(ctx context.Context) (*types.NetworkStatusResponse, error) { @@ -185,6 +206,24 @@ func (b *Client) NetworkStatus(ctx context.Context) (*types.NetworkStatusRespons }, nil } +// WaitForNode returns once zend is ready to serve +// block queries. +func (b *Client) WaitForNode(ctx context.Context) error { + logger := utils.ExtractLogger(ctx, "client") + for { + _, err := b.NetworkStatus(ctx) + if err == nil { + logger.Infow("status is ok...") + return nil + } + + logger.Infow("waiting for zend...") + if err := sdkUtils.ContextSleep(ctx, nodeWaitSleep); err != nil { + return err + } + } +} + // GetPeers fetches the list of peer nodes func (b *Client) GetPeers(ctx context.Context) ([]*types.Peer, error) { info, err := b.getPeerInfo(ctx) @@ -232,7 +271,6 @@ func (b *Client) GetRawBlock( return block, coins, nil } - func addCoins(txIndex int, blockTxHashes []string, hash string, inputs []*Input, b *Client, coins []string) ([]string, []string) { blockTxHashes = append(blockTxHashes, hash) for inputIndex, input := range inputs { @@ -243,7 +281,7 @@ func addCoins(txIndex int, blockTxHashes []string, hash string, inputs []*Input, // If any transactions spent in the same block they are created, don't include them // in previousTxHashes to fetch. - if !utils.ContainsString(blockTxHashes, txHash) { + if !sdkUtils.ContainsString(blockTxHashes, txHash) { coins = append(coins, CoinIdentifier(txHash, vout)) } } @@ -256,7 +294,7 @@ func addCoins(txIndex int, blockTxHashes []string, hash string, inputs []*Input, func (b *Client) ParseBlock( ctx context.Context, block *Block, - coins map[string]*storage.AccountCoin, + coins map[string]*types.AccountCoin, ) (*types.Block, error) { rblock, err := b.parseBlockData(block) if err != nil { @@ -397,6 +435,22 @@ func (b *Client) getBlockchainInfo( return response.Result, nil } +// NetworkInfo performs the `getnetworkinfo` JSON-RPC request +func (b *Client) NetworkInfo( + ctx context.Context, +) (*NetworkInfo, error) { + if err := b.WaitForNode(ctx); err != nil { + return nil, fmt.Errorf("%w: failed to wait for node", err) + } + params := []interface{}{} + response := &networkInfoResponse{} + if err := b.post(ctx, requestMethodGetNetworkInfo, params, response); err != nil { + return nil, fmt.Errorf("%w: unbale to get network info", err) + } + + return response.Result, nil +} + // GetBestBlock performs the `getbestblock` JSON-RPC request func (b *Client) GetBestBlock( ctx context.Context, @@ -494,18 +548,17 @@ func (b *Client) GetHashFromIndex( return response.Result, nil } - // parseTransactions returns the transactions for a specified `Block` func (b *Client) parseTransactions( ctx context.Context, block *Block, - coins map[string]*storage.AccountCoin, + coins map[string]*types.AccountCoin, ) ([]*types.Transaction, error) { if block == nil { return nil, errors.New("error parsing nil block") } - txs := make([]*types.Transaction, len(block.Txs) + len(block.Certs)) + txs := make([]*types.Transaction, len(block.Txs)+len(block.Certs)) for index, transaction := range block.Txs { txOps, err := b.parseTxOperations(transaction.Inputs, transaction.Outputs, transaction.Hash, index, coins, false) if err != nil { @@ -531,7 +584,7 @@ func (b *Client) parseTransactions( } for index, certificate := range block.Certs { - txIndex := len(block.Txs) + index; + txIndex := len(block.Txs) + index certTxOps, err := b.parseTxOperations(certificate.Inputs, certificate.Outputs, certificate.Hash, txIndex, coins, true) if err != nil { return nil, fmt.Errorf("%w: error parsing certificate transaction operations", err) @@ -554,12 +607,12 @@ func (b *Client) parseTransactions( backwardTransferOutputs := []*Output{} for i := range certificate.Outputs { - if certificate.Outputs[i].BackwardTransfer == true { + if certificate.Outputs[i].BackwardTransfer == true { backwardTransferOutputs = append(backwardTransferOutputs, certificate.Outputs[i]) } } - certTxOps, err := b.parseTxOperations([]*Input{}, backwardTransferOutputs, certificate.Hash, len(block.Txs) + len(block.Certs) + index, coins, false) + certTxOps, err := b.parseTxOperations([]*Input{}, backwardTransferOutputs, certificate.Hash, len(block.Txs)+len(block.Certs)+index, coins, false) if err != nil { return nil, fmt.Errorf("%w: error parsing mature certificate transaction operations", err) } @@ -579,7 +632,7 @@ func (b *Client) parseTransactions( return txs, nil } -func addCoinsFromSameBlock(operations []*types.Operation, coins map[string]*storage.AccountCoin) map[string]*storage.AccountCoin { +func addCoinsFromSameBlock(operations []*types.Operation, coins map[string]*types.AccountCoin) map[string]*types.AccountCoin { // In some cases, a transaction will spent an output // from the same block. for _, op := range operations { @@ -591,7 +644,7 @@ func addCoinsFromSameBlock(operations []*types.Operation, coins map[string]*stor continue } - coins[op.CoinChange.CoinIdentifier.Identifier] = &storage.AccountCoin{ + coins[op.CoinChange.CoinIdentifier.Identifier] = &types.AccountCoin{ Coin: &types.Coin{ CoinIdentifier: op.CoinChange.CoinIdentifier, Amount: op.Amount, @@ -610,7 +663,7 @@ func (b *Client) parseTxOperations( outputs []*Output, hash string, txIndex int, - coins map[string]*storage.AccountCoin, + coins map[string]*types.AccountCoin, isImmatureCertificate bool, ) ([]*types.Operation, error) { txOps := []*types.Operation{} @@ -726,7 +779,7 @@ func (b *Client) parseOutputTransactionOperation( // if it's a coinbase output and we are not in regtest populate SubAccount field if txIndex == 0 && b.genesisBlockIdentifier.Hash != RegtestGenesisBlockIdentifier.Hash { account.SubAccount = &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", } } @@ -742,7 +795,7 @@ func (b *Client) parseOutputTransactionOperation( NetworkIndex: &networkIndex, }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: account, Amount: &types.Amount{ Value: strconv.FormatInt(int64(amount), 10), @@ -781,7 +834,7 @@ func (b *Client) parseInputTransactionOperation( input *Input, index int64, networkIndex int64, - accountCoin *storage.AccountCoin, + accountCoin *types.AccountCoin, ) (*types.Operation, error) { metadata, err := input.Metadata() if err != nil { @@ -799,7 +852,7 @@ func (b *Client) parseInputTransactionOperation( NetworkIndex: &networkIndex, }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: accountCoin.Account, Amount: &types.Amount{ Value: newValue, @@ -861,7 +914,7 @@ func (b *Client) coinbaseTxOperation( NetworkIndex: &networkIndex, }, Type: CoinbaseOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Metadata: metadata, }, nil } @@ -902,7 +955,7 @@ func (b *Client) post( // We expect JSON-RPC responses to return `200 OK` statuses if res.StatusCode != http.StatusOK { - val, _ := ioutil.ReadAll(res.Body) + val, _ := io.ReadAll(res.Body) return fmt.Errorf("invalid response: %s %s", res.Status, string(val)) } diff --git a/zen/client_test.go b/zen/client_test.go index 8a167486..4d721b28 100644 --- a/zen/client_test.go +++ b/zen/client_test.go @@ -24,7 +24,6 @@ import ( "net/http/httptest" "testing" - "github.com/coinbase/rosetta-sdk-go/storage" "github.com/coinbase/rosetta-sdk-go/types" "github.com/stretchr/testify/assert" ) @@ -77,10 +76,10 @@ var ( Value: 7.5001, Index: 0, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint + ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", }, @@ -90,10 +89,10 @@ var ( Value: 2.5, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint - Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint + ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint + Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", }, @@ -103,10 +102,10 @@ var ( Value: 1.25, Index: 2, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint - Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint + ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint + Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", }, @@ -116,10 +115,10 @@ var ( Value: 1.25, Index: 3, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint - Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint + ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint + Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", }, @@ -133,33 +132,33 @@ var ( Size: 595, Version: 1, Locktime: 0, - Inputs: []*Input{ + Inputs: []*Input{ { TxHash: "9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a", - Vout: 0, + Vout: 0, ScriptSig: &ScriptSig{ ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", Hex: "473044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e278700012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", }, - Sequence: 4294967295, + Sequence: 4294967295, }, { TxHash: "14e8fe02ec4e237d8cb6bf95943bd05706a19f6bd29f9b2b1fefc4fa09ef6737", - Vout: 0, + Vout: 0, ScriptSig: &ScriptSig{ ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", Hex: "4730440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", }, - Sequence: 4294967295, + Sequence: 4294967295, }, { TxHash: "4c292f9ba0e94f2d48a16f8765217e62b6673796bffd92c26b13ed5e661946bc", - Vout: 1, + Vout: 1, ScriptSig: &ScriptSig{ ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", Hex: "47304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", }, - Sequence: 4294967295, + Sequence: 4294967295, }, }, // all we care about in this test is the outputs Outputs: []*Output{ @@ -180,10 +179,10 @@ var ( Value: 68.5999, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -228,10 +227,10 @@ var ( Value: 7.5001, Index: 0, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint + ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", }, @@ -241,10 +240,10 @@ var ( Value: 2.5, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint - Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint + ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint + Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", }, @@ -254,10 +253,10 @@ var ( Value: 1.25, Index: 2, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint - Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint + ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint + Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", }, @@ -267,10 +266,10 @@ var ( Value: 1.25, Index: 3, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint - Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint + ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint + Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", }, @@ -284,33 +283,33 @@ var ( Size: 595, Version: 1, Locktime: 0, - Inputs: []*Input{ + Inputs: []*Input{ { TxHash: "9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a", - Vout: 0, + Vout: 0, ScriptSig: &ScriptSig{ ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", Hex: "473044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e278700012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", }, - Sequence: 4294967295, + Sequence: 4294967295, }, { TxHash: "14e8fe02ec4e237d8cb6bf95943bd05706a19f6bd29f9b2b1fefc4fa09ef6737", - Vout: 0, + Vout: 0, ScriptSig: &ScriptSig{ ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", Hex: "4730440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", }, - Sequence: 4294967295, + Sequence: 4294967295, }, { TxHash: "4c292f9ba0e94f2d48a16f8765217e62b6673796bffd92c26b13ed5e661946bc", - Vout: 1, + Vout: 1, ScriptSig: &ScriptSig{ ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", Hex: "47304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", }, - Sequence: 4294967295, + Sequence: 4294967295, }, }, // all we care about in this test is the outputs Outputs: []*Output{ @@ -331,10 +330,10 @@ var ( Value: 68.5999, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -345,17 +344,17 @@ var ( }, Certs: []*Certificate{ { - Hash: "afa747bcb78e22e5550e880d0803a5fa4cdbc7e04ff303a4b14da2c36e348e89", - Version: 1, - Inputs: []*Input{ + Hash: "afa747bcb78e22e5550e880d0803a5fa4cdbc7e04ff303a4b14da2c36e348e89", + Version: 1, + Inputs: []*Input{ { TxHash: "62091923e9805a8650d752b3b83e0d56ce70e775ee67c080feade7e5ee677ad9", - Vout: 0, + Vout: 0, ScriptSig: &ScriptSig{ ASM: "3044022014d8dee1da3821dce95e48060f8f38394aee00f84d03a8203611ff3e703c10a002205ce62cffdc12dd26742489120d50d071ff08f993b9cca0b31a73e0f20f20cb5d01 0241b92fed18a3ded2b98459b5432982a0712912ad86b929ec6feb19655824b7cc", Hex: "473044022014d8dee1da3821dce95e48060f8f38394aee00f84d03a8203611ff3e703c10a002205ce62cffdc12dd26742489120d50d071ff08f993b9cca0b31a73e0f20f20cb5d01210241b92fed18a3ded2b98459b5432982a0712912ad86b929ec6feb19655824b7cc", }, - Sequence: 4294967295, + Sequence: 4294967295, }, }, Cert: &Cert{ @@ -372,7 +371,7 @@ var ( VBitVectorCertificateField: []string{ "021f8b08000000000002ff017f0080ff44c7e21ba1c7c0a29de006cb8074e2ba39f15abfef2525a4cbb3f235734410bda21cdab6624de769ceec818ac6c2d3a01e382e357dce1f6e9a0ff281f0fedae0efe274351db37599af457984dcf8e3ae4479e0561341adfff4746fbe274d90f6f76b8a2552a6ebb98aee918c7ceac058f4c1ae0131249546ef5e22f4187a07da02ca5b7f000000", }, - FtScFee: 10.00000000, + FtScFee: 10.00000000, MbtrScFee: 20.00000000, }, Outputs: []*Output{ @@ -393,10 +392,10 @@ var ( Value: 1.00000000, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 4aeea9b9beec0af6eb8e6e8d6015a8a679590553 OP_EQUALVERIFY OP_CHECKSIG", - Hex: "76a9144aeea9b9beec0af6eb8e6e8d6015a8a67959055388ac", + ASM: "OP_DUP OP_HASH160 4aeea9b9beec0af6eb8e6e8d6015a8a679590553 OP_EQUALVERIFY OP_CHECKSIG", + Hex: "76a9144aeea9b9beec0af6eb8e6e8d6015a8a67959055388ac", RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztZzAfqxzua7EDHUMFq6hpQPhXyC1XPJMUs", }, @@ -442,10 +441,10 @@ var ( Value: 7.50000000, Index: 0, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 1571d181a7f5e891815d42863ae6aae630e59b39 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a9141571d181a7f5e891815d42863ae6aae630e59b3988ac", // nolint + ASM: "OP_DUP OP_HASH160 1571d181a7f5e891815d42863ae6aae630e59b39 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a9141571d181a7f5e891815d42863ae6aae630e59b3988ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztV7MJKfz5kpoAYtbcbMu3PNZfuV7zzENex", }, @@ -455,10 +454,10 @@ var ( Value: 2.50000000, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 ea81ee2d877a25c7530a33fcf5a65c72f681250f OP_EQUAL", // nolint - Hex: "a914ea81ee2d877a25c7530a33fcf5a65c72f681250f87", // nolint + ASM: "OP_HASH160 ea81ee2d877a25c7530a33fcf5a65c72f681250f OP_EQUAL", // nolint + Hex: "a914ea81ee2d877a25c7530a33fcf5a65c72f681250f87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrQWJd1fhtkQtrjbYPXfHFF1c61DUtiXcCD", }, @@ -468,10 +467,10 @@ var ( Value: 1.25000000, Index: 2, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 e7d25d82be231cf77ab8aecb80b6066923819ffc OP_EQUAL", // nolint - Hex: "a914e7d25d82be231cf77ab8aecb80b6066923819ffc87", // nolint + ASM: "OP_HASH160 e7d25d82be231cf77ab8aecb80b6066923819ffc OP_EQUAL", // nolint + Hex: "a914e7d25d82be231cf77ab8aecb80b6066923819ffc87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrQG6x9j33DLbCfzAqu3qKMe7z1VDL1z2L7", }, @@ -481,10 +480,10 @@ var ( Value: 1.25000000, Index: 3, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed OP_EQUAL", // nolint - Hex: "a914ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed87", // nolint + ASM: "OP_HASH160 ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed OP_EQUAL", // nolint + Hex: "a914ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrMasbhB1yyfQ5RBUm7NPcEjGWZdRneWCEx", }, @@ -497,17 +496,17 @@ var ( Certs: []*Certificate{}, MaturedCerts: []*Certificate{ { - Hash: "815c88e2bb7a0b083c74bf9643f94db252704f475290c58f6cb123e8793f5376", - Version: -5, - Inputs: []*Input{ + Hash: "815c88e2bb7a0b083c74bf9643f94db252704f475290c58f6cb123e8793f5376", + Version: -5, + Inputs: []*Input{ { TxHash: "2143020b085a539ce6cc498e644c49fba54fcbca8cfa79a1139a9a1235a86439", - Vout: 0, + Vout: 0, ScriptSig: &ScriptSig{ ASM: "30440220646ef26388da7a1888f8fff42f9f0265496be89f0bf450021f8666a9aa72eef602206809359d1cf03a58f49fa1c76e2829ff80bfe3052d8773d2c0d2ff5a6c646fad01 03dde477d47ffd54677388518f0ab5bf6fb5c261d9394f20c801b247a71df9c9bf", Hex: "4730440220646ef26388da7a1888f8fff42f9f0265496be89f0bf450021f8666a9aa72eef602206809359d1cf03a58f49fa1c76e2829ff80bfe3052d8773d2c0d2ff5a6c646fad012103dde477d47ffd54677388518f0ab5bf6fb5c261d9394f20c801b247a71df9c9bf", }, - Sequence: 4294967295, + Sequence: 4294967295, }, }, Cert: &Cert{ @@ -524,8 +523,8 @@ var ( VBitVectorCertificateField: []string{ "021f8b08000000000002ff017f0080ff44c7e21ba1c7c0a29de006cb8074e2ba39f15abfef2525a4cbb3f235734410bda21cdab6624de769ceec818ac6c2d3a01e382e357dce1f6e9a0ff281f0fedae0efe274351db37599af457984dcf8e3ae4479e0561341adfff4746fbe274d90f6f76b8a2552a6ebb98aee918c7ceac058f4c1ae0131249546ef5e22f4187a07da02ca5b7f000000", }, - FtScFee: 1.00000000, - MbtrScFee: 2.00000000, + FtScFee: 1.00000000, + MbtrScFee: 2.00000000, TotalAmount: 2.00000000, }, Outputs: []*Output{ @@ -546,10 +545,10 @@ var ( Value: 2.00000000, Index: 1, ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 80271800053d996d0ebd51ee357e37bfedafc6a6 OP_EQUALVERIFY OP_CHECKSIG", - Hex: "76a91480271800053d996d0ebd51ee357e37bfedafc6a688ac", + ASM: "OP_DUP OP_HASH160 80271800053d996d0ebd51ee357e37bfedafc6a6 OP_EQUALVERIFY OP_CHECKSIG", + Hex: "76a91480271800053d996d0ebd51ee357e37bfedafc6a688ac", RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "zteqa5taBUZaJFsTJpmD9KVvCSfWjEG7w2S", }, @@ -563,6 +562,108 @@ var ( } ) +func TestGetPeers(t *testing.T) { + tests := map[string]struct { + responses []responseFixture + + expectedPeers []*types.Peer + expectedError error + }{ + "successful": { + responses: []responseFixture{ + { + status: http.StatusOK, + body: loadFixture("get_peer_info_response.json"), + url: url, + }, + }, + expectedPeers: []*types.Peer{ + { + PeerID: "77.93.223.9:8333", + Metadata: forceMarshalMap(t, &PeerInfo{ + Addr: "77.93.223.9:8333", + Version: 70015, + SubVer: "/Satoshi:0.14.2/", + StartingHeight: 643579, + RelayTxes: true, + LastSend: 1597606676, + LastRecv: 1597606677, + BanScore: 0, + SyncedHeaders: 644046, + SyncedBlocks: 644046, + }), + }, + { + PeerID: "172.105.93.179:8333", + Metadata: forceMarshalMap(t, &PeerInfo{ + Addr: "172.105.93.179:8333", + RelayTxes: true, + LastSend: 1597606678, + LastRecv: 1597606676, + Version: 70015, + SubVer: "/Satoshi:0.18.1/", + StartingHeight: 643579, + BanScore: 0, + SyncedHeaders: 644046, + SyncedBlocks: 644046, + }), + }, + }, + }, + "blockchain warming up error": { + responses: []responseFixture{ + { + status: http.StatusOK, + body: loadFixture("rpc_in_warmup_response.json"), + url: url, + }, + }, + expectedError: errors.New("rpc in warmup"), + }, + "peer info error": { + responses: []responseFixture{ + { + status: http.StatusInternalServerError, + body: "{}", + url: url, + }, + }, + expectedError: errors.New("invalid response: 500 Internal Server Error"), + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var ( + assert = assert.New(t) + ) + + responses := make(chan responseFixture, len(test.responses)) + for _, response := range test.responses { + responses <- response + } + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + response := <-responses + assert.Equal("application/json", r.Header.Get("Content-Type")) + assert.Equal("POST", r.Method) + assert.Equal(response.url, r.URL.RequestURI()) + + w.WriteHeader(response.status) + fmt.Fprintln(w, response.body) + })) + + client := NewClient(ts.URL, MainnetGenesisBlockIdentifier, MainnetCurrency) + peers, err := client.GetPeers(context.Background()) + if test.expectedError != nil { + assert.Contains(err.Error(), test.expectedError.Error()) + } else { + assert.NoError(err) + assert.Equal(test.expectedPeers, peers) + } + }) + } +} func TestNetworkStatus(t *testing.T) { tests := map[string]struct { @@ -737,7 +838,7 @@ func TestGetRawBlock(t *testing.T) { }, }, expectedBlock: block717984, - expectedCoins: []string{"9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0", "14e8fe02ec4e237d8cb6bf95943bd05706a19f6bd29f9b2b1fefc4fa09ef6737:0", "4c292f9ba0e94f2d48a16f8765217e62b6673796bffd92c26b13ed5e661946bc:1","62091923e9805a8650d752b3b83e0d56ce70e775ee67c080feade7e5ee677ad9:0"}, + expectedCoins: []string{"9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0", "14e8fe02ec4e237d8cb6bf95943bd05706a19f6bd29f9b2b1fefc4fa09ef6737:0", "4c292f9ba0e94f2d48a16f8765217e62b6673796bffd92c26b13ed5e661946bc:1", "62091923e9805a8650d752b3b83e0d56ce70e775ee67c080feade7e5ee677ad9:0"}, }, "lookup by hash - block with mature certificate": { blockIdentifier: &types.PartialBlockIdentifier{ @@ -826,7 +927,7 @@ func TestGetRawBlock(t *testing.T) { }, }, expectedBlock: block717983, - expectedCoins:[]string{"9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0", "14e8fe02ec4e237d8cb6bf95943bd05706a19f6bd29f9b2b1fefc4fa09ef6737:0", "4c292f9ba0e94f2d48a16f8765217e62b6673796bffd92c26b13ed5e661946bc:1"}, + expectedCoins: []string{"9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0", "14e8fe02ec4e237d8cb6bf95943bd05706a19f6bd29f9b2b1fefc4fa09ef6737:0", "4c292f9ba0e94f2d48a16f8765217e62b6673796bffd92c26b13ed5e661946bc:1"}, }, "current block lookup (can't get current info)": { responses: []responseFixture{ @@ -886,14 +987,14 @@ func mustMarshalMap(v interface{}) map[string]interface{} { func TestParseBlockRegtest(t *testing.T) { tests := map[string]struct { block *Block - coins map[string]*storage.AccountCoin + coins map[string]*types.AccountCoin expectedBlock *types.Block expectedError error }{ "block717983": { block: block717983, - coins: map[string]*storage.AccountCoin{ + coins: map[string]*types.AccountCoin{ "9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0": { Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", @@ -956,7 +1057,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: CoinbaseOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Metadata: mustMarshalMap(&OperationMetadata{ Coinbase: "039ff40a0102", Sequence: 4294967295, @@ -968,7 +1069,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", // nolint }, @@ -984,10 +1085,10 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint + ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", }, @@ -1000,7 +1101,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", // nolint }, @@ -1016,10 +1117,10 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint - Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint + ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint + Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", }, @@ -1032,7 +1133,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", // nolint }, @@ -1048,10 +1149,10 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint - Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint + ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint + Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", }, @@ -1064,7 +1165,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(3), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", // nolint }, @@ -1080,10 +1181,10 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint - Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint + ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint + Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", }, @@ -1107,7 +1208,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-60000000", Currency: MainnetCurrency, @@ -1123,7 +1224,7 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "473044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e278700012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1135,7 +1236,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-200000000", Currency: MainnetCurrency, @@ -1151,7 +1252,7 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "4730440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1163,7 +1264,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-7100000000", Currency: MainnetCurrency, @@ -1179,7 +1280,7 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "47304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1191,7 +1292,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztjySYJL8g9i6wc2YTusbDpPZSpPM5xuTua", }, @@ -1207,10 +1308,10 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 b87cc09d17751ffeab924a82134665ae4202cbfc OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914b87cc09d17751ffeab924a82134665ae4202cbfc88ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 b87cc09d17751ffeab924a82134665ae4202cbfc OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914b87cc09d17751ffeab924a82134665ae4202cbfc88ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztjySYJL8g9i6wc2YTusbDpPZSpPM5xuTua", }, @@ -1223,7 +1324,7 @@ func TestParseBlockRegtest(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -1239,10 +1340,10 @@ func TestParseBlockRegtest(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -1289,14 +1390,14 @@ func TestParseBlockRegtest(t *testing.T) { func TestParseBlock(t *testing.T) { tests := map[string]struct { block *Block - coins map[string]*storage.AccountCoin + coins map[string]*types.AccountCoin expectedBlock *types.Block expectedError error }{ "block717983": { block: block717983, - coins: map[string]*storage.AccountCoin{ + coins: map[string]*types.AccountCoin{ "9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0": { Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", @@ -1359,7 +1460,7 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: CoinbaseOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Metadata: mustMarshalMap(&OperationMetadata{ Coinbase: "039ff40a0102", Sequence: 4294967295, @@ -1371,11 +1472,11 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1390,10 +1491,10 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint + ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", }, @@ -1406,11 +1507,11 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1425,10 +1526,10 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint - Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint + ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint + Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", }, @@ -1441,11 +1542,11 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1460,10 +1561,10 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint - Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint + ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint + Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", }, @@ -1476,11 +1577,11 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(3), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1495,10 +1596,10 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint - Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint + ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint + Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", }, @@ -1522,7 +1623,7 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-60000000", Currency: MainnetCurrency, @@ -1538,7 +1639,7 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "473044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e278700012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1550,7 +1651,7 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-200000000", Currency: MainnetCurrency, @@ -1566,7 +1667,7 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "4730440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1578,7 +1679,7 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-7100000000", Currency: MainnetCurrency, @@ -1594,7 +1695,7 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "47304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1606,7 +1707,7 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztjySYJL8g9i6wc2YTusbDpPZSpPM5xuTua", }, @@ -1622,10 +1723,10 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 b87cc09d17751ffeab924a82134665ae4202cbfc OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914b87cc09d17751ffeab924a82134665ae4202cbfc88ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 b87cc09d17751ffeab924a82134665ae4202cbfc OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914b87cc09d17751ffeab924a82134665ae4202cbfc88ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztjySYJL8g9i6wc2YTusbDpPZSpPM5xuTua", }, @@ -1638,7 +1739,7 @@ func TestParseBlock(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -1654,10 +1755,10 @@ func TestParseBlock(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -1723,14 +1824,14 @@ func TestParseBlock(t *testing.T) { func TestParseBlockWithCertificate(t *testing.T) { tests := map[string]struct { block *Block - coins map[string]*storage.AccountCoin + coins map[string]*types.AccountCoin expectedBlock *types.Block expectedError error }{ "block717984": { block: block717984, - coins: map[string]*storage.AccountCoin{ + coins: map[string]*types.AccountCoin{ "9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0": { Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", @@ -1807,7 +1908,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: CoinbaseOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Metadata: mustMarshalMap(&OperationMetadata{ Coinbase: "039ff40a0102", Sequence: 4294967295, @@ -1819,11 +1920,11 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1838,10 +1939,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint + ASM: "OP_DUP OP_HASH160 557662a6b307f95aa00311c074f7feebb955d451 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a914557662a6b307f95aa00311c074f7feebb955d45188ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztawr1vEZ6pZRtLqNy2C9u7EK7JN2gP8W6z", }, @@ -1854,11 +1955,11 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1873,10 +1974,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint - Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint + ASM: "OP_HASH160 8d3468b6686ac59caf9ad94e547a737b09fa1027 OP_EQUAL", // nolint + Hex: "a9148d3468b6686ac59caf9ad94e547a737b09fa102787", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFzxutppvxEdjyu4QNjogBMjtC1py9Hp1S", }, @@ -1889,11 +1990,11 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1908,10 +2009,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint - Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint + ASM: "OP_HASH160 fc1d7f04db5e2c05b051e0decc85effe6bc539d5 OP_EQUAL", // nolint + Hex: "a914fc1d7f04db5e2c05b051e0decc85effe6bc539d587", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrS7QUB2eDbbKvyP43VJys3t7RpojW8GdxH", }, @@ -1924,11 +2025,11 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(3), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -1943,10 +2044,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint - Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint + ASM: "OP_HASH160 8b85fc1e171a4c7994c088b91d5a75dff9e56cad OP_EQUAL", // nolint + Hex: "a9148b85fc1e171a4c7994c088b91d5a75dff9e56cad87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrFr5HVm7woVq3oFzkMEdJdbfBchfPAPDsP", }, @@ -1970,7 +2071,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-60000000", Currency: MainnetCurrency, @@ -1986,7 +2087,7 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "3044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e27870001 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "473044022059135f673a4919ab56775064cc82080ead1c74d8f0ebd943062b247c5946cf88022048f26c94a15752fa04d8bfff7388dd65d57485acd2395e539a50b2ca8e278700012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -1998,7 +2099,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-200000000", Currency: MainnetCurrency, @@ -2014,7 +2115,7 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "30440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "4730440220527c59b1d2dbb87b71e01c9d1489f110727fc3120e5306539bd4668ed1063d30022079b6ca4ff77de3ab953bb0d896b74bb60c8ceca28248340201e701da0d1fd12b012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -2026,7 +2127,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Amount: &types.Amount{ Value: "-7100000000", Currency: MainnetCurrency, @@ -2042,7 +2143,7 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptSig: &ScriptSig{ - ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint + ASM: "304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb01 03ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint Hex: "47304402202d3b75ed231c1fe478c471452a0385c5cdc9fe2e337d5ee62cacd8a26d013e5002207d864a38e013d8c61b1972bd7bf78a53accd9b8d600fbbd7c79c21b2171fd8cb012103ae26fe63b19c80972b6ffbd47e9f3b3e202740e5e349b0e23fd712927b0792ce", // nolint }, Sequence: 4294967295, @@ -2054,7 +2155,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztjySYJL8g9i6wc2YTusbDpPZSpPM5xuTua", }, @@ -2070,10 +2171,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 b87cc09d17751ffeab924a82134665ae4202cbfc OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914b87cc09d17751ffeab924a82134665ae4202cbfc88ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 b87cc09d17751ffeab924a82134665ae4202cbfc OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914b87cc09d17751ffeab924a82134665ae4202cbfc88ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztjySYJL8g9i6wc2YTusbDpPZSpPM5xuTua", }, @@ -2086,7 +2187,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -2102,10 +2203,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", + ASM: "OP_DUP OP_HASH160 fd2831ec8fc1bf3ccdeadbe9fcdb515aac904761 OP_EQUALVERIFY OP_CHECKSIG bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a00 717682 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914fd2831ec8fc1bf3ccdeadbe9fcdb515aac90476188ac20bd1d792d97a7da359adbc2fdadd04536f79aad9afc5821c4340043f7fb302a000372f30ab4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", }, @@ -2129,7 +2230,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: InputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztpha3vQzv7eTdBvPC1oWnouuManmCEVbTT", }, @@ -2157,7 +2258,7 @@ func TestParseBlockWithCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztpha3vQzv7eTdBvPC1oWnouuManmCEVbTT", }, @@ -2173,10 +2274,10 @@ func TestParseBlockWithCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 ec54fedd6a312d5c536046323bfabb9d2a475d7a OP_EQUALVERIFY OP_CHECKSIG 4ca064b46515f3f00e846e6c1b45ef36a082ea786783096d2cb6169556756e08 21 OP_CHECKBLOCKATHEIGHT", - Hex: "76a914ec54fedd6a312d5c536046323bfabb9d2a475d7a88ac204ca064b46515f3f00e846e6c1b45ef36a082ea786783096d2cb6169556756e080115b4", + ASM: "OP_DUP OP_HASH160 ec54fedd6a312d5c536046323bfabb9d2a475d7a OP_EQUALVERIFY OP_CHECKSIG 4ca064b46515f3f00e846e6c1b45ef36a082ea786783096d2cb6169556756e08 21 OP_CHECKBLOCKATHEIGHT", + Hex: "76a914ec54fedd6a312d5c536046323bfabb9d2a475d7a88ac204ca064b46515f3f00e846e6c1b45ef36a082ea786783096d2cb6169556756e080115b4", RequiredSigs: 1, - Type: "pubkeyhashreplay", + Type: "pubkeyhashreplay", Addresses: []string{ "ztpha3vQzv7eTdBvPC1oWnouuManmCEVbTT", }, @@ -2238,14 +2339,14 @@ func TestParseBlockWithCertificate(t *testing.T) { func TestParseBlockWithMatureCertificate(t *testing.T) { tests := map[string]struct { block *Block - coins map[string]*storage.AccountCoin + coins map[string]*types.AccountCoin expectedBlock *types.Block expectedError error }{ "block717985": { block: block717985, - coins: map[string]*storage.AccountCoin{ + coins: map[string]*types.AccountCoin{ "9401f535c210f3ff362d3f51dba88ecddf4f87ed9d0563c1f9e8af75eca1fd1a:0": { Account: &types.AccountIdentifier{ Address: "ztrEXsPLywPcxE3Sn9qdWV6tYkBH4HnYwin", @@ -2322,7 +2423,7 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: CoinbaseOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Metadata: mustMarshalMap(&OperationMetadata{ Coinbase: "0280020101", Sequence: 4294967295, @@ -2334,11 +2435,11 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { NetworkIndex: int64Pointer(0), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "ztV7MJKfz5kpoAYtbcbMu3PNZfuV7zzENex", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -2353,10 +2454,10 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 1571d181a7f5e891815d42863ae6aae630e59b39 OP_EQUALVERIFY OP_CHECKSIG", // nolint - Hex: "76a9141571d181a7f5e891815d42863ae6aae630e59b3988ac", // nolint + ASM: "OP_DUP OP_HASH160 1571d181a7f5e891815d42863ae6aae630e59b39 OP_EQUALVERIFY OP_CHECKSIG", // nolint + Hex: "76a9141571d181a7f5e891815d42863ae6aae630e59b3988ac", // nolint RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "ztV7MJKfz5kpoAYtbcbMu3PNZfuV7zzENex", }, @@ -2369,11 +2470,11 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrQWJd1fhtkQtrjbYPXfHFF1c61DUtiXcCD", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -2388,10 +2489,10 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 ea81ee2d877a25c7530a33fcf5a65c72f681250f OP_EQUAL", // nolint - Hex: "a914ea81ee2d877a25c7530a33fcf5a65c72f681250f87", // nolint + ASM: "OP_HASH160 ea81ee2d877a25c7530a33fcf5a65c72f681250f OP_EQUAL", // nolint + Hex: "a914ea81ee2d877a25c7530a33fcf5a65c72f681250f87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrQWJd1fhtkQtrjbYPXfHFF1c61DUtiXcCD", }, @@ -2404,11 +2505,11 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { NetworkIndex: int64Pointer(2), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrQG6x9j33DLbCfzAqu3qKMe7z1VDL1z2L7", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -2423,10 +2524,10 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 e7d25d82be231cf77ab8aecb80b6066923819ffc OP_EQUAL", // nolint - Hex: "a914e7d25d82be231cf77ab8aecb80b6066923819ffc87", // nolint + ASM: "OP_HASH160 e7d25d82be231cf77ab8aecb80b6066923819ffc OP_EQUAL", // nolint + Hex: "a914e7d25d82be231cf77ab8aecb80b6066923819ffc87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrQG6x9j33DLbCfzAqu3qKMe7z1VDL1z2L7", }, @@ -2439,11 +2540,11 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { NetworkIndex: int64Pointer(3), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zrMasbhB1yyfQ5RBUm7NPcEjGWZdRneWCEx", // nolint SubAccount: &types.SubAccountIdentifier{ - Address: "coinbase", + Address: "coinbase", }, }, Amount: &types.Amount{ @@ -2458,10 +2559,10 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_HASH160 ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed OP_EQUAL", // nolint - Hex: "a914ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed87", // nolint + ASM: "OP_HASH160 ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed OP_EQUAL", // nolint + Hex: "a914ca76beb25c5f1c29c305a2b3e71a2de5fe1d2eed87", // nolint RequiredSigs: 1, - Type: "scripthash", + Type: "scripthash", Addresses: []string{ "zrMasbhB1yyfQ5RBUm7NPcEjGWZdRneWCEx", }, @@ -2485,7 +2586,7 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { NetworkIndex: int64Pointer(1), }, Type: OutputOpType, - Status: SuccessStatus, + Status: types.String(SuccessStatus), Account: &types.AccountIdentifier{ Address: "zteqa5taBUZaJFsTJpmD9KVvCSfWjEG7w2S", }, @@ -2501,10 +2602,10 @@ func TestParseBlockWithMatureCertificate(t *testing.T) { }, Metadata: mustMarshalMap(&OperationMetadata{ ScriptPubKey: &ScriptPubKey{ - ASM: "OP_DUP OP_HASH160 80271800053d996d0ebd51ee357e37bfedafc6a6 OP_EQUALVERIFY OP_CHECKSIG", - Hex: "76a91480271800053d996d0ebd51ee357e37bfedafc6a688ac", + ASM: "OP_DUP OP_HASH160 80271800053d996d0ebd51ee357e37bfedafc6a6 OP_EQUALVERIFY OP_CHECKSIG", + Hex: "76a91480271800053d996d0ebd51ee357e37bfedafc6a688ac", RequiredSigs: 1, - Type: "pubkeyhash", + Type: "pubkeyhash", Addresses: []string{ "zteqa5taBUZaJFsTJpmD9KVvCSfWjEG7w2S", }, @@ -2681,7 +2782,6 @@ func TestRawMempool(t *testing.T) { } } - // loadFixture takes a file name and returns the response fixture. func loadFixture(fileName string) string { content, err := ioutil.ReadFile(fmt.Sprintf("client_fixtures/%s", fileName)) diff --git a/zen/node.go b/zen/node.go index 2d7e9281..e975b2da 100644 --- a/zen/node.go +++ b/zen/node.go @@ -43,7 +43,7 @@ func logPipe(ctx context.Context, pipe io.ReadCloser, identifier string) error { return err } - message := strings.Replace(str, "\n", "", -1) + message := strings.ReplaceAll(str, "\n", "") messages := strings.SplitAfterN(message, " ", 2) // Trim the timestamp from the log if it exists diff --git a/zen/types.go b/zen/types.go index 64e17e6d..73d6c822 100644 --- a/zen/types.go +++ b/zen/types.go @@ -184,6 +184,40 @@ type PeerInfo struct { SyncedHeaders int64 `json:"synced_headers"` } +type Info struct { + Version int `json:"version"` + Protocolversion int `json:"protocolversion"` + Blocks int `json:"blocks"` + Timeoffset int `json:"timeoffset"` + Connections int `json:"connections"` + Proxy string `json:"proxy"` + Difficulty float64 `json:"difficulty"` + Testnet bool `json:"testnet"` + Paytxfee float64 `json:"paytxfee"` + Relayfee float64 `json:"relayfee"` + Errors string `json:"errors"` +} + +type NetworkInfo struct { + Version int `json:"version"` + Subversion string `json:"subversion"` + Protocolversion int `json:"protocolversion"` + Localservices string `json:"localservices"` + Timeoffset int `json:"timeoffset"` + Connections int `json:"connections"` + TlsCertVerified bool `json:"tls_cert_verified"` + Networks []struct { + Name string `json:"name"` + Limited bool `json:"limited"` + Reachable bool `json:"reachable"` + Proxy string `json:"proxy"` + ProxyRandomizeCredentials bool `json:"proxy_randomize_credentials"` + } `json:"networks"` + Relayfee float64 `json:"relayfee"` + Localaddresses []interface{} `json:"localaddresses"` + Warnings string `json:"warnings"` +} + // Block is a raw Horizen block (with verbosity == 2). type Block struct { Hash string `json:"hash"` @@ -197,8 +231,8 @@ type Block struct { Bits string `json:"bits"` Difficulty float64 `json:"difficulty"` - Txs []*Transaction `json:"tx"` - Certs []*Certificate `json:"cert"` + Txs []*Transaction `json:"tx"` + Certs []*Certificate `json:"cert"` MaturedCerts []*Certificate `json:"matureCertificate"` } @@ -245,22 +279,22 @@ type Certificate struct { Hash string `json:"txid"` Version int32 `json:"version"` Inputs []*Input `json:"vin"` - Cert *Cert `json:"cert"` + Cert *Cert `json:"cert"` Outputs []*Output `json:"vout"` Joinsplits []*Joinsplit `json:"vjoinsplit"` } type Cert struct { - Scid string `json:"scid"` - EpochNumber int64 `json:"epochNumber"` - Quality int64 `json:"quality"` - EndEpochCumScTxCommTreeRoot string `json:"endEpochCumScTxCommTreeRoot"` - ScProof string `json:"scProof"` - VFieldElementCertificateField []string `json:"vFieldElementCertificateField"` - VBitVectorCertificateField []string `json:"vBitVectorCertificateField"` - FtScFee float64 `json:"ftScFee"` - MbtrScFee float64 `json:"mbtrScFee"` - TotalAmount float64 `json:"totalAmount"` + Scid string `json:"scid"` + EpochNumber int64 `json:"epochNumber"` + Quality int64 `json:"quality"` + EndEpochCumScTxCommTreeRoot string `json:"endEpochCumScTxCommTreeRoot"` + ScProof string `json:"scProof"` + VFieldElementCertificateField []string `json:"vFieldElementCertificateField"` + VBitVectorCertificateField []string `json:"vBitVectorCertificateField"` + FtScFee float64 `json:"ftScFee"` + MbtrScFee float64 `json:"mbtrScFee"` + TotalAmount float64 `json:"totalAmount"` } // Joinsplit is a raw Joinsplit transaction representation. @@ -435,6 +469,24 @@ func (b blockchainInfoResponse) Err() error { ) } +type networkInfoResponse struct { + Result *NetworkInfo `json:"result"` + Error *responseError `json:"error"` +} + +func (b networkInfoResponse) Err() error { + if b.Error == nil { + return nil + } + + return fmt.Errorf( + "%w: error JSON RPC response, code: %d, message: %s", + ErrJSONRPCError, + b.Error.Code, + b.Error.Message, + ) +} + type peerInfoResponse struct { Result []*PeerInfo `json:"result"` Error *responseError `json:"error"`