conflicts

This commit is contained in:
Federico Kunze 2021-04-17 12:00:07 +02:00
parent 20f9a72908
commit 5a3d514ba0
No known key found for this signature in database
GPG Key ID: 655F93A970080A30
173 changed files with 19393 additions and 13627 deletions

View File

@ -113,4 +113,3 @@ Standard: Cpp11
TabWidth: 8 TabWidth: 8
UseTab: Never UseTab: Never
... ...

View File

@ -14,29 +14,29 @@ jobs:
- uses: rokroskar/workflow-run-cleanup-action@master - uses: rokroskar/workflow-run-cleanup-action@master
env: env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/development'" # if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/development'"
install-runsim: # install-runsim:
runs-on: ubuntu-latest # runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'skip-sims')" # if: "!contains(github.event.head_commit.message, 'skip-sims')"
steps: # steps:
- name: install runsim # - name: install runsim
run: | # run: |
export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0 # export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0
- uses: actions/cache@v2.1.3 # - uses: actions/cache@v2.1.3
with: # with:
path: ~/go/bin # path: ~/go/bin
key: ${{ runner.os }}-go-runsim-binary # key: ${{ runner.os }}-go-runsim-binary
test-sim-multi-seed-long: # test-sim-multi-seed-long:
runs-on: ubuntu-latest # runs-on: ubuntu-latest
needs: install-runsim # needs: install-runsim
steps: # steps:
- uses: actions/checkout@v2 # - uses: actions/checkout@v2
- uses: actions/cache@v2.1.3 # - uses: actions/cache@v2.1.3
with: # with:
path: ~/go/bin # path: ~/go/bin
key: ${{ runner.os }}-go-runsim-binary # key: ${{ runner.os }}-go-runsim-binary
- name: test-sim-multi-seed-long # - name: test-sim-multi-seed-long
run: | # run: |
make test-sim-multi-seed-long # make test-sim-multi-seed-long

View File

@ -12,6 +12,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4 - uses: technote-space/get-diff-action@v4
id: git_diff id: git_diff
with: with:
@ -56,6 +59,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4 - uses: technote-space/get-diff-action@v4
id: git_diff id: git_diff
with: with:
@ -92,6 +98,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4 - uses: technote-space/get-diff-action@v4
id: git_diff id: git_diff
with: with:
@ -128,6 +137,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4 - uses: technote-space/get-diff-action@v4
id: git_diff id: git_diff
with: with:
@ -164,6 +176,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4 - uses: technote-space/get-diff-action@v4
id: git_diff id: git_diff
with: with:
@ -199,6 +214,9 @@ jobs:
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4 - uses: technote-space/get-diff-action@v4
id: git_diff id: git_diff
with: with:

1
.gitignore vendored
View File

@ -37,6 +37,7 @@ coverage.txt
*.out *.out
sim_log_file sim_log_file
importer/tmp importer/tmp
yarn.lock
# Vagrant # Vagrant
.vagrant/ .vagrant/

View File

@ -71,6 +71,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features ### Features
* (api) [\#821](https://github.com/cosmos/ethermint/pull/821) Individually enable the api modules. Will be implemented in the latest version of ethermint with the upcoming stargate upgrade. * (api) [\#821](https://github.com/cosmos/ethermint/pull/821) Individually enable the api modules. Will be implemented in the latest version of ethermint with the upcoming stargate upgrade.
### Features
* (api) [\#825](https://github.com/cosmos/ethermint/pull/825) Individually enable the api modules. Will be implemented in the latest version of ethermint with the upcoming stargate upgrade.
## [v0.4.0] - 2020-12-15 ## [v0.4.0] - 2020-12-15
### API Breaking ### API Breaking
@ -227,6 +230,11 @@ corresponding Ethereum API namespace:
### Bug Fixes ### Bug Fixes
* (evm) [\#767](https://github.com/cosmos/ethermint/issues/767) Fix error of timeout when using Truffle to deploy contract.
* (evm) [\#751](https://github.com/cosmos/ethermint/issues/751) Fix misused method to calculate block hash in evm related function.
* (evm) [\#721](https://github.com/cosmos/ethermint/issues/721) Fix mismatch block hash in rpc response when use eth.getBlock.
* (evm) [\#730](https://github.com/cosmos/ethermint/issues/730) Fix 'EIP2028' not open when Istanbul version has been enabled.
* (app) [\#749](https://github.com/cosmos/ethermint/issues/749) Fix panic in `AnteHandler` when gas price larger than 100000
* (rpc) [\#305](https://github.com/cosmos/ethermint/issues/305) Update `eth_getTransactionCount` to check for account existence before getting sequence and return 0 as the nonce if it doesn't exist. * (rpc) [\#305](https://github.com/cosmos/ethermint/issues/305) Update `eth_getTransactionCount` to check for account existence before getting sequence and return 0 as the nonce if it doesn't exist.
* (`x/evm`) [\#319](https://github.com/cosmos/ethermint/pull/319) Fix `SetBlockHash` that was setting the incorrect height during `BeginBlock`. * (`x/evm`) [\#319](https://github.com/cosmos/ethermint/pull/319) Fix `SetBlockHash` that was setting the incorrect height during `BeginBlock`.
* (`x/evm`) [\#176](https://github.com/cosmos/ethermint/issues/176) Updated Web3 transaction hash from using RLP hash. Now all transaction hashes exposed are amino hashes: * (`x/evm`) [\#176](https://github.com/cosmos/ethermint/issues/176) Updated Web3 transaction hash from using RLP hash. Now all transaction hashes exposed are amino hashes:

View File

@ -25,7 +25,6 @@ WORKDIR /root
# Copy over binaries from the build-env # Copy over binaries from the build-env
COPY --from=build-env /go/src/github.com/cosmos/ethermint/build/ethermintd /usr/bin/ethermintd COPY --from=build-env /go/src/github.com/cosmos/ethermint/build/ethermintd /usr/bin/ethermintd
COPY --from=build-env /go/src/github.com/cosmos/ethermint/build/ethermintcli /usr/bin/ethermintcli
# Run ethermintd by default # Run ethermintd by default
CMD ["ethermintd"] CMD ["ethermintd"]

76
Makefile Normal file → Executable file
View File

@ -19,8 +19,9 @@ COMMIT := $(shell git log -1 --format='%H')
PACKAGES=$(shell go list ./... | grep -Ev 'vendor|importer|rpc/tester') PACKAGES=$(shell go list ./... | grep -Ev 'vendor|importer|rpc/tester')
DOCKER_TAG = unstable DOCKER_TAG = unstable
DOCKER_IMAGE = cosmos/ethermint DOCKER_IMAGE = cosmos/ethermint
ETHERMINT_DAEMON_BINARY = ethermintd DOCKER_BUF := docker run -v $(shell pwd):/workspace --workdir /workspace bufbuild/buf
ETHERMINT_CLI_BINARY = ethermintcli ETHERMINT_BINARY = ethermintd
ETHERMINT_DIR = ethermint
GO_MOD=GO111MODULE=on GO_MOD=GO111MODULE=on
BUILDDIR ?= $(CURDIR)/build BUILDDIR ?= $(CURDIR)/build
SIMAPP = ./app SIMAPP = ./app
@ -34,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DETECTED_OS := windows DETECTED_OS := windows
else else
UNAME_S = $(shell uname -s) UNAME_S = $(shell uname -s)
ifeq ($(UNAME_S),Darwin) ifeq ($(UNAME_S),Darwin)
DETECTED_OS := mac DETECTED_OS := mac
else else
DETECTED_OS := linux DETECTED_OS := linux
@ -106,8 +107,7 @@ build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags))
# process linker flags # process linker flags
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=ethermint \ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=ethermint \
-X github.com/cosmos/cosmos-sdk/version.ServerName=$(ETHERMINT_DAEMON_BINARY) \ -X github.com/cosmos/cosmos-sdk/version.AppName=$(ETHERMINT_BINARY) \
-X github.com/cosmos/cosmos-sdk/version.ClientName=$(ETHERMINT_CLI_BINARY) \
-X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \
-X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \ -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \
-X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)"
@ -129,17 +129,14 @@ all: tools verify install
build: go.sum build: go.sum
ifeq ($(OS), Windows_NT) ifeq ($(OS), Windows_NT)
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_DAEMON_BINARY).exe ./cmd/$(ETHERMINT_DAEMON_BINARY) go build $(BUILD_FLAGS) -o build/$(ETHERMINT_BINARY).exe ./cmd/$(ETHERMINT_BINARY)
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_CLI_BINARY).exe ./cmd/$(ETHERMINT_CLI_BINARY)
else else
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_DAEMON_BINARY) ./cmd/$(ETHERMINT_DAEMON_BINARY) go build $(BUILD_FLAGS) -o build/$(ETHERMINT_BINARY) ./cmd/$(ETHERMINT_BINARY)
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_CLI_BINARY) ./cmd/$(ETHERMINT_CLI_BINARY)
endif endif
build-ethermint: go.sum build-ethermint: go.sum
mkdir -p $(BUILDDIR) mkdir -p $(BUILDDIR)
go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR) ./cmd/$(ETHERMINT_DAEMON_BINARY) go build $(BUILD_FLAGS) -o $(BUILDDIR) ./cmd/$(ETHERMINT_BINARY)
go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR) ./cmd/$(ETHERMINT_CLI_BINARY)
build-ethermint-linux: go.sum build-ethermint-linux: go.sum
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 $(MAKE) build-ethermint GOOS=linux GOARCH=amd64 CGO_ENABLED=1 $(MAKE) build-ethermint
@ -147,8 +144,7 @@ build-ethermint-linux: go.sum
.PHONY: build build-ethermint build-ethermint-linux .PHONY: build build-ethermint build-ethermint-linux
install: install:
${GO_MOD} go install $(BUILD_FLAGS) ./cmd/$(ETHERMINT_DAEMON_BINARY) ${GO_MOD} go install $(BUILD_FLAGS) ./cmd/$(ETHERMINT_BINARY)
${GO_MOD} go install $(BUILD_FLAGS) ./cmd/$(ETHERMINT_CLI_BINARY)
clean: clean:
@rm -rf ./build ./vendor @rm -rf ./build ./vendor
@ -165,8 +161,7 @@ docker-build:
docker create --name ethermint -t -i cosmos/ethermint:latest ethermint docker create --name ethermint -t -i cosmos/ethermint:latest ethermint
# move the binaries to the ./build directory # move the binaries to the ./build directory
mkdir -p ./build/ mkdir -p ./build/
docker cp ethermint:/usr/bin/ethermintd ./build/ ; \ docker cp ethermint:/usr/bin/ethermintd ./build/
docker cp ethermint:/usr/bin/ethermintcli ./build/
docker-localnet: docker-localnet:
docker build -f ./networks/local/ethermintnode/Dockerfile . -t ethermintd/node docker build -f ./networks/local/ethermintnode/Dockerfile . -t ethermintd/node
@ -186,40 +181,47 @@ RUNSIM = $(TOOLS_DESTDIR)/runsim
runsim: $(RUNSIM) runsim: $(RUNSIM)
$(RUNSIM): $(RUNSIM):
@echo "Installing runsim..." @echo "Installing runsim..."
@(cd /tmp && ${GO_MOD} go get github.com/cosmos/tools/cmd/runsim@v1.0.0) @(cd /tmp && ${GO_MOD} go get github.com/cosmos/tools/cmd/runsim@master)
contract-tools: contract-tools:
ifeq (, $(shell which stringer)) ifeq (, $(shell which stringer))
@echo "Installing stringer..." @echo "Installing stringer..."
@go install golang.org/x/tools/cmd/stringer @go get golang.org/x/tools/cmd/stringer
else else
@echo "stringer already installed; skipping..." @echo "stringer already installed; skipping..."
endif endif
ifeq (, $(shell which go-bindata)) ifeq (, $(shell which go-bindata))
@echo "Installing go-bindata..." @echo "Installing go-bindata..."
@go install github.com/kevinburke/go-bindata/go-bindata @go get github.com/kevinburke/go-bindata/go-bindata
else else
@echo "go-bindata already installed; skipping..." @echo "go-bindata already installed; skipping..."
endif endif
ifeq (, $(shell which gencodec)) ifeq (, $(shell which gencodec))
@echo "Installing gencodec..." @echo "Installing gencodec..."
@go install github.com/fjl/gencodec @go get github.com/fjl/gencodec
else else
@echo "gencodec already installed; skipping..." @echo "gencodec already installed; skipping..."
endif endif
ifeq (, $(shell which protoc-gen-go)) ifeq (, $(shell which protoc-gen-go))
@echo "Installing protoc-gen-go..." @echo "Installing protoc-gen-go..."
@go install github.com/golang/protobuf/protoc-gen-go @go get github.com/fjl/gencodec github.com/golang/protobuf/protoc-gen-go
else else
@echo "protoc-gen-go already installed; skipping..." @echo "protoc-gen-go already installed; skipping..."
endif endif
ifeq (, $(shell which protoc))
@echo "Please istalling protobuf according to your OS"
@echo "macOS: brew install protobuf"
@echo "linux: apt-get install -f -y protobuf-compiler"
else
@echo "protoc already installed; skipping..."
endif
ifeq (, $(shell which solcjs)) ifeq (, $(shell which solcjs))
@echo "Installing solcjs..." @echo "Installing solcjs..."
@apt-get install -f -y protobuf-compiler
@npm install -g solc@0.5.11 @npm install -g solc@0.5.11
else else
@echo "solcjs already installed; skipping..." @echo "solcjs already installed; skipping..."
@ -234,7 +236,7 @@ else
endif endif
tools: tools-stamp tools: tools-stamp
tools-stamp: contract-tools docs-tools runsim tools-stamp: contract-tools docs-tools proto-tools runsim
# Create dummy file to satisfy dependency and avoid # Create dummy file to satisfy dependency and avoid
# rebuilding when this Makefile target is hit twice # rebuilding when this Makefile target is hit twice
# in a row. # in a row.
@ -250,7 +252,7 @@ docs-tools-stamp: docs-tools
# in a row. # in a row.
touch $@ touch $@
.PHONY: runsim tools tools-stamp tools-clean docs-tools-stamp .PHONY: runsim tools contract-tools docs-tools proto-tools tools-stamp tools-clean docs-tools-stamp
############################################################################### ###############################################################################
### Tests & Simulation ### ### Tests & Simulation ###
@ -270,10 +272,10 @@ test-import:
rm -rf importer/tmp rm -rf importer/tmp
test-rpc: test-rpc:
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" ./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
test-rpc-pending: test-rpc-pending:
./scripts/integration-test-all.sh -t "pending" -q 1 -z 1 -s 2 -m "pending" ./scripts/integration-test-all.sh -t "pending" -q 1 -z 1 -s 2 -m "pending" -r "true"
test-contract: test-contract:
@type "npm" 2> /dev/null || (echo 'Npm does not exist. Please install node.js and npm."' && exit 1) @type "npm" 2> /dev/null || (echo 'Npm does not exist. Please install node.js and npm."' && exit 1)
@ -288,22 +290,22 @@ test-sim-nondeterminism:
test-sim-custom-genesis-fast: test-sim-custom-genesis-fast:
@echo "Running custom genesis simulation..." @echo "Running custom genesis simulation..."
@echo "By default, ${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json will be used." @echo "By default, ${HOME}/.$(ETHERMINT_DIR)/config/genesis.json will be used."
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json \ @go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.$(ETHERMINT_DIR)/config/genesis.json \
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h -Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
test-sim-import-export: runsim test-sim-import-export: runsim
@echo "Running application import/export simulation. This may take several minutes..." @echo "Running application import/export simulation. This may take several minutes..."
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail -Genesis=${HOME}/.$(ETHERMINT_DIR)/config/genesis.json 50 5 TestAppImportExport
test-sim-after-import: runsim test-sim-after-import: runsim
@echo "Running application simulation-after-import. This may take several minutes..." @echo "Running application simulation-after-import. This may take several minutes..."
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -Genesis=${HOME}/.$(ETHERMINT_DIR)/config/genesis.json -ExitOnFail 50 5 TestAppSimulationAfterImport
test-sim-custom-genesis-multi-seed: runsim test-sim-custom-genesis-multi-seed: runsim
@echo "Running multi-seed custom genesis simulation..." @echo "Running multi-seed custom genesis simulation..."
@echo "By default, ${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json will be used." @echo "By default, ${HOME}/.$(ETHERMINT_DIR)/config/genesis.json will be used."
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail -Genesis=${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json 400 5 TestFullAppSimulation @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail -Genesis=${HOME}/.$(ETHERMINT_DIR)/config/genesis.json 400 5 TestFullAppSimulation
test-sim-multi-seed-long: runsim test-sim-multi-seed-long: runsim
@echo "Running multi-seed application simulation. This may take awhile!" @echo "Running multi-seed application simulation. This may take awhile!"
@ -359,13 +361,19 @@ proto-format:
proto-swagger-gen: proto-swagger-gen:
@./scripts/protoc-swagger-gen.sh @./scripts/protoc-swagger-gen.sh
proto-format:
find ./ -not -path "./third_party/*" -name *.proto -exec clang-format -i {} \;
proto-swagger-gen:
@./scripts/protoc-swagger-gen.sh
proto-lint: proto-lint:
@$(DOCKER_BUF) check lint --error-format=json @$(DOCKER_BUF) check lint --error-format=json
proto-check-breaking: proto-check-breaking:
@$(DOCKER_BUF) check breaking --against-input $(HTTPS_GIT)#branch=development @$(DOCKER_BUF) check breaking --against-input $(HTTPS_GIT)#branch=development
TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.0-rc6/proto/tendermint TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.1/proto/tendermint
GOGO_PROTO_URL = https://raw.githubusercontent.com/regen-network/protobuf/cosmos GOGO_PROTO_URL = https://raw.githubusercontent.com/regen-network/protobuf/cosmos
COSMOS_SDK_URL = https://raw.githubusercontent.com/cosmos/cosmos-sdk/master COSMOS_SDK_URL = https://raw.githubusercontent.com/cosmos/cosmos-sdk/master
COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master
@ -437,13 +445,13 @@ ifeq ($(OS),Windows_NT)
mkdir build & mkdir build &
@$(MAKE) docker-localnet @$(MAKE) docker-localnet
IF not exist "build/node0/$(ETHERMINT_DAEMON_BINARY)/config/genesis.json" docker run --rm -v $(CURDIR)/build\ethermint\Z ethermintd/node "ethermintd testnet --v 4 -o /ethermint --starting-ip-address 192.168.10.2 --keyring-backend=test" IF not exist "build/node0/$(ETHERMINT_BINARY)/config/genesis.json" docker run --rm -v $(CURDIR)/build\ethermint\Z ethermintd/node "ethermintd testnet --v 4 -o /ethermint --starting-ip-address 192.168.10.2 --keyring-backend=test"
docker-compose up -d docker-compose up -d
else else
mkdir -p ./build/ mkdir -p ./build/
@$(MAKE) docker-localnet @$(MAKE) docker-localnet
if ! [ -f build/node0/$(ETHERMINT_DAEMON_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/ethermint:Z ethermintd/node "ethermintd testnet --v 4 -o /ethermint --starting-ip-address 192.168.10.2 --keyring-backend=test"; fi if ! [ -f build/node0/$(ETHERMINT_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/build:/ethermint:Z ethermintd/node "ethermintd testnet --v 4 -o /ethermint --starting-ip-address 192.168.10.2 --keyring-backend=test"; fi
docker-compose up -d docker-compose up -d
endif endif

View File

@ -1,23 +1,22 @@
package ante package ante
import ( import (
"fmt"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/keeper" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" "github.com/cosmos/ethermint/crypto/ethsecp256k1"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
) )
func init() {
ethsecp256k1.RegisterCodec(types.ModuleCdc)
}
const ( const (
// TODO: Use this cost per byte through parameter or overriding NewConsumeGasForTxSizeDecorator // TODO: Use this cost per byte through parameter or overriding NewConsumeGasForTxSizeDecorator
// which currently defaults at 10, if intended // which currently defaults at 10, if intended
@ -25,43 +24,61 @@ const (
secp256k1VerifyCost uint64 = 21000 secp256k1VerifyCost uint64 = 21000
) )
// AccountKeeper defines an expected keeper interface for the auth module's AccountKeeper
type AccountKeeper interface {
authante.AccountKeeper
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
}
// BankKeeper defines an expected keeper interface for the bank module's Keeper
type BankKeeper interface {
authtypes.BankKeeper
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error
}
// NewAnteHandler returns an ante handler responsible for attempting to route an // NewAnteHandler returns an ante handler responsible for attempting to route an
// Ethereum or SDK transaction to an internal ante handler for performing // Ethereum or SDK transaction to an internal ante handler for performing
// transaction-level processing (e.g. fee payment, signature verification) before // transaction-level processing (e.g. fee payment, signature verification) before
// being passed onto it's respective handler. // being passed onto it's respective handler.
func NewAnteHandler(ak auth.AccountKeeper, evmKeeper EVMKeeper, sk types.SupplyKeeper) sdk.AnteHandler { func NewAnteHandler(
ak AccountKeeper, bankKeeper BankKeeper, evmKeeper EVMKeeper, signModeHandler authsigning.SignModeHandler,
) sdk.AnteHandler {
return func( return func(
ctx sdk.Context, tx sdk.Tx, sim bool, ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) { ) (newCtx sdk.Context, err error) {
var anteHandler sdk.AnteHandler var anteHandler sdk.AnteHandler
switch tx.(type) { switch tx.(type) {
case auth.StdTx: case *evmtypes.MsgEthereumTx:
anteHandler = sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
NewAccountSetupDecorator(ak),
authante.NewMempoolFeeDecorator(),
authante.NewValidateBasicDecorator(),
authante.NewValidateMemoDecorator(ak),
authante.NewConsumeGasForTxSizeDecorator(ak),
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
authante.NewValidateSigCountDecorator(ak),
authante.NewDeductFeeDecorator(ak, sk),
authante.NewSigGasConsumeDecorator(ak, sigGasConsumer),
authante.NewSigVerificationDecorator(ak),
authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator
)
case evmtypes.MsgEthereumTx:
anteHandler = sdk.ChainAnteDecorators( anteHandler = sdk.ChainAnteDecorators(
NewEthSetupContextDecorator(), // outermost AnteDecorator. EthSetUpContext must be called first NewEthSetupContextDecorator(), // outermost AnteDecorator. EthSetUpContext must be called first
authante.NewRejectExtensionOptionsDecorator(),
NewEthMempoolFeeDecorator(evmKeeper), NewEthMempoolFeeDecorator(evmKeeper),
authante.NewValidateBasicDecorator(), authante.NewValidateBasicDecorator(),
NewEthSigVerificationDecorator(), NewEthSigVerificationDecorator(),
NewAccountVerificationDecorator(ak, evmKeeper), NewAccountVerificationDecorator(ak, bankKeeper, evmKeeper),
NewNonceVerificationDecorator(ak), NewNonceVerificationDecorator(ak),
NewEthGasConsumeDecorator(ak, sk, evmKeeper), NewEthGasConsumeDecorator(ak, bankKeeper, evmKeeper),
NewIncrementSenderSequenceDecorator(ak), // innermost AnteDecorator. NewIncrementSenderSequenceDecorator(ak), // innermost AnteDecorator.
) )
case sdk.Tx:
anteHandler = sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
authante.NewRejectExtensionOptionsDecorator(),
authante.NewMempoolFeeDecorator(),
authante.NewValidateBasicDecorator(),
authante.TxTimeoutHeightDecorator{},
authante.NewValidateMemoDecorator(ak),
authante.NewConsumeGasForTxSizeDecorator(ak),
authante.NewRejectFeeGranterDecorator(),
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
authante.NewValidateSigCountDecorator(ak),
authante.NewDeductFeeDecorator(ak, bankKeeper),
authante.NewSigGasConsumeDecorator(ak, DefaultSigVerificationGasConsumer),
authante.NewSigVerificationDecorator(ak, signModeHandler),
authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator
)
default: default:
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
@ -70,59 +87,40 @@ func NewAnteHandler(ak auth.AccountKeeper, evmKeeper EVMKeeper, sk types.SupplyK
} }
} }
// sigGasConsumer overrides the DefaultSigVerificationGasConsumer from the x/auth var _ = DefaultSigVerificationGasConsumer
// module on the SDK. It doesn't allow ed25519 nor multisig thresholds.
func sigGasConsumer( // DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
meter sdk.GasMeter, _ []byte, pubkey tmcrypto.PubKey, _ types.Params, // for signature verification based upon the public key type. The cost is fetched from the given params and is matched
// by the concrete type.
func DefaultSigVerificationGasConsumer(
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
) error { ) error {
switch pubkey.(type) { pubkey := sig.PubKey
case ethsecp256k1.PubKey: switch pubkey := pubkey.(type) {
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: secp256k1") case *ed25519.PubKey:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
return nil return nil
case tmcrypto.PubKey:
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: tendermint secp256k1") case *secp256k1.PubKey:
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
return nil
// support for etherum ECDSA secp256k1 keys
case *ethsecp256k1.PubKey:
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
return nil
case multisig.PubKey:
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
if !ok {
return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data)
}
err := authante.ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence)
if err != nil {
return err
}
return nil return nil
default: default:
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey) return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
} }
} }
// AccountSetupDecorator sets an account to state if it's not stored already. This only applies for MsgEthermint.
type AccountSetupDecorator struct {
ak auth.AccountKeeper
}
// NewAccountSetupDecorator creates a new AccountSetupDecorator instance
func NewAccountSetupDecorator(ak auth.AccountKeeper) AccountSetupDecorator {
return AccountSetupDecorator{
ak: ak,
}
}
// AnteHandle sets an account for MsgEthermint (evm) if the sender is registered.
// NOTE: Since the account is set without any funds, the message execution will
// fail if the validator requires a minimum fee > 0.
func (asd AccountSetupDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
msgs := tx.GetMsgs()
if len(msgs) == 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "no messages included in transaction")
}
for _, msg := range msgs {
if msgEthermint, ok := msg.(evmtypes.MsgEthermint); ok {
setupAccount(asd.ak, ctx, msgEthermint.From)
}
}
return next(ctx, tx, simulate)
}
func setupAccount(ak keeper.AccountKeeper, ctx sdk.Context, addr sdk.AccAddress) {
acc := ak.GetAccount(ctx, addr)
if acc != nil {
return
}
acc = ak.NewAccountWithAddress(ctx, addr)
ak.SetAccount(ctx, acc)
}

View File

@ -9,9 +9,9 @@ import (
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/app" "github.com/cosmos/ethermint/app"
@ -42,12 +42,14 @@ func (suite *AnteTestSuite) TestValidEthTx() {
addr2, _ := newTestAddrKey() addr2, _ := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc1) suite.app.AccountKeeper.SetAccount(suite.ctx, acc1)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc1.GetAddress(), newTestCoins())
suite.Require().NoError(err)
acc2 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr2) acc2 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr2)
_ = acc2.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc2) suite.app.AccountKeeper.SetAccount(suite.ctx, acc2)
err = suite.app.BankKeeper.SetBalances(suite.ctx, acc2.GetAddress(), newTestCoins())
suite.Require().NoError(err)
// require a valid Ethereum tx to pass // require a valid Ethereum tx to pass
to := ethcmn.BytesToAddress(addr2.Bytes()) to := ethcmn.BytesToAddress(addr2.Bytes())
@ -60,32 +62,35 @@ func (suite *AnteTestSuite) TestValidEthTx() {
requireValidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false) requireValidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false)
} }
func (suite *AnteTestSuite) TestValidTx() { // the legacytx.NewStdTx has been deprecated and It only works with Amino now
func (suite *AnteTestSuite) TestInValidTx() {
suite.ctx = suite.ctx.WithBlockHeight(1) suite.ctx = suite.ctx.WithBlockHeight(1)
addr1, priv1 := newTestAddrKey() addr1, priv1 := newTestAddrKey()
addr2, priv2 := newTestAddrKey() addr2, priv2 := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc1) suite.app.AccountKeeper.SetAccount(suite.ctx, acc1)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc1.GetAddress(), newTestCoins())
suite.Require().NoError(err)
acc2 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr2) acc2 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr2)
_ = acc2.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc2) suite.app.AccountKeeper.SetAccount(suite.ctx, acc2)
err = suite.app.BankKeeper.SetBalances(suite.ctx, acc2.GetAddress(), newTestCoins())
suite.Require().NoError(err)
// require a valid SDK tx to pass // require a valid SDK tx to pass
fee := newTestStdFee() fee := newTestStdFee()
msg1 := newTestMsg(addr1, addr2) msg1 := newTestMsg(addr1, addr2)
msgs := []sdk.Msg{msg1} msgs := []sdk.Msg{msg1}
privKeys := []tmcrypto.PrivKey{priv1, priv2} privKeys := []cryptotypes.PrivKey{priv1, priv2}
accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()} accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()} accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()}
tx := newTestSDKTx(suite.ctx, msgs, privKeys, accNums, accSeqs, fee) tx := newTestSDKTx(suite.ctx, msgs, privKeys, accNums, accSeqs, fee)
requireValidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false) requireInvalidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false)
} }
func (suite *AnteTestSuite) TestSDKInvalidSigs() { func (suite *AnteTestSuite) TestSDKInvalidSigs() {
@ -96,12 +101,14 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
addr3, priv3 := newTestAddrKey() addr3, priv3 := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc1) suite.app.AccountKeeper.SetAccount(suite.ctx, acc1)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc1.GetAddress(), newTestCoins())
suite.Require().NoError(err)
acc2 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr2) acc2 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr2)
_ = acc2.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc2) suite.app.AccountKeeper.SetAccount(suite.ctx, acc2)
err = suite.app.BankKeeper.SetBalances(suite.ctx, acc2.GetAddress(), newTestCoins())
suite.Require().NoError(err)
fee := newTestStdFee() fee := newTestStdFee()
msg1 := newTestMsg(addr1, addr2) msg1 := newTestMsg(addr1, addr2)
@ -109,7 +116,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
// require validation failure with no signers // require validation failure with no signers
msgs := []sdk.Msg{msg1} msgs := []sdk.Msg{msg1}
privKeys := []tmcrypto.PrivKey{} privKeys := []cryptotypes.PrivKey{}
accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()} accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()} accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()}
@ -119,7 +126,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
// require validation failure with invalid number of signers // require validation failure with invalid number of signers
msgs = []sdk.Msg{msg1} msgs = []sdk.Msg{msg1}
privKeys = []tmcrypto.PrivKey{priv1} privKeys = []cryptotypes.PrivKey{priv1}
accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()} accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence()} accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence()}
@ -130,7 +137,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
msg2 := newTestMsg(addr1, addr3) msg2 := newTestMsg(addr1, addr3)
msgs = []sdk.Msg{msg1, msg2} msgs = []sdk.Msg{msg1, msg2}
privKeys = []tmcrypto.PrivKey{priv1, priv2, priv3} privKeys = []cryptotypes.PrivKey{priv1, priv2, priv3}
accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber(), 0} accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber(), 0}
accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence(), 0} accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence(), 0}
@ -144,13 +151,14 @@ func (suite *AnteTestSuite) TestSDKInvalidAcc() {
addr1, priv1 := newTestAddrKey() addr1, priv1 := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc1) suite.app.AccountKeeper.SetAccount(suite.ctx, acc1)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc1.GetAddress(), newTestCoins())
suite.Require().NoError(err)
fee := newTestStdFee() fee := newTestStdFee()
msg1 := newTestMsg(addr1) msg1 := newTestMsg(addr1)
msgs := []sdk.Msg{msg1} msgs := []sdk.Msg{msg1}
privKeys := []tmcrypto.PrivKey{priv1} privKeys := []cryptotypes.PrivKey{priv1}
// require validation failure with invalid account number // require validation failure with invalid account number
accNums := []uint64{1} accNums := []uint64{1}
@ -194,8 +202,9 @@ func (suite *AnteTestSuite) TestEthInvalidNonce() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
err := acc.SetSequence(10) err := acc.SetSequence(10)
suite.Require().NoError(err) suite.Require().NoError(err)
_ = acc.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc) suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
err = suite.app.BankKeeper.SetBalances(suite.ctx, acc.GetAddress(), newTestCoins())
suite.Require().NoError(err)
// require a valid Ethereum tx to pass // require a valid Ethereum tx to pass
to := ethcmn.BytesToAddress(addr2.Bytes()) to := ethcmn.BytesToAddress(addr2.Bytes())
@ -235,8 +244,9 @@ func (suite *AnteTestSuite) TestEthInvalidIntrinsicGas() {
addr2, _ := newTestAddrKey() addr2, _ := newTestAddrKey()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc) suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc.GetAddress(), newTestCoins())
suite.Require().NoError(err)
// require a valid Ethereum tx to pass // require a valid Ethereum tx to pass
to := ethcmn.BytesToAddress(addr2.Bytes()) to := ethcmn.BytesToAddress(addr2.Bytes())
@ -253,17 +263,18 @@ func (suite *AnteTestSuite) TestEthInvalidIntrinsicGas() {
func (suite *AnteTestSuite) TestEthInvalidMempoolFees() { func (suite *AnteTestSuite) TestEthInvalidMempoolFees() {
// setup app with checkTx = true // setup app with checkTx = true
suite.app = app.Setup(true) suite.app = app.Setup(true)
suite.ctx = suite.app.BaseApp.NewContext(true, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()}) suite.ctx = suite.app.BaseApp.NewContext(true, tmproto.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams()) suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper) suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper, suite.encodingConfig.TxConfig.SignModeHandler())
suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(types.NewPhotonDecCoin(sdk.NewInt(500000)))) suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(types.NewPhotonDecCoin(sdk.NewInt(500000))))
addr1, priv1 := newTestAddrKey() addr1, priv1 := newTestAddrKey()
addr2, _ := newTestAddrKey() addr2, _ := newTestAddrKey()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc) suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc.GetAddress(), newTestCoins())
suite.Require().NoError(err)
// require a valid Ethereum tx to pass // require a valid Ethereum tx to pass
to := ethcmn.BytesToAddress(addr2.Bytes()) to := ethcmn.BytesToAddress(addr2.Bytes())
@ -283,8 +294,9 @@ func (suite *AnteTestSuite) TestEthInvalidChainID() {
addr2, _ := newTestAddrKey() addr2, _ := newTestAddrKey()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1) acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc) suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc.GetAddress(), newTestCoins())
suite.Require().NoError(err)
// require a valid Ethereum tx to pass // require a valid Ethereum tx to pass
to := ethcmn.BytesToAddress(addr2.Bytes()) to := ethcmn.BytesToAddress(addr2.Bytes())

View File

@ -6,9 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/types"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
@ -91,7 +89,7 @@ func (emfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx) msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
@ -99,7 +97,7 @@ func (emfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
evmDenom := emfd.evmKeeper.GetParams(ctx).EvmDenom evmDenom := emfd.evmKeeper.GetParams(ctx).EvmDenom
// fee = gas price * gas limit // fee = gas price * gas limit
fee := sdk.NewDecCoinFromDec(evmDenom, sdk.NewDecFromBigIntWithPrec(msgEthTx.Fee(), sdk.Precision)) fee := sdk.NewDecCoin(evmDenom, sdk.NewIntFromBigInt(msgEthTx.Fee()))
minGasPrices := ctx.MinGasPrices() minGasPrices := ctx.MinGasPrices()
minFees := minGasPrices.AmountOf(evmDenom).MulInt64(int64(msgEthTx.Data.GasLimit)) minFees := minGasPrices.AmountOf(evmDenom).MulInt64(int64(msgEthTx.Data.GasLimit))
@ -134,7 +132,7 @@ func NewEthSigVerificationDecorator() EthSigVerificationDecorator {
// AnteHandle validates the signature and returns sender address // AnteHandle validates the signature and returns sender address
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx) msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
@ -159,15 +157,17 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
// AccountVerificationDecorator validates an account balance checks // AccountVerificationDecorator validates an account balance checks
type AccountVerificationDecorator struct { type AccountVerificationDecorator struct {
ak auth.AccountKeeper ak AccountKeeper
evmKeeper EVMKeeper bankKeeper BankKeeper
evmKeeper EVMKeeper
} }
// NewAccountVerificationDecorator creates a new AccountVerificationDecorator // NewAccountVerificationDecorator creates a new AccountVerificationDecorator
func NewAccountVerificationDecorator(ak auth.AccountKeeper, ek EVMKeeper) AccountVerificationDecorator { func NewAccountVerificationDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKeeper) AccountVerificationDecorator {
return AccountVerificationDecorator{ return AccountVerificationDecorator{
ak: ak, ak: ak,
evmKeeper: ek, bankKeeper: bankKeeper,
evmKeeper: ek,
} }
} }
@ -177,13 +177,13 @@ func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx) msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
// sender address should be in the tx cache from the previous AnteHandle call // sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.From() address := msgEthTx.GetFrom()
if address.Empty() { if address.Empty() {
panic("sender address cannot be empty") panic("sender address cannot be empty")
} }
@ -205,8 +205,8 @@ func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
evmDenom := avd.evmKeeper.GetParams(ctx).EvmDenom evmDenom := avd.evmKeeper.GetParams(ctx).EvmDenom
// validate sender has enough funds to pay for gas cost // validate sender has enough funds to pay for gas cost
balance := acc.GetCoins().AmountOf(evmDenom) balance := avd.bankKeeper.GetBalance(ctx, address, evmDenom)
if balance.BigInt().Cmp(msgEthTx.Cost()) < 0 { if balance.Amount.BigInt().Cmp(msgEthTx.Cost()) < 0 {
return ctx, sdkerrors.Wrapf( return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds, sdkerrors.ErrInsufficientFunds,
"sender balance < tx gas cost (%s%s < %s%s)", balance.String(), evmDenom, msgEthTx.Cost().String(), evmDenom, "sender balance < tx gas cost (%s%s < %s%s)", balance.String(), evmDenom, msgEthTx.Cost().String(), evmDenom,
@ -219,11 +219,11 @@ func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
// NonceVerificationDecorator checks that the account nonce from the transaction matches // NonceVerificationDecorator checks that the account nonce from the transaction matches
// the sender account sequence. // the sender account sequence.
type NonceVerificationDecorator struct { type NonceVerificationDecorator struct {
ak auth.AccountKeeper ak AccountKeeper
} }
// NewNonceVerificationDecorator creates a new NonceVerificationDecorator // NewNonceVerificationDecorator creates a new NonceVerificationDecorator
func NewNonceVerificationDecorator(ak auth.AccountKeeper) NonceVerificationDecorator { func NewNonceVerificationDecorator(ak AccountKeeper) NonceVerificationDecorator {
return NonceVerificationDecorator{ return NonceVerificationDecorator{
ak: ak, ak: ak,
} }
@ -232,13 +232,13 @@ func NewNonceVerificationDecorator(ak auth.AccountKeeper) NonceVerificationDecor
// AnteHandle validates that the transaction nonce is valid (equivalent to the sender accounts // AnteHandle validates that the transaction nonce is valid (equivalent to the sender accounts
// current nonce). // current nonce).
func (nvd NonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { func (nvd NonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx) msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
// sender address should be in the tx cache from the previous AnteHandle call // sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.From() address := msgEthTx.GetFrom()
if address.Empty() { if address.Empty() {
panic("sender address cannot be empty") panic("sender address cannot be empty")
} }
@ -268,17 +268,17 @@ func (nvd NonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim
// EthGasConsumeDecorator validates enough intrinsic gas for the transaction and // EthGasConsumeDecorator validates enough intrinsic gas for the transaction and
// gas consumption. // gas consumption.
type EthGasConsumeDecorator struct { type EthGasConsumeDecorator struct {
ak auth.AccountKeeper ak AccountKeeper
sk types.SupplyKeeper bankKeeper BankKeeper
evmKeeper EVMKeeper evmKeeper EVMKeeper
} }
// NewEthGasConsumeDecorator creates a new EthGasConsumeDecorator // NewEthGasConsumeDecorator creates a new EthGasConsumeDecorator
func NewEthGasConsumeDecorator(ak auth.AccountKeeper, sk types.SupplyKeeper, ek EVMKeeper) EthGasConsumeDecorator { func NewEthGasConsumeDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKeeper) EthGasConsumeDecorator {
return EthGasConsumeDecorator{ return EthGasConsumeDecorator{
ak: ak, ak: ak,
sk: sk, bankKeeper: bankKeeper,
evmKeeper: ek, evmKeeper: ek,
} }
} }
@ -290,19 +290,19 @@ func NewEthGasConsumeDecorator(ak auth.AccountKeeper, sk types.SupplyKeeper, ek
// constant value of 21000 plus any cost inccured by additional bytes of data // constant value of 21000 plus any cost inccured by additional bytes of data
// supplied with the transaction. // supplied with the transaction.
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx) msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
// sender address should be in the tx cache from the previous AnteHandle call // sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.From() address := msgEthTx.GetFrom()
if address.Empty() { if address.Empty() {
panic("sender address cannot be empty") panic("sender address cannot be empty")
} }
// fetch sender account from signature // fetch sender account from signature
senderAcc, err := auth.GetSignerAcc(ctx, egcd.ak, address) senderAcc, err := authante.GetSignerAcc(ctx, egcd.ak, address)
if err != nil { if err != nil {
return ctx, err return ctx, err
} }
@ -336,14 +336,14 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
sdk.NewCoin(evmDenom, sdk.NewIntFromBigInt(cost)), sdk.NewCoin(evmDenom, sdk.NewIntFromBigInt(cost)),
) )
err = auth.DeductFees(egcd.sk, ctx, senderAcc, feeAmt) err = authante.DeductFees(egcd.bankKeeper, ctx, senderAcc, feeAmt)
if err != nil { if err != nil {
return ctx, err return ctx, err
} }
} }
// Set gas meter after ante handler to ignore gaskv costs // Set gas meter after ante handler to ignore gaskv costs
newCtx = auth.SetGasMeter(simulate, ctx, gasLimit) newCtx = authante.SetGasMeter(simulate, ctx, gasLimit)
return next(newCtx, tx, simulate) return next(newCtx, tx, simulate)
} }
@ -353,11 +353,11 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
// //
// CONTRACT: must be called after msg.VerifySig in order to cache the sender address. // CONTRACT: must be called after msg.VerifySig in order to cache the sender address.
type IncrementSenderSequenceDecorator struct { type IncrementSenderSequenceDecorator struct {
ak auth.AccountKeeper ak AccountKeeper
} }
// NewIncrementSenderSequenceDecorator creates a new IncrementSenderSequenceDecorator. // NewIncrementSenderSequenceDecorator creates a new IncrementSenderSequenceDecorator.
func NewIncrementSenderSequenceDecorator(ak auth.AccountKeeper) IncrementSenderSequenceDecorator { func NewIncrementSenderSequenceDecorator(ak AccountKeeper) IncrementSenderSequenceDecorator {
return IncrementSenderSequenceDecorator{ return IncrementSenderSequenceDecorator{
ak: ak, ak: ak,
} }
@ -370,7 +370,7 @@ func (issd IncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.
gasMeter := ctx.GasMeter() gasMeter := ctx.GasMeter()
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx) msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
ctx = ctx.WithGasMeter(gasMeter) ctx = ctx.WithGasMeter(gasMeter)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)

View File

@ -1,14 +1,16 @@
package ante_test package ante_test
import ( import (
"fmt"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/ethermint/app" "github.com/cosmos/ethermint/app"
ante "github.com/cosmos/ethermint/app/ante" ante "github.com/cosmos/ethermint/app/ante"
@ -16,50 +18,56 @@ import (
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto" ethcrypto "github.com/ethereum/go-ethereum/crypto"
abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
) )
type AnteTestSuite struct { type AnteTestSuite struct {
suite.Suite suite.Suite
ctx sdk.Context ctx sdk.Context
app *app.EthermintApp app *app.EthermintApp
anteHandler sdk.AnteHandler encodingConfig params.EncodingConfig
anteHandler sdk.AnteHandler
} }
func (suite *AnteTestSuite) SetupTest() { func (suite *AnteTestSuite) SetupTest() {
checkTx := false checkTx := false
suite.app = app.Setup(checkTx) suite.app = app.Setup(checkTx)
suite.app.Codec().RegisterConcrete(&sdk.TestMsg{}, "test/TestMsg", nil)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()}) suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 2, ChainID: "ethermint-3", Time: time.Now().UTC()})
suite.app.AccountKeeper.SetParams(suite.ctx, authtypes.DefaultParams())
suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams()) suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.SupplyKeeper) suite.encodingConfig = app.MakeEncodingConfig()
// We're using TestMsg amino encoding in some tests, so register it here.
suite.encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper, suite.encodingConfig.TxConfig.SignModeHandler())
} }
func TestAnteTestSuite(t *testing.T) { func TestAnteTestSuite(t *testing.T) {
suite.Run(t, new(AnteTestSuite)) suite.Run(t, new(AnteTestSuite))
} }
func newTestMsg(addrs ...sdk.AccAddress) *sdk.TestMsg { func newTestMsg(addrs ...sdk.AccAddress) *testdata.TestMsg {
return sdk.NewTestMsg(addrs...) return testdata.NewTestMsg(addrs...)
} }
func newTestCoins() sdk.Coins { func newTestCoins() sdk.Coins {
return sdk.NewCoins(ethermint.NewPhotonCoinInt64(500000000)) return sdk.NewCoins(ethermint.NewPhotonCoinInt64(500000000))
} }
func newTestStdFee() auth.StdFee { func newTestStdFee() legacytx.StdFee {
return auth.NewStdFee(220000, sdk.NewCoins(ethermint.NewPhotonCoinInt64(150))) return legacytx.NewStdFee(220000, sdk.NewCoins(ethermint.NewPhotonCoinInt64(150)))
} }
// GenerateAddress generates an Ethereum address. // GenerateAddress generates an Ethereum address.
func newTestAddrKey() (sdk.AccAddress, tmcrypto.PrivKey) { func newTestAddrKey() (sdk.AccAddress, cryptotypes.PrivKey) {
privkey, _ := ethsecp256k1.GenerateKey() privkey, _ := ethsecp256k1.GenerateKey()
addr := ethcrypto.PubkeyToAddress(privkey.ToECDSA().PublicKey) addr := ethcrypto.PubkeyToAddress(privkey.ToECDSA().PublicKey)
@ -67,38 +75,35 @@ func newTestAddrKey() (sdk.AccAddress, tmcrypto.PrivKey) {
} }
func newTestSDKTx( func newTestSDKTx(
ctx sdk.Context, msgs []sdk.Msg, privs []tmcrypto.PrivKey, ctx sdk.Context, msgs []sdk.Msg, privs []cryptotypes.PrivKey,
accNums []uint64, seqs []uint64, fee auth.StdFee, accNums []uint64, seqs []uint64, fee legacytx.StdFee,
) sdk.Tx { ) sdk.Tx {
sigs := make([]auth.StdSignature, len(privs)) sigs := make([]legacytx.StdSignature, len(privs))
for i, priv := range privs { for i, priv := range privs {
signBytes := auth.StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], fee, msgs, "") signBytes := legacytx.StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], 0, fee, msgs, "")
sig, err := priv.Sign(signBytes) sig, err := priv.Sign(signBytes)
if err != nil { if err != nil {
panic(err) panic(err)
} }
sigs[i] = auth.StdSignature{ sigs[i] = legacytx.StdSignature{
PubKey: priv.PubKey(), PubKey: priv.PubKey(),
Signature: sig, Signature: sig,
} }
} }
return auth.NewStdTx(msgs, fee, sigs, "") return legacytx.NewStdTx(msgs, fee, sigs, "")
} }
func newTestEthTx(ctx sdk.Context, msg evmtypes.MsgEthereumTx, priv tmcrypto.PrivKey) (sdk.Tx, error) { func newTestEthTx(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey) (sdk.Tx, error) {
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID()) chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if err != nil { if err != nil {
return nil, err return nil, err
} }
privkey, ok := priv.(ethsecp256k1.PrivKey) privkey := &ethsecp256k1.PrivKey{Key: priv.Bytes()}
if !ok {
return nil, fmt.Errorf("invalid private key type: %T", priv)
}
if err := msg.Sign(chainIDEpoch, privkey.ToECDSA()); err != nil { if err := msg.Sign(chainIDEpoch, privkey.ToECDSA()); err != nil {
return nil, err return nil, err

72
app/encoding.go Normal file
View File

@ -0,0 +1,72 @@
package app
import (
"github.com/cosmos/cosmos-sdk/client"
amino "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/cosmos/ethermint/codec"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
)
// MakeEncodingConfig creates an EncodingConfig for testing
func MakeEncodingConfig() params.EncodingConfig {
cdc := amino.NewLegacyAmino()
interfaceRegistry := types.NewInterfaceRegistry()
marshaler := amino.NewProtoCodec(interfaceRegistry)
encodingConfig := params.EncodingConfig{
InterfaceRegistry: interfaceRegistry,
Marshaler: marshaler,
TxConfig: NewTxConfig(marshaler),
Amino: cdc,
}
codec.RegisterLegacyAminoCodec(encodingConfig.Amino)
ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino)
codec.RegisterInterfaces(encodingConfig.InterfaceRegistry)
ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry)
return encodingConfig
}
type txConfig struct {
cdc amino.ProtoCodecMarshaler
client.TxConfig
}
// NewTxConfig returns a new protobuf TxConfig using the provided ProtoCodec and sign modes. The
// first enabled sign mode will become the default sign mode.
func NewTxConfig(marshaler amino.ProtoCodecMarshaler) client.TxConfig {
return &txConfig{
marshaler,
tx.NewTxConfig(marshaler, tx.DefaultSignModes),
}
}
// TxEncoder overwites sdk.TxEncoder to support MsgEthereumTx
func (g txConfig) TxEncoder() sdk.TxEncoder {
return func(tx sdk.Tx) ([]byte, error) {
ethtx, ok := tx.(*evmtypes.MsgEthereumTx)
if ok {
return g.cdc.MarshalBinaryBare(ethtx)
}
return g.TxConfig.TxEncoder()(tx)
}
}
// TxDecoder overwites sdk.TxDecoder to support MsgEthereumTx
func (g txConfig) TxDecoder() sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, error) {
var ethtx evmtypes.MsgEthereumTx
err := g.cdc.UnmarshalBinaryBare(txBytes, &ethtx)
if err == nil {
return &ethtx, nil
}
return g.TxConfig.TxDecoder()(txBytes)
}
}

View File

@ -3,38 +3,95 @@ package app
import ( import (
"io" "io"
"os" "os"
"path/filepath"
bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
sdkapi "github.com/cosmos/cosmos-sdk/server/api"
sdkconfig "github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
"github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/bank"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/capability"
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
"github.com/cosmos/cosmos-sdk/x/crisis" "github.com/cosmos/cosmos-sdk/x/crisis"
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
distr "github.com/cosmos/cosmos-sdk/x/distribution" distr "github.com/cosmos/cosmos-sdk/x/distribution"
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/evidence" "github.com/cosmos/cosmos-sdk/x/evidence"
evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/gov"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer"
ibctransferkeeper "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper"
ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
ibc "github.com/cosmos/cosmos-sdk/x/ibc/core"
ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host"
ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper"
"github.com/cosmos/cosmos-sdk/x/mint" "github.com/cosmos/cosmos-sdk/x/mint"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/params" "github.com/cosmos/cosmos-sdk/x/params"
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal"
"github.com/cosmos/cosmos-sdk/x/slashing" "github.com/cosmos/cosmos-sdk/x/slashing"
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
"github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/supply" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/cosmos-sdk/x/upgrade" "github.com/cosmos/cosmos-sdk/x/upgrade"
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
// unnamed import of statik for swagger UI support
_ "github.com/cosmos/cosmos-sdk/client/docs/statik"
"github.com/cosmos/ethermint/app/ante" "github.com/cosmos/ethermint/app/ante"
ethermintcodec "github.com/cosmos/ethermint/codec"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm" "github.com/cosmos/ethermint/x/evm"
abci "github.com/tendermint/tendermint/abci/types" evmrest "github.com/cosmos/ethermint/x/evm/client/rest"
"github.com/tendermint/tendermint/libs/log" evmkeeper "github.com/cosmos/ethermint/x/evm/keeper"
tmos "github.com/tendermint/tendermint/libs/os" evmtypes "github.com/cosmos/ethermint/x/evm/types"
dbm "github.com/tendermint/tm-db"
) )
func init() { func init() {
@ -42,93 +99,113 @@ func init() {
config := sdk.GetConfig() config := sdk.GetConfig()
ethermint.SetBech32Prefixes(config) ethermint.SetBech32Prefixes(config)
ethermint.SetBip44CoinType(config) ethermint.SetBip44CoinType(config)
userHomeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
DefaultNodeHome = filepath.Join(userHomeDir, ".ethermint")
} }
const appName = "Ethermint" const appName = "Ethermint"
var ( var (
// DefaultCLIHome sets the default home directories for the application CLI // DefaultNodeHome default home directories for the application daemon
DefaultCLIHome = os.ExpandEnv("$HOME/.ethermintcli") DefaultNodeHome string
// DefaultNodeHome sets the folder where the applcation data and configuration will be stored
DefaultNodeHome = os.ExpandEnv("$HOME/.ethermintd")
// ModuleBasics defines the module BasicManager is in charge of setting up basic, // ModuleBasics defines the module BasicManager is in charge of setting up basic,
// non-dependant module elements, such as codec registration // non-dependant module elements, such as codec registration
// and genesis verification. // and genesis verification.
ModuleBasics = module.NewBasicManager( ModuleBasics = module.NewBasicManager(
auth.AppModuleBasic{}, auth.AppModuleBasic{},
supply.AppModuleBasic{},
genutil.AppModuleBasic{}, genutil.AppModuleBasic{},
bank.AppModuleBasic{}, bank.AppModuleBasic{},
capability.AppModuleBasic{},
staking.AppModuleBasic{}, staking.AppModuleBasic{},
mint.AppModuleBasic{}, mint.AppModuleBasic{},
distr.AppModuleBasic{}, distr.AppModuleBasic{},
gov.NewAppModuleBasic( gov.NewAppModuleBasic(
paramsclient.ProposalHandler, distr.ProposalHandler, upgradeclient.ProposalHandler, paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
), ),
params.AppModuleBasic{}, params.AppModuleBasic{},
crisis.AppModuleBasic{}, crisis.AppModuleBasic{},
slashing.AppModuleBasic{}, slashing.AppModuleBasic{},
evidence.AppModuleBasic{}, ibc.AppModuleBasic{},
upgrade.AppModuleBasic{}, upgrade.AppModuleBasic{},
evidence.AppModuleBasic{},
transfer.AppModuleBasic{},
vesting.AppModuleBasic{},
evm.AppModuleBasic{}, evm.AppModuleBasic{},
) )
// module account permissions // module account permissions
maccPerms = map[string][]string{ maccPerms = map[string][]string{
auth.FeeCollectorName: nil, authtypes.FeeCollectorName: nil,
distr.ModuleName: nil, distrtypes.ModuleName: nil,
mint.ModuleName: {supply.Minter}, minttypes.ModuleName: {authtypes.Minter},
staking.BondedPoolName: {supply.Burner, supply.Staking}, stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
staking.NotBondedPoolName: {supply.Burner, supply.Staking}, stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
gov.ModuleName: {supply.Burner}, govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
} }
// module accounts that are allowed to receive tokens // module accounts that are allowed to receive tokens
allowedReceivingModAcc = map[string]bool{ allowedReceivingModAcc = map[string]bool{
distr.ModuleName: true, distrtypes.ModuleName: true,
} }
) )
var _ simapp.App = (*EthermintApp)(nil) var (
// _ simapp.App = (*EthermintApp)(nil)
_ servertypes.Application = (*EthermintApp)(nil)
)
// EthermintApp implements an extended ABCI application. It is an application // EthermintApp implements an extended ABCI application. It is an application
// that may process transactions through Ethereum's EVM running atop of // that may process transactions through Ethereum's EVM running atop of
// Tendermint consensus. // Tendermint consensus.
type EthermintApp struct { type EthermintApp struct {
*bam.BaseApp *baseapp.BaseApp
cdc *codec.Codec cdc *codec.LegacyAmino
appCodec codec.Marshaler
interfaceRegistry types.InterfaceRegistry
invCheckPeriod uint invCheckPeriod uint
// keys to access the substores // keys to access the substores
keys map[string]*sdk.KVStoreKey keys map[string]*sdk.KVStoreKey
tkeys map[string]*sdk.TransientStoreKey tkeys map[string]*sdk.TransientStoreKey
memKeys map[string]*sdk.MemoryStoreKey
// subspaces
subspaces map[string]params.Subspace
// keepers // keepers
AccountKeeper auth.AccountKeeper AccountKeeper authkeeper.AccountKeeper
BankKeeper bank.Keeper BankKeeper bankkeeper.Keeper
SupplyKeeper supply.Keeper CapabilityKeeper *capabilitykeeper.Keeper
StakingKeeper staking.Keeper StakingKeeper stakingkeeper.Keeper
SlashingKeeper slashing.Keeper SlashingKeeper slashingkeeper.Keeper
MintKeeper mint.Keeper MintKeeper mintkeeper.Keeper
DistrKeeper distr.Keeper DistrKeeper distrkeeper.Keeper
GovKeeper gov.Keeper GovKeeper govkeeper.Keeper
CrisisKeeper crisis.Keeper CrisisKeeper crisiskeeper.Keeper
UpgradeKeeper upgrade.Keeper UpgradeKeeper upgradekeeper.Keeper
ParamsKeeper params.Keeper ParamsKeeper paramskeeper.Keeper
EvidenceKeeper evidence.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
EvmKeeper *evm.Keeper EvidenceKeeper evidencekeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper
// make scoped keepers public for test purposes
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedTransferKeeper capabilitykeeper.ScopedKeeper
// ethermint keepers
EvmKeeper *evmkeeper.Keeper
// the module manager // the module manager
mm *module.Manager mm *module.Manager
// simulation manager // simulation manager
sm *module.SimulationManager // disable for now, enable it once SDK side fix the simulator issue for custom keys
// sm *module.SimulationManager
} }
// NewEthermintApp returns a reference to a new initialized Ethermint application. // NewEthermintApp returns a reference to a new initialized Ethermint application.
@ -138,181 +215,267 @@ func NewEthermintApp(
traceStore io.Writer, traceStore io.Writer,
loadLatest bool, loadLatest bool,
skipUpgradeHeights map[int64]bool, skipUpgradeHeights map[int64]bool,
homePath string,
invCheckPeriod uint, invCheckPeriod uint,
baseAppOptions ...func(*bam.BaseApp), encodingConfig simappparams.EncodingConfig,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *EthermintApp { ) *EthermintApp {
cdc := ethermintcodec.MakeCodec(ModuleBasics) appCodec := encodingConfig.Marshaler
cdc := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
// NOTE we use custom Ethermint transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx // NOTE we use custom Ethermint transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
bApp := bam.NewBaseApp(appName, logger, db, evm.TxDecoder(cdc), baseAppOptions...) bApp := baseapp.NewBaseApp(
appName,
logger,
db,
encodingConfig.TxConfig.TxDecoder(),
baseAppOptions...,
)
bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetAppVersion(version.Version) bApp.SetAppVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
keys := sdk.NewKVStoreKeys( keys := sdk.NewKVStoreKeys(
bam.MainStoreKey, auth.StoreKey, staking.StoreKey, // SDK keys
supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey, authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
gov.StoreKey, params.StoreKey, upgrade.StoreKey, evidence.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
evm.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey,
evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey,
// ethermint keys
evmtypes.StoreKey,
) )
tkeys := sdk.NewTransientStoreKeys(params.TStoreKey) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
app := &EthermintApp{ app := &EthermintApp{
BaseApp: bApp, BaseApp: bApp,
cdc: cdc, cdc: cdc,
invCheckPeriod: invCheckPeriod, appCodec: appCodec,
keys: keys, interfaceRegistry: interfaceRegistry,
tkeys: tkeys, invCheckPeriod: invCheckPeriod,
subspaces: make(map[string]params.Subspace), keys: keys,
tkeys: tkeys,
memKeys: memKeys,
} }
// init params keeper and subspaces // init params keeper and subspaces
app.ParamsKeeper = params.NewKeeper(cdc, keys[params.StoreKey], tkeys[params.TStoreKey]) app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
app.subspaces[auth.ModuleName] = app.ParamsKeeper.Subspace(auth.DefaultParamspace) // set the BaseApp's parameter store
app.subspaces[bank.ModuleName] = app.ParamsKeeper.Subspace(bank.DefaultParamspace) bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()))
app.subspaces[staking.ModuleName] = app.ParamsKeeper.Subspace(staking.DefaultParamspace)
app.subspaces[mint.ModuleName] = app.ParamsKeeper.Subspace(mint.DefaultParamspace) // add capability keeper and ScopeToModule for ibc module
app.subspaces[distr.ModuleName] = app.ParamsKeeper.Subspace(distr.DefaultParamspace) app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
app.subspaces[slashing.ModuleName] = app.ParamsKeeper.Subspace(slashing.DefaultParamspace) scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
app.subspaces[gov.ModuleName] = app.ParamsKeeper.Subspace(gov.DefaultParamspace).WithKeyTable(gov.ParamKeyTable()) scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName)
app.subspaces[crisis.ModuleName] = app.ParamsKeeper.Subspace(crisis.DefaultParamspace)
app.subspaces[evidence.ModuleName] = app.ParamsKeeper.Subspace(evidence.DefaultParamspace)
app.subspaces[evm.ModuleName] = app.ParamsKeeper.Subspace(evm.DefaultParamspace)
// use custom Ethermint account for contracts // use custom Ethermint account for contracts
app.AccountKeeper = auth.NewAccountKeeper( app.AccountKeeper = authkeeper.NewAccountKeeper(
cdc, keys[auth.StoreKey], app.subspaces[auth.ModuleName], ethermint.ProtoAccount, appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
) )
app.BankKeeper = bank.NewBaseKeeper( app.BankKeeper = bankkeeper.NewBaseKeeper(
app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(), appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
) )
app.SupplyKeeper = supply.NewKeeper( stakingKeeper := stakingkeeper.NewKeeper(
cdc, keys[supply.StoreKey], app.AccountKeeper, app.BankKeeper, maccPerms, appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
) )
stakingKeeper := staking.NewKeeper( app.MintKeeper = mintkeeper.NewKeeper(
cdc, keys[staking.StoreKey], app.SupplyKeeper, app.subspaces[staking.ModuleName], appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
) )
app.MintKeeper = mint.NewKeeper( app.DistrKeeper = distrkeeper.NewKeeper(
cdc, keys[mint.StoreKey], app.subspaces[mint.ModuleName], &stakingKeeper, appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
app.SupplyKeeper, auth.FeeCollectorName, &stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
) )
app.DistrKeeper = distr.NewKeeper( app.SlashingKeeper = slashingkeeper.NewKeeper(
cdc, keys[distr.StoreKey], app.subspaces[distr.ModuleName], &stakingKeeper, appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
app.SupplyKeeper, auth.FeeCollectorName, app.ModuleAccountAddrs(),
) )
app.SlashingKeeper = slashing.NewKeeper( app.CrisisKeeper = crisiskeeper.NewKeeper(
cdc, keys[slashing.StoreKey], &stakingKeeper, app.subspaces[slashing.ModuleName], app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
)
app.CrisisKeeper = crisis.NewKeeper(
app.subspaces[crisis.ModuleName], invCheckPeriod, app.SupplyKeeper, auth.FeeCollectorName,
)
app.UpgradeKeeper = upgrade.NewKeeper(skipUpgradeHeights, keys[upgrade.StoreKey], app.cdc)
app.EvmKeeper = evm.NewKeeper(
app.cdc, keys[evm.StoreKey], app.subspaces[evm.ModuleName], app.AccountKeeper,
)
// create evidence keeper with router
evidenceKeeper := evidence.NewKeeper(
cdc, keys[evidence.StoreKey], app.subspaces[evidence.ModuleName], &app.StakingKeeper, app.SlashingKeeper,
)
evidenceRouter := evidence.NewRouter()
// TODO: Register evidence routes.
evidenceKeeper.SetRouter(evidenceRouter)
app.EvidenceKeeper = *evidenceKeeper
// register the proposal types
govRouter := gov.NewRouter()
govRouter.AddRoute(gov.RouterKey, gov.ProposalHandler).
AddRoute(params.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distr.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgrade.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
app.GovKeeper = gov.NewKeeper(
cdc, keys[gov.StoreKey], app.subspaces[gov.ModuleName], app.SupplyKeeper,
&stakingKeeper, govRouter,
) )
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath)
// register the staking hooks // register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks( app.StakingKeeper = *stakingKeeper.SetHooks(
staking.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
) )
// Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper,
)
// register the proposal types
govRouter := govtypes.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper))
app.GovKeeper = govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter,
)
// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
)
transferModule := transfer.NewAppModule(app.TransferKeeper)
// Create static IBC router, add transfer route, then set and seal it
ibcRouter := porttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule)
app.IBCKeeper.SetRouter(ibcRouter)
// create evidence keeper with router
evidenceKeeper := evidencekeeper.NewKeeper(
appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
)
// If evidence needs to be handled for the app, set routes in router here and seal
app.EvidenceKeeper = *evidenceKeeper
// Create Ethermint keepers
app.EvmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], app.GetSubspace(evmtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
)
/**** Module Options ****/
// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
// we prefer to be more strict in what arguments the modules expect.
var skipGenesisInvariants = cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants))
// NOTE: Any module instantiated in the module manager that is later modified // NOTE: Any module instantiated in the module manager that is later modified
// must be passed by reference here. // must be passed by reference here.
app.mm = module.NewManager( app.mm = module.NewManager(
genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx), // SDK app modules
auth.NewAppModule(app.AccountKeeper), genutil.NewAppModule(
bank.NewAppModule(app.BankKeeper, app.AccountKeeper), app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
crisis.NewAppModule(&app.CrisisKeeper), encodingConfig.TxConfig,
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper), ),
gov.NewAppModule(app.GovKeeper, app.AccountKeeper, app.SupplyKeeper), auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
mint.NewAppModule(app.MintKeeper), vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
slashing.NewAppModule(app.SlashingKeeper, app.AccountKeeper, app.StakingKeeper), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
distr.NewAppModule(app.DistrKeeper, app.AccountKeeper, app.SupplyKeeper, app.StakingKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper),
staking.NewAppModule(app.StakingKeeper, app.AccountKeeper, app.SupplyKeeper), crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
upgrade.NewAppModule(app.UpgradeKeeper),
evidence.NewAppModule(app.EvidenceKeeper), evidence.NewAppModule(app.EvidenceKeeper),
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper), ibc.NewAppModule(app.IBCKeeper),
params.NewAppModule(app.ParamsKeeper),
transferModule,
// Ethermint app modules
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper, app.BankKeeper),
) )
// During begin block slashing happens after distr.BeginBlocker so that // During begin block slashing happens after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool, so as to keep the // there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant. // CanWithdrawInvariant invariant.
// NOTE: upgrade module must go first to handle software upgrades.
// NOTE: staking module is required if HistoricalEntries param > 0.
app.mm.SetOrderBeginBlockers( app.mm.SetOrderBeginBlockers(
evm.ModuleName, mint.ModuleName, distr.ModuleName, slashing.ModuleName, upgradetypes.ModuleName,
evidence.ModuleName, evmtypes.ModuleName,
minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName,
) )
app.mm.SetOrderEndBlockers( app.mm.SetOrderEndBlockers(
evm.ModuleName, crisis.ModuleName, gov.ModuleName, staking.ModuleName, evmtypes.ModuleName,
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
) )
// NOTE: The genutils module must occur after staking so that pools are // NOTE: The genutils module must occur after staking so that pools are
// properly initialized with tokens from genesis accounts. // properly initialized with tokens from genesis accounts.
// NOTE: Capability module must occur first so that it can initialize any capabilities
// so that other modules that want to create or claim capabilities afterwards in InitChain
// can do so safely.
app.mm.SetOrderInitGenesis( app.mm.SetOrderInitGenesis(
auth.ModuleName, distr.ModuleName, staking.ModuleName, bank.ModuleName, // SDK modules
slashing.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName, capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName,
evm.ModuleName, crisis.ModuleName, genutil.ModuleName, evidence.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName,
ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName,
// Ethermint modules
evmtypes.ModuleName,
// NOTE: crisis module must go at the end to check for invariants on each module
crisistypes.ModuleName,
) )
app.mm.RegisterInvariants(&app.CrisisKeeper) app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter()) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()))
// add test gRPC service for testing gRPC queries in isolation
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
// create the simulation manager and define the order of the modules for deterministic simulations // create the simulation manager and define the order of the modules for deterministic simulations
// //
// NOTE: this is not required apps that don't use the simulator for fuzz testing // NOTE: this is not required apps that don't use the simulator for fuzz testing
// transactions // transactions
app.sm = module.NewSimulationManager( // app.sm = module.NewSimulationManager(
auth.NewAppModule(app.AccountKeeper), // auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
bank.NewAppModule(app.BankKeeper, app.AccountKeeper), // bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper), // capability.NewAppModule(appCodec, *app.CapabilityKeeper),
gov.NewAppModule(app.GovKeeper, app.AccountKeeper, app.SupplyKeeper), // gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(app.MintKeeper), // mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
staking.NewAppModule(app.StakingKeeper, app.AccountKeeper, app.SupplyKeeper), // staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
distr.NewAppModule(app.DistrKeeper, app.AccountKeeper, app.SupplyKeeper, app.StakingKeeper), // distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
slashing.NewAppModule(app.SlashingKeeper, app.AccountKeeper, app.StakingKeeper), // slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
params.NewAppModule(), // NOTE: only used for simulation to generate randomized param change proposals // params.NewAppModule(app.ParamsKeeper),
) // evidence.NewAppModule(app.EvidenceKeeper),
// ibc.NewAppModule(app.IBCKeeper),
// transferModule,
//)
app.sm.RegisterStoreDecoders() // app.sm.RegisterStoreDecoders()
// initialize stores // initialize stores
app.MountKVStores(keys) app.MountKVStores(keys)
app.MountTransientStores(tkeys) app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)
// initialize BaseApp // initialize BaseApp
app.SetInitChainer(app.InitChainer) app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker) app.SetBeginBlocker(app.BeginBlocker)
app.SetAnteHandler(ante.NewAnteHandler(app.AccountKeeper, app.EvmKeeper, app.SupplyKeeper))
// use Ethermint's custom AnteHandler
app.SetAnteHandler(
ante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, app.EvmKeeper,
encodingConfig.TxConfig.SignModeHandler(),
),
)
app.SetEndBlocker(app.EndBlocker) app.SetEndBlocker(app.EndBlocker)
if loadLatest { if loadLatest {
err := app.LoadLatestVersion(app.keys[bam.MainStoreKey]) if err := app.LoadLatestVersion(); err != nil {
if err != nil {
tmos.Exit(err.Error()) tmos.Exit(err.Error())
} }
// Initialize and seal the capability keeper so all persistent capabilities
// are loaded in-memory and prevent any further modules from creating scoped
// sub-keepers.
// This must be done during creation of baseapp rather than in InitChain so
// that in-memory capabilities get regenerated on app restart.
// Note that since this reads from the store, we can only perform it when
// `loadLatest` is set to true.
ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{})
app.CapabilityKeeper.InitializeAndSeal(ctx)
} }
app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
return app return app
} }
@ -332,38 +495,57 @@ func (app *EthermintApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) a
// InitChainer updates at chain initialization // InitChainer updates at chain initialization
func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
var genesisState simapp.GenesisState var genesisState simapp.GenesisState
app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState) if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
return app.mm.InitGenesis(ctx, genesisState) panic(err)
}
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
} }
// LoadHeight loads state at a particular height // LoadHeight loads state at a particular height
func (app *EthermintApp) LoadHeight(height int64) error { func (app *EthermintApp) LoadHeight(height int64) error {
return app.LoadVersion(height, app.keys[bam.MainStoreKey]) return app.LoadVersion(height)
} }
// ModuleAccountAddrs returns all the app's module account addresses. // ModuleAccountAddrs returns all the app's module account addresses.
func (app *EthermintApp) ModuleAccountAddrs() map[string]bool { func (app *EthermintApp) ModuleAccountAddrs() map[string]bool {
modAccAddrs := make(map[string]bool) modAccAddrs := make(map[string]bool)
for acc := range maccPerms { for acc := range maccPerms {
modAccAddrs[supply.NewModuleAddress(acc).String()] = true modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
} }
return modAccAddrs return modAccAddrs
} }
// BlacklistedAccAddrs returns all the app's module account addresses black listed for receiving tokens. // BlockedAddrs returns all the app's module account addresses that are not
func (app *EthermintApp) BlacklistedAccAddrs() map[string]bool { // allowed to receive external tokens.
blacklistedAddrs := make(map[string]bool) func (app *EthermintApp) BlockedAddrs() map[string]bool {
blockedAddrs := make(map[string]bool)
for acc := range maccPerms { for acc := range maccPerms {
blacklistedAddrs[supply.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc] blockedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc]
} }
return blacklistedAddrs return blockedAddrs
} }
// SimulationManager implements the SimulationApp interface // LegacyAmino returns EthermintApp's amino codec.
func (app *EthermintApp) SimulationManager() *module.SimulationManager { //
return app.sm // NOTE: This is solely to be used for testing purposes as it may be desirable
// for modules to register their own custom testing types.
func (app *EthermintApp) LegacyAmino() *codec.LegacyAmino {
return app.cdc
}
// AppCodec returns EthermintApp's app codec.
//
// NOTE: This is solely to be used for testing purposes as it may be desirable
// for modules to register their own custom testing types.
func (app *EthermintApp) AppCodec() codec.Marshaler {
return app.appCodec
}
// InterfaceRegistry returns EthermintApp's InterfaceRegistry
func (app *EthermintApp) InterfaceRegistry() types.InterfaceRegistry {
return app.interfaceRegistry
} }
// GetKey returns the KVStoreKey for the provided store key. // GetKey returns the KVStoreKey for the provided store key.
@ -373,12 +555,57 @@ func (app *EthermintApp) GetKey(storeKey string) *sdk.KVStoreKey {
return app.keys[storeKey] return app.keys[storeKey]
} }
// Codec returns Ethermint's codec. // GetTKey returns the TransientStoreKey for the provided store key.
// //
// NOTE: This is solely to be used for testing purposes as it may be desirable // NOTE: This is solely to be used for testing purposes.
// for modules to register their own custom testing types. func (app *EthermintApp) GetTKey(storeKey string) *sdk.TransientStoreKey {
func (app *EthermintApp) Codec() *codec.Codec { return app.tkeys[storeKey]
return app.cdc }
// GetMemKey returns the MemStoreKey for the provided mem key.
//
// NOTE: This is solely used for testing purposes.
func (app *EthermintApp) GetMemKey(storeKey string) *sdk.MemoryStoreKey {
return app.memKeys[storeKey]
}
// GetSubspace returns a param subspace for a given module name.
//
// NOTE: This is solely to be used for testing purposes.
func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
subspace, _ := app.ParamsKeeper.GetSubspace(moduleName)
return subspace
}
// SimulationManager implements the SimulationApp interface
// func (app *EthermintApp) SimulationManager() *module.SimulationManager {
// return app.sm
//}
// RegisterAPIRoutes registers all application module routes with the provided
// API server.
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *sdkapi.Server, apiConfig sdkconfig.APIConfig) {
clientCtx := apiSvr.ClientCtx
rpc.RegisterRoutes(clientCtx, apiSvr.Router)
evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router)
ModuleBasics.RegisterGRPCGatewayRoutes(apiSvr.ClientCtx, apiSvr.GRPCGatewayRouter)
// register swagger API from root so that other applications can override easily
if apiConfig.Swagger {
simapp.RegisterSwaggerAPI(clientCtx, apiSvr.Router)
}
}
// RegisterTxService implements the Application.RegisterTxService method.
func (app *EthermintApp) RegisterTxService(clientCtx client.Context) {
authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}
// RegisterTendermintService implements the Application.RegisterTendermintService method.
func (app *EthermintApp) RegisterTendermintService(clientCtx client.Context) {
tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry)
} }
// GetMaccPerms returns a copy of the module account permissions // GetMaccPerms returns a copy of the module account permissions
@ -390,3 +617,25 @@ func GetMaccPerms() map[string][]string {
return dupMaccPerms return dupMaccPerms
} }
// initParamsKeeper init params keeper and its subspaces
func initParamsKeeper(
appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper {
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
// SDK subspaces
paramsKeeper.Subspace(authtypes.ModuleName)
paramsKeeper.Subspace(banktypes.ModuleName)
paramsKeeper.Subspace(stakingtypes.ModuleName)
paramsKeeper.Subspace(minttypes.ModuleName)
paramsKeeper.Subspace(distrtypes.ModuleName)
paramsKeeper.Subspace(slashingtypes.ModuleName)
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
paramsKeeper.Subspace(ibchost.ModuleName)
// ethermint subspaces
paramsKeeper.Subspace(evmtypes.ModuleName)
return paramsKeeper
}

View File

@ -1,24 +1,25 @@
package app package app
import ( import (
"encoding/json"
"os" "os"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/simapp"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
) )
func TestEthermintAppExport(t *testing.T) { func TestEthermintAppExport(t *testing.T) {
db := dbm.NewMemDB() db := dbm.NewMemDB()
app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, 0) app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, MakeEncodingConfig(), simapp.EmptyAppOptions{})
genesisState := ModuleBasics.DefaultGenesis() genesisState := NewDefaultGenesisState()
stateBytes, err := codec.MarshalJSONIndent(app.cdc, genesisState) stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err) require.NoError(t, err)
// Initialize the chain // Initialize the chain
@ -31,7 +32,7 @@ func TestEthermintAppExport(t *testing.T) {
app.Commit() app.Commit()
// Making a new app object with the db, so that initchain hasn't been called // Making a new app object with the db, so that initchain hasn't been called
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, 0) app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, MakeEncodingConfig(), simapp.EmptyAppOptions{})
_, _, err = app2.ExportAppStateAndValidators(false, []string{}) _, err = app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error") require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
} }

View File

@ -2,70 +2,81 @@ package app
import ( import (
"encoding/json" "encoding/json"
"log" "fmt"
abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec" servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
"github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/staking/exported" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
ethcdc "github.com/cosmos/ethermint/codec"
) )
// NewDefaultGenesisState generates the default state for the application. // NewDefaultGenesisState generates the default state for the application.
func NewDefaultGenesisState() simapp.GenesisState { func NewDefaultGenesisState() simapp.GenesisState {
_ = ethcdc.MakeCodec(ModuleBasics) encCfg := MakeEncodingConfig()
return ModuleBasics.DefaultGenesis() return ModuleBasics.DefaultGenesis(encCfg.Marshaler)
} }
// ExportAppStateAndValidators exports the state of the application for a genesis // ExportAppStateAndValidators exports the state of the application for a genesis
// file. // file.
func (app *EthermintApp) ExportAppStateAndValidators( func (app *EthermintApp) ExportAppStateAndValidators(
forZeroHeight bool, jailWhiteList []string, forZeroHeight bool, jailAllowedAddrs []string,
) (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) { ) (servertypes.ExportedApp, error) {
// Creates context with current height and checks txs for ctx to be usable by start of next block // Creates context with current height and checks txs for ctx to be usable by start of next block
ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()})
// We export at last height + 1, because that's the height at which
// Tendermint will start InitChain.
height := app.LastBlockHeight() + 1
if forZeroHeight { if forZeroHeight {
app.prepForZeroHeightGenesis(ctx, jailWhiteList) height = 0
if err := app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs); err != nil {
return servertypes.ExportedApp{}, err
}
} }
// Export genesis to be used by SDK modules genState := app.mm.ExportGenesis(ctx, app.appCodec)
genState := app.mm.ExportGenesis(ctx) appState, err := json.MarshalIndent(genState, "", " ")
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
if err != nil { if err != nil {
return nil, nil, err return servertypes.ExportedApp{}, err
} }
// Write validators to staking module to be used by TM node validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
validators = staking.WriteValidators(ctx, app.StakingKeeper) if err != nil {
return appState, validators, nil return servertypes.ExportedApp{}, err
}
return servertypes.ExportedApp{
AppState: appState,
Validators: validators,
Height: height,
ConsensusParams: app.BaseApp.GetConsensusParams(ctx),
}, nil
} }
// prepare for fresh start at zero height // prepare for fresh start at zero height
// NOTE zero height genesis is a temporary feature which will be deprecated // NOTE zero height genesis is a temporary feature which will be deprecated
// in favour of export at a block height // in favour of export at a block height
func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) { func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) error {
applyWhiteList := false applyAllowedAddrs := false
//Check if there is a whitelist // check if there is a allowed address list
if len(jailWhiteList) > 0 { if len(jailAllowedAddrs) > 0 {
applyWhiteList = true applyAllowedAddrs = true
} }
whiteListMap := make(map[string]bool) allowedAddrsMap := make(map[string]bool)
for _, addr := range jailWhiteList { for _, addr := range jailAllowedAddrs {
_, err := sdk.ValAddressFromBech32(addr) _, err := sdk.ValAddressFromBech32(addr)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
whiteListMap[addr] = true allowedAddrsMap[addr] = true
} }
/* Just to be safe, assert the invariants on current state. */ /* Just to be safe, assert the invariants on current state. */
@ -74,7 +85,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
/* Handle fee distribution state. */ /* Handle fee distribution state. */
// withdraw all validator commission // withdraw all validator commission
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val exported.ValidatorI) (stop bool) { app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
_, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator()) _, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator())
return false return false
}) })
@ -82,7 +93,16 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
// withdraw all delegator rewards // withdraw all delegator rewards
dels := app.StakingKeeper.GetAllDelegations(ctx) dels := app.StakingKeeper.GetAllDelegations(ctx)
for _, delegation := range dels { for _, delegation := range dels {
_, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress) valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress)
if err != nil {
return err
}
delAddr, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress)
if err != nil {
return err
}
_, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr)
} }
// clear validator slash events // clear validator slash events
@ -96,7 +116,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
ctx = ctx.WithBlockHeight(0) ctx = ctx.WithBlockHeight(0)
// reinitialize all validators // reinitialize all validators
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val exported.ValidatorI) (stop bool) { app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
// donate any unwithdrawn outstanding reward fraction tokens to the community pool // donate any unwithdrawn outstanding reward fraction tokens to the community pool
scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator()) scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator())
feePool := app.DistrKeeper.GetFeePool(ctx) feePool := app.DistrKeeper.GetFeePool(ctx)
@ -109,8 +129,16 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
// reinitialize all delegations // reinitialize all delegations
for _, del := range dels { for _, del := range dels {
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, del.DelegatorAddress, del.ValidatorAddress) valAddr, err := sdk.ValAddressFromBech32(del.ValidatorAddress)
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, del.DelegatorAddress, del.ValidatorAddress) if err != nil {
return err
}
delAddr, err := sdk.AccAddressFromBech32(del.DelegatorAddress)
if err != nil {
return err
}
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr)
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr)
} }
// reset context height // reset context height
@ -119,7 +147,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
/* Handle staking state. */ /* Handle staking state. */
// iterate through redelegations, reset creation height // iterate through redelegations, reset creation height
app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red staking.Redelegation) (stop bool) { app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) {
for i := range red.Entries { for i := range red.Entries {
red.Entries[i].CreationHeight = 0 red.Entries[i].CreationHeight = 0
} }
@ -128,7 +156,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
}) })
// iterate through unbonding delegations, reset creation height // iterate through unbonding delegations, reset creation height
app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd staking.UnbondingDelegation) (stop bool) { app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) {
for i := range ubd.Entries { for i := range ubd.Entries {
ubd.Entries[i].CreationHeight = 0 ubd.Entries[i].CreationHeight = 0
} }
@ -138,19 +166,19 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
// Iterate through validators by power descending, reset bond heights, and // Iterate through validators by power descending, reset bond heights, and
// update bond intra-tx counters. // update bond intra-tx counters.
store := ctx.KVStore(app.keys[staking.StoreKey]) store := ctx.KVStore(app.keys[stakingtypes.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, staking.ValidatorsKey) iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
counter := int16(0) counter := int16(0)
for ; iter.Valid(); iter.Next() { for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(iter.Key()[1:]) addr := sdk.ValAddress(iter.Key()[1:])
validator, found := app.StakingKeeper.GetValidator(ctx, addr) validator, found := app.StakingKeeper.GetValidator(ctx, addr)
if !found { if !found {
panic("expected validator, not found") return fmt.Errorf("expected validator %s not found", addr)
} }
validator.UnbondingHeight = 0 validator.UnbondingHeight = 0
if applyWhiteList && !whiteListMap[addr.String()] { if applyAllowedAddrs && !allowedAddrsMap[addr.String()] {
validator.Jailed = true validator.Jailed = true
} }
@ -160,17 +188,20 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
iter.Close() iter.Close()
_ = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil {
return err
}
/* Handle slashing state. */ /* Handle slashing state. */
// reset start height on signing infos // reset start height on signing infos
app.SlashingKeeper.IterateValidatorSigningInfos( app.SlashingKeeper.IterateValidatorSigningInfos(
ctx, ctx,
func(addr sdk.ConsAddress, info slashing.ValidatorSigningInfo) (stop bool) { func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) {
info.StartHeight = 0 info.StartHeight = 0
app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info) app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
return false return false
}, },
) )
return nil
} }

View File

@ -1,296 +1,340 @@
package app package app
import ( // disable for now, enable it once SDK side fix the simulator issue for custom keys
"encoding/json" //import (
"fmt" // "encoding/json"
"math/rand" // "fmt"
"os" // "math/rand"
"testing" // "os"
// "testing"
"github.com/stretchr/testify/require" //
// "github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types" //
"github.com/tendermint/tendermint/libs/log" // abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tm-db" // "github.com/tendermint/tendermint/libs/log"
// tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/baseapp" // dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/simapp" //
"github.com/cosmos/cosmos-sdk/simapp/helpers" // "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/store" // "github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types" // "github.com/cosmos/cosmos-sdk/simapp/helpers"
"github.com/cosmos/cosmos-sdk/x/auth" // "github.com/cosmos/cosmos-sdk/store"
distr "github.com/cosmos/cosmos-sdk/x/distribution" // sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov" // simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/cosmos/cosmos-sdk/x/mint" // authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/params" // banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/simulation" // capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
"github.com/cosmos/cosmos-sdk/x/slashing" // distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/staking" // evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
"github.com/cosmos/cosmos-sdk/x/supply" // govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
) // ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
// ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host"
func init() { // minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
simapp.GetSimulatorFlags() // paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
} // "github.com/cosmos/cosmos-sdk/x/simulation"
// slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
type storeKeysPrefixes struct { // stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
A sdk.StoreKey //)
B sdk.StoreKey //
Prefixes [][]byte //func init() {
} // simapp.GetSimulatorFlags()
//}
// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of //
// an IAVLStore for faster simulation speed. //type storeKeysPrefixes struct {
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { // A sdk.StoreKey
bapp.SetFauxMerkleMode() // B sdk.StoreKey
} // Prefixes [][]byte
//}
// interBlockCacheOpt returns a BaseApp option function that sets the persistent //
// inter-block write-through cache. //// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
func interBlockCacheOpt() func(*baseapp.BaseApp) { //// an IAVLStore for faster simulation speed.
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) //func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
} // bapp.SetFauxMerkleMode()
//}
func TestFullAppSimulation(t *testing.T) { //
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") //// interBlockCacheOpt returns a BaseApp option function that sets the persistent
if skip { //// inter-block write-through cache.
t.Skip("skipping application simulation") //func interBlockCacheOpt() func(*baseapp.BaseApp) {
} // return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
require.NoError(t, err, "simulation setup failed") //}
//
defer func() { //func TestFullAppSimulation(t *testing.T) {
db.Close() // config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
require.NoError(t, os.RemoveAll(dir)) // if skip {
}() // t.Skip("skipping application simulation")
// }
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt) // require.NoError(t, err, "simulation setup failed")
require.Equal(t, appName, app.Name()) //
// defer func() {
// run randomized simulation // db.Close()
_, simParams, simErr := simulation.SimulateFromSeed( // require.NoError(t, os.RemoveAll(dir))
t, os.Stdout, app.BaseApp, simapp.AppStateFn(app.Codec(), app.SimulationManager()), // }()
simapp.SimulationOperations(app, app.Codec(), config), //
app.ModuleAccountAddrs(), config, // app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
) // require.Equal(t, appName, app.Name())
//
// export state and simParams before the simulation error is checked // // run randomized simulation
err = simapp.CheckExportSimulation(app, config, simParams) // _, simParams, simErr := simulation.SimulateFromSeed(
require.NoError(t, err) // t,
require.NoError(t, simErr) // os.Stdout,
// app.BaseApp,
if config.Commit { // simapp.AppStateFn(app.AppCodec(), app.SimulationManager()),
simapp.PrintStats(db) // simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
} // simapp.SimulationOperations(app, app.AppCodec(), config),
} // app.ModuleAccountAddrs(),
// config,
func TestAppImportExport(t *testing.T) { // app.AppCodec(),
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") // )
if skip { //
t.Skip("skipping application import/export simulation") // // export state and simParams before the simulation error is checked
} // err = simapp.CheckExportSimulation(app, config, simParams)
require.NoError(t, err, "simulation setup failed") // require.NoError(t, err)
// require.NoError(t, simErr)
defer func() { //
db.Close() // if config.Commit {
require.NoError(t, os.RemoveAll(dir)) // simapp.PrintStats(db)
}() // }
//}
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt) //
require.Equal(t, appName, app.Name()) //func TestAppImportExport(t *testing.T) {
// config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
// Run randomized simulation // if skip {
_, simParams, simErr := simulation.SimulateFromSeed( // t.Skip("skipping application import/export simulation")
t, os.Stdout, app.BaseApp, simapp.AppStateFn(app.Codec(), app.SimulationManager()), // }
simapp.SimulationOperations(app, app.Codec(), config), // require.NoError(t, err, "simulation setup failed")
app.ModuleAccountAddrs(), config, //
) // defer func() {
// db.Close()
// export state and simParams before the simulation error is checked // require.NoError(t, os.RemoveAll(dir))
err = simapp.CheckExportSimulation(app, config, simParams) // }()
require.NoError(t, err) //
require.NoError(t, simErr) // app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
// require.Equal(t, appName, app.Name())
if config.Commit { //
simapp.PrintStats(db) // // Run randomized simulation
} // _, simParams, simErr := simulation.SimulateFromSeed(
// t,
fmt.Printf("exporting genesis...\n") // os.Stdout,
// app.BaseApp,
appState, _, err := app.ExportAppStateAndValidators(false, []string{}) // simapp.AppStateFn(app.AppCodec(), app.SimulationManager()),
require.NoError(t, err) // simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
// simapp.SimulationOperations(app, app.AppCodec(), config),
fmt.Printf("importing genesis...\n") // app.ModuleAccountAddrs(),
// config,
// nolint: dogsled // app.AppCodec(),
_, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2") // )
require.NoError(t, err, "simulation setup failed") //
// // export state and simParams before the simulation error is checked
defer func() { // err = simapp.CheckExportSimulation(app, config, simParams)
newDB.Close() // require.NoError(t, err)
require.NoError(t, os.RemoveAll(newDir)) // require.NoError(t, simErr)
}() //
// if config.Commit {
newApp := NewEthermintApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt) // simapp.PrintStats(db)
require.Equal(t, appName, newApp.Name()) // }
//
var genesisState map[string]json.RawMessage // fmt.Printf("exporting genesis...\n")
err = app.Codec().UnmarshalJSON(appState, &genesisState) //
require.NoError(t, err) // exported, err := app.ExportAppStateAndValidators(false, []string{})
// require.NoError(t, err)
ctxA := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) //
ctxB := newApp.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) // fmt.Printf("importing genesis...\n")
newApp.mm.InitGenesis(ctxB, genesisState) //
// // nolint: dogsled
fmt.Printf("comparing stores...\n") // _, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2")
// require.NoError(t, err, "simulation setup failed")
storeKeysPrefixes := []storeKeysPrefixes{ //
{app.keys[baseapp.MainStoreKey], newApp.keys[baseapp.MainStoreKey], [][]byte{}}, // defer func() {
{app.keys[auth.StoreKey], newApp.keys[auth.StoreKey], [][]byte{}}, // newDB.Close()
{app.keys[staking.StoreKey], newApp.keys[staking.StoreKey], // require.NoError(t, os.RemoveAll(newDir))
[][]byte{ // }()
staking.UnbondingQueueKey, staking.RedelegationQueueKey, staking.ValidatorQueueKey, //
staking.HistoricalInfoKey, // newApp := NewEthermintApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
}}, // ordering may change but it doesn't matter // require.Equal(t, appName, newApp.Name())
{app.keys[slashing.StoreKey], newApp.keys[slashing.StoreKey], [][]byte{}}, //
{app.keys[mint.StoreKey], newApp.keys[mint.StoreKey], [][]byte{}}, // var genesisState simapp.GenesisState
{app.keys[distr.StoreKey], newApp.keys[distr.StoreKey], [][]byte{}}, // err = json.Unmarshal(exported.AppState, &genesisState)
{app.keys[supply.StoreKey], newApp.keys[supply.StoreKey], [][]byte{}}, // require.NoError(t, err)
{app.keys[params.StoreKey], newApp.keys[params.StoreKey], [][]byte{}}, //
{app.keys[gov.StoreKey], newApp.keys[gov.StoreKey], [][]byte{}}, // ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()})
} // ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()})
// newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState)
for _, skp := range storeKeysPrefixes { // newApp.StoreConsensusParams(ctxB, exported.ConsensusParams)
storeA := ctxA.KVStore(skp.A) //
storeB := ctxB.KVStore(skp.B) // fmt.Printf("comparing stores...\n")
//
failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes) // storeKeysPrefixes := []storeKeysPrefixes{
require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare") // {app.keys[authtypes.StoreKey], newApp.keys[authtypes.StoreKey], [][]byte{}},
// {app.keys[stakingtypes.StoreKey], newApp.keys[stakingtypes.StoreKey],
fmt.Printf("compared %d key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B) // [][]byte{
require.Equal(t, len(failedKVAs), 0, simapp.GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, app.Codec(), failedKVAs, failedKVBs)) // stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey,
} // stakingtypes.HistoricalInfoKey,
} // }}, // ordering may change but it doesn't matter
// {app.keys[slashingtypes.StoreKey], newApp.keys[slashingtypes.StoreKey], [][]byte{}},
func TestAppSimulationAfterImport(t *testing.T) { // {app.keys[minttypes.StoreKey], newApp.keys[minttypes.StoreKey], [][]byte{}},
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation") // {app.keys[distrtypes.StoreKey], newApp.keys[distrtypes.StoreKey], [][]byte{}},
if skip { // {app.keys[banktypes.StoreKey], newApp.keys[banktypes.StoreKey], [][]byte{banktypes.BalancesPrefix}},
t.Skip("skipping application simulation after import") // {app.keys[paramtypes.StoreKey], newApp.keys[paramtypes.StoreKey], [][]byte{}},
} // {app.keys[govtypes.StoreKey], newApp.keys[govtypes.StoreKey], [][]byte{}},
require.NoError(t, err, "simulation setup failed") // {app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}},
// {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}},
defer func() { // {app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}},
db.Close() // {app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}},
require.NoError(t, os.RemoveAll(dir)) // }
}() //
// for _, skp := range storeKeysPrefixes {
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt) // storeA := ctxA.KVStore(skp.A)
require.Equal(t, appName, app.Name()) // storeB := ctxB.KVStore(skp.B)
//
// Run randomized simulation // failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes)
stopEarly, simParams, simErr := simulation.SimulateFromSeed( // require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare")
t, os.Stdout, app.BaseApp, simapp.AppStateFn(app.Codec(), app.SimulationManager()), //
simapp.SimulationOperations(app, app.Codec(), config), // fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B)
app.ModuleAccountAddrs(), config, // require.Equal(t, len(failedKVAs), 0, simapp.GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs))
) // }
//}
// export state and simParams before the simulation error is checked //
err = simapp.CheckExportSimulation(app, config, simParams) //func TestAppSimulationAfterImport(t *testing.T) {
require.NoError(t, err) // config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
require.NoError(t, simErr) // if skip {
// t.Skip("skipping application simulation after import")
if config.Commit { // }
simapp.PrintStats(db) // require.NoError(t, err, "simulation setup failed")
} //
// defer func() {
if stopEarly { // db.Close()
fmt.Println("can't export or import a zero-validator genesis, exiting test...") // require.NoError(t, os.RemoveAll(dir))
return // }()
} //
// app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
fmt.Printf("exporting genesis...\n") // require.Equal(t, appName, app.Name())
//
appState, _, err := app.ExportAppStateAndValidators(true, []string{}) // // Run randomized simulation
require.NoError(t, err) // stopEarly, simParams, simErr := simulation.SimulateFromSeed(
// t,
fmt.Printf("importing genesis...\n") // os.Stdout,
// app.BaseApp,
// nolint: dosgsled // simapp.AppStateFn(app.AppCodec(), app.SimulationManager()),
_, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2") // simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
require.NoError(t, err, "simulation setup failed") // simapp.SimulationOperations(app, app.AppCodec(), config),
// app.ModuleAccountAddrs(),
defer func() { // config,
newDB.Close() // app.AppCodec(),
require.NoError(t, os.RemoveAll(newDir)) // )
}() //
// // export state and simParams before the simulation error is checked
newApp := NewEthermintApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, fauxMerkleModeOpt) // err = simapp.CheckExportSimulation(app, config, simParams)
require.Equal(t, appName, newApp.Name()) // require.NoError(t, err)
// require.NoError(t, simErr)
newApp.InitChain(abci.RequestInitChain{ //
AppStateBytes: appState, // if config.Commit {
}) // simapp.PrintStats(db)
// }
_, _, err = simulation.SimulateFromSeed( //
t, os.Stdout, newApp.BaseApp, simapp.AppStateFn(app.Codec(), app.SimulationManager()), // if stopEarly {
simapp.SimulationOperations(newApp, newApp.Codec(), config), // fmt.Println("can't export or import a zero-validator genesis, exiting test...")
newApp.ModuleAccountAddrs(), config, // return
) // }
require.NoError(t, err) //
} // fmt.Printf("exporting genesis...\n")
//
func TestAppStateDeterminism(t *testing.T) { // exported, err := app.ExportAppStateAndValidators(true, []string{})
if !simapp.FlagEnabledValue { // require.NoError(t, err)
t.Skip("skipping application simulation") //
} // fmt.Printf("importing genesis...\n")
//
config := simapp.NewConfigFromFlags() // _, newDB, newDir, _, _, err := simapp.SetupSimulation("leveldb-app-sim-2", "Simulation-2")
config.InitialBlockHeight = 1 // require.NoError(t, err, "simulation setup failed")
config.ExportParamsPath = "" //
config.OnOperation = false // defer func() {
config.AllInvariants = false // newDB.Close()
config.ChainID = helpers.SimAppChainID // require.NoError(t, os.RemoveAll(newDir))
// }()
numTimesToRunPerSeed := 2 //
appHashList := make([]json.RawMessage, numTimesToRunPerSeed) // newApp := NewEthermintApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
// require.Equal(t, appName, newApp.Name())
config.Seed = rand.Int63() //
// newApp.InitChain(abci.RequestInitChain{
for i := 0; i < numTimesToRunPerSeed; i++ { // AppStateBytes: exported.AppState,
var logger log.Logger // })
if simapp.FlagVerboseValue { //
logger = log.TestingLogger() // _, _, err = simulation.SimulateFromSeed(
} else { // t,
logger = log.NewNopLogger() // os.Stdout,
} // newApp.BaseApp,
// simapp.AppStateFn(app.AppCodec(), app.SimulationManager()),
db := dbm.NewMemDB() // simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
// simapp.SimulationOperations(newApp, newApp.AppCodec(), config),
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, simapp.FlagPeriodValue, interBlockCacheOpt()) // app.ModuleAccountAddrs(),
// config,
fmt.Printf( // app.AppCodec(),
"running non-determinism simulation; seed %d: attempt: %d/%d\n", // )
config.Seed, i+1, numTimesToRunPerSeed, // require.NoError(t, err)
) //}
//
_, _, err := simulation.SimulateFromSeed( //// TODO: Make another test for the fuzzer itself, which just has noOp txs
t, os.Stdout, app.BaseApp, simapp.AppStateFn(app.Codec(), app.SimulationManager()), //// and doesn't depend on the application.
simapp.SimulationOperations(app, app.Codec(), config), //func TestAppStateDeterminism(t *testing.T) {
app.ModuleAccountAddrs(), config, // if !simapp.FlagEnabledValue {
) // t.Skip("skipping application simulation")
require.NoError(t, err) // }
//
if config.Commit { // config := simapp.NewConfigFromFlags()
simapp.PrintStats(db) // config.InitialBlockHeight = 1
} // config.ExportParamsPath = ""
// config.OnOperation = false
appHash := app.LastCommitID().Hash // config.AllInvariants = false
appHashList[i] = appHash // config.ChainID = helpers.SimAppChainID
//
if i != 0 { // numSeeds := 3
require.Equal( // numTimesToRunPerSeed := 5
t, appHashList[0], appHashList[i], // appHashList := make([]json.RawMessage, numTimesToRunPerSeed)
"non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numTimesToRunPerSeed, //
) // for i := 0; i < numSeeds; i++ {
} // config.Seed = rand.Int63()
} //
} // for j := 0; j < numTimesToRunPerSeed; j++ {
// var logger log.Logger
// if simapp.FlagVerboseValue {
// logger = log.TestingLogger()
// } else {
// logger = log.NewNopLogger()
// }
//
// db := dbm.NewMemDB()
// app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, interBlockCacheOpt())
//
// fmt.Printf(
// "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n",
// config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
// )
//
// _, _, err := simulation.SimulateFromSeed(
// t,
// os.Stdout,
// app.BaseApp,
// simapp.AppStateFn(app.AppCodec(), app.SimulationManager()),
// simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
// simapp.SimulationOperations(app, app.AppCodec(), config),
// app.ModuleAccountAddrs(),
// config,
// app.AppCodec(),
// )
// require.NoError(t, err)
//
// if config.Commit {
// simapp.PrintStats(db)
// }
//
// appHash := app.LastCommitID().Hash
// appHashList[j] = appHash
//
// if j != 0 {
// require.Equal(
// t, string(appHashList[0]), string(appHashList[j]),
// "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
// )
// }
// }
// }
//}

View File

@ -1,22 +1,45 @@
package app package app
import ( import (
"encoding/json"
"time"
"github.com/cosmos/cosmos-sdk/simapp"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
) )
// DefaultConsensusParams defines the default Tendermint consensus params used in
// EthermintApp testing.
var DefaultConsensusParams = &abci.ConsensusParams{
Block: &abci.BlockParams{
MaxBytes: 200000,
MaxGas: -1, // no limit
},
Evidence: &tmproto.EvidenceParams{
MaxAgeNumBlocks: 302400,
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
MaxBytes: 10000,
},
Validator: &tmproto.ValidatorParams{
PubKeyTypes: []string{
tmtypes.ABCIPubKeyTypeEd25519,
},
},
}
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp. // Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
func Setup(isCheckTx bool) *EthermintApp { func Setup(isCheckTx bool) *EthermintApp {
db := dbm.NewMemDB() db := dbm.NewMemDB()
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, 0) app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, MakeEncodingConfig(), simapp.EmptyAppOptions{})
if !isCheckTx { if !isCheckTx {
// init chain must be called to stop deliverState from being nil // init chain must be called to stop deliverState from being nil
genesisState := NewDefaultGenesisState() genesisState := NewDefaultGenesisState()
stateBytes, err := codec.MarshalJSONIndent(app.Codec(), genesisState) stateBytes, err := json.MarshalIndent(genesisState, "", " ")
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -24,8 +47,9 @@ func Setup(isCheckTx bool) *EthermintApp {
// Initialize the chain // Initialize the chain
app.InitChain( app.InitChain(
abci.RequestInitChain{ abci.RequestInitChain{
Validators: []abci.ValidatorUpdate{}, Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes, ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
}, },
) )
} }

View File

@ -49,7 +49,7 @@ func ValidateChainID(baseCmd *cobra.Command) *cobra.Command {
// Function to replace command's RunE function // Function to replace command's RunE function
validateFn := func(cmd *cobra.Command, args []string) error { validateFn := func(cmd *cobra.Command, args []string) error {
chainID := viper.GetString(flags.FlagChainID) chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
if !ethermint.IsValidChainID(chainID) { if !ethermint.IsValidChainID(chainID) {
return fmt.Errorf("invalid chain-id format: %s", chainID) return fmt.Errorf("invalid chain-id format: %s", chainID)
@ -70,10 +70,12 @@ func GenerateChainID(baseCmd *cobra.Command) *cobra.Command {
// Function to replace command's RunE function // Function to replace command's RunE function
generateFn := func(cmd *cobra.Command, args []string) error { generateFn := func(cmd *cobra.Command, args []string) error {
chainID := viper.GetString(flags.FlagChainID) chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
if chainID == "" { if chainID == "" {
viper.Set(flags.FlagChainID, ethermint.GenerateRandomChainID()) if err := cmd.Flags().Set(flags.FlagChainID, ethermint.GenerateRandomChainID()); err != nil {
return fmt.Errorf("could not set random chain-id: %v", err)
}
} }
return baseRunE(cmd, args) return baseRunE(cmd, args)
} }

View File

@ -6,15 +6,16 @@ import (
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
ethcrypto "github.com/ethereum/go-ethereum/crypto" ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" "github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/crypto/hd" "github.com/cosmos/ethermint/crypto/hd"
) )
@ -29,12 +30,15 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin()) inBuf := bufio.NewReader(cmd.InOrStdin())
kb, err := keys.NewKeyring( keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
kr, err := keyring.New(
sdk.KeyringServiceName(), sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend), keyringBackend,
viper.GetString(flags.FlagHome), rootDir,
inBuf, inBuf,
hd.EthSecp256k1Options()..., hd.EthSecp256k1Option(),
) )
if err != nil { if err != nil {
return err return err
@ -42,35 +46,44 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
decryptPassword := "" decryptPassword := ""
conf := true conf := true
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
switch keyringBackend { switch keyringBackend {
case keys.BackendFile: case keyring.BackendFile:
decryptPassword, err = input.GetPassword( decryptPassword, err = input.GetPassword(
"**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:", "**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:",
inBuf) inBuf)
case keys.BackendOS: case keyring.BackendOS:
conf, err = input.GetConfirmation( conf, err = input.GetConfirmation(
"**WARNING** this is an unsafe way to export your unencrypted private key, are you sure?", "**WARNING** this is an unsafe way to export your unencrypted private key, are you sure?",
inBuf) inBuf, cmd.ErrOrStderr())
} }
if err != nil || !conf { if err != nil || !conf {
return err return err
} }
// Exports private key from keybase using password // Exports private key from keybase using password
privKey, err := kb.ExportPrivateKeyObject(args[0], decryptPassword) armor, err := kr.ExportPrivKeyArmor(args[0], decryptPassword)
if err != nil { if err != nil {
return err return err
} }
privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, decryptPassword)
if err != nil {
return err
}
if algo != ethsecp256k1.KeyType {
return fmt.Errorf("invalid key algorithm, got %s, expected %s", algo, ethsecp256k1.KeyType)
}
// Converts key to Ethermint secp256 implementation // Converts key to Ethermint secp256 implementation
emintKey, ok := privKey.(ethsecp256k1.PrivKey) ethermintPrivKey, ok := privKey.(*ethsecp256k1.PrivKey)
if !ok { if !ok {
return fmt.Errorf("invalid private key type, must be Ethereum key: %T", privKey) return fmt.Errorf("invalid private key type %T, expected %T", privKey, &ethsecp256k1.PrivKey{})
} }
// Formats key for output // Formats key for output
privB := ethcrypto.FromECDSA(emintKey.ToECDSA()) privB := ethcrypto.FromECDSA(ethermintPrivKey.ToECDSA())
keyS := strings.ToUpper(hexutil.Encode(privB)[2:]) keyS := strings.ToUpper(hexutil.Encode(privB)[2:])
fmt.Println(keyS) fmt.Println(keyS)

View File

@ -1,88 +0,0 @@
package client
import (
"bufio"
"io"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client/flags"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/crypto/hd"
)
const (
flagDryRun = "dry-run"
)
// KeyCommands registers a sub-tree of commands to interact with
// local private key storage.
func KeyCommands() *cobra.Command {
cmd := &cobra.Command{
Use: "keys",
Short: "Add or view local private keys",
Long: `Keys allows you to manage your local keystore for tendermint.
These keys may be in any format supported by go-crypto and can be
used by light-clients, full nodes, or any other application that
needs to sign with a private key.`,
}
// support adding Ethereum supported keys
addCmd := clientkeys.AddKeyCommand()
// update the default signing algorithm value to "eth_secp256k1"
algoFlag := addCmd.Flag("algo")
algoFlag.DefValue = string(hd.EthSecp256k1)
err := algoFlag.Value.Set(string(hd.EthSecp256k1))
if err != nil {
panic(err)
}
addCmd.RunE = runAddCmd
cmd.AddCommand(
clientkeys.MnemonicKeyCommand(),
addCmd,
clientkeys.ExportKeyCommand(),
clientkeys.ImportKeyCommand(),
clientkeys.ListKeysCmd(),
clientkeys.ShowKeysCmd(),
flags.LineBreak,
clientkeys.DeleteKeyCommand(),
clientkeys.ParseKeyStringCommand(),
clientkeys.MigrateCommand(),
flags.LineBreak,
UnsafeExportEthKeyCommand(),
)
return cmd
}
func runAddCmd(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
kb, err := getKeybase(viper.GetBool(flagDryRun), inBuf)
if err != nil {
return err
}
return clientkeys.RunAddCmd(cmd, args, kb, inBuf)
}
func getKeybase(transient bool, buf io.Reader) (keys.Keybase, error) {
if transient {
return keys.NewInMemory(
hd.EthSecp256k1Options()...,
), nil
}
return keys.NewKeyring(
sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend),
viper.GetString(flags.FlagHome),
buf,
hd.EthSecp256k1Options()...,
)
}

61
client/keys/keys.go Normal file
View File

@ -0,0 +1,61 @@
package keys
import (
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/keys"
)
// Commands registers a sub-tree of commands to interact with
// local private key storage.
func Commands(defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "keys",
Short: "Manage your application's keys",
Long: `Keyring management commands. These keys may be in any format supported by the
Tendermint crypto library and can be used by light-clients, full nodes, or any other application
that needs to sign with a private key.
The keyring supports the following backends:
os Uses the operating system's default credentials store.
file Uses encrypted file-based keystore within the app's configuration directory.
This keyring will request a password each time it is accessed, which may occur
multiple times in a single command resulting in repeated password prompts.
kwallet Uses KDE Wallet Manager as a credentials management application.
pass Uses the pass command line utility to store and retrieve keys.
test Stores keys insecurely to disk. It does not prompt for a password to be unlocked
and it should be use only for testing purposes.
kwallet and pass backends depend on external tools. Refer to their respective documentation for more
information:
KWallet https://github.com/KDE/kwallet
pass https://www.passwordstore.org/
The pass backend requires GnuPG: https://gnupg.org/
`,
}
cmd.AddCommand(
keys.MnemonicKeyCommand(),
AddKeyCommand(),
keys.ExportKeyCommand(),
keys.ImportKeyCommand(),
keys.ListKeysCmd(),
keys.ShowKeysCmd(),
flags.LineBreak,
keys.DeleteKeyCommand(),
keys.ParseKeyStringCommand(),
keys.MigrateCommand(),
)
cmd.PersistentFlags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
cmd.PersistentFlags().String(flags.FlagKeyringDir, "", "The client Keyring directory; if omitted, the default 'home' directory will be used")
cmd.PersistentFlags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.PersistentFlags().String(cli.OutputFlag, "text", "Output format (text|json)")
return cmd
}

358
client/keys/keysadd.go Normal file
View File

@ -0,0 +1,358 @@
package keys
import (
"bufio"
"bytes"
"errors"
"fmt"
"sort"
ethermintHd "github.com/cosmos/ethermint/crypto/hd"
bip39 "github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
const (
flagInteractive = "interactive"
flagRecover = "recover"
flagNoBackup = "no-backup"
flagCoinType = "coin-type"
flagAccount = "account"
flagIndex = "index"
flagMultisig = "multisig"
flagNoSort = "nosort"
flagHDPath = "hd-path"
// repeat var client/keys/show.go unexported
flagMultiSigThreshold = "multisig-threshold"
// repeat of client/keys/mnemonic.go unexported
mnemonicEntropySize = 256
// DefaultKeyPass contains the default key password for genesis transactions
DefaultKeyPass = "12345678"
)
// AddKeyCommand defines a keys command to add a generated or recovered private key to keybase.
func AddKeyCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "add <name>",
Short: "Add an encrypted private key (either newly generated or recovered), encrypt it, and save to disk",
Long: `Derive a new private key and encrypt to disk.
Optionally specify a BIP39 mnemonic, a BIP39 passphrase to further secure the mnemonic,
and a bip32 HD path to derive a specific account. The key will be stored under the given name
and encrypted with the given password. The only input that is required is the encryption password.
If run with -i, it will prompt the user for BIP44 path, BIP39 mnemonic, and passphrase.
The flag --recover allows one to recover a key from a seed passphrase.
If run with --dry-run, a key would be generated (or recovered) but not stored to the
local keystore.
Use the --pubkey flag to add arbitrary public keys to the keystore for constructing
multisig transactions.
You can add a multisig key by passing the list of key names you want the public
key to be composed of to the --multisig flag and the minimum number of signatures
required through --multisig-threshold. The keys are sorted by address, unless
the flag --nosort is set.
`,
Args: cobra.ExactArgs(1),
RunE: runAddCmd,
}
cmd.Flags().StringSlice(flagMultisig, nil, "Construct and store a multisig public key (implies --pubkey)")
cmd.Flags().Int(flagMultiSigThreshold, 1, "K out of N required signatures. For use in conjunction with --multisig")
cmd.Flags().Bool(flagNoSort, false, "Keys passed to --multisig are taken in the order they're supplied")
cmd.Flags().String(keys.FlagPublicKey, "", "Parse a public key in bech32 format and save it to disk")
cmd.Flags().BoolP(flagInteractive, "i", false, "Interactively prompt user for BIP39 passphrase and mnemonic")
cmd.Flags().Bool(flags.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device")
cmd.Flags().Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating")
cmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)")
cmd.Flags().Bool(flags.FlagDryRun, false, "Perform action, but don't add key to local keystore")
cmd.Flags().String(flagHDPath, "", "Manual HD Path derivation (overrides BIP44 config)")
cmd.Flags().Uint32(flagCoinType, sdk.GetConfig().GetCoinType(), "coin type number for HD derivation")
cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation")
cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation")
cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
cmd.SetOut(cmd.OutOrStdout())
cmd.SetErr(cmd.ErrOrStderr())
return cmd
}
func runAddCmd(cmd *cobra.Command, args []string) error {
buf := bufio.NewReader(cmd.InOrStdin())
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
var kr keyring.Keyring
dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun)
if dryRun {
// options to include "eth_secp256k1" in signing algorithms list
kr, err = keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, clientCtx.KeyringDir, buf, ethermintHd.EthSecp256k1Option())
} else {
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
// options to include "eth_secp256k1" in signing algorithms list
kr, err = keyring.New(sdk.KeyringServiceName(), backend, clientCtx.KeyringDir, buf, ethermintHd.EthSecp256k1Option())
}
if err != nil {
return err
}
return RunAddCmd(cmd, args, kr, buf)
}
/*
input
- bip39 mnemonic
- bip39 passphrase
- bip44 path
- local encryption password
output
- armor encrypted private key (saved to file)
*/
func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *bufio.Reader) error {
var err error
name := args[0]
interactive, _ := cmd.Flags().GetBool(flagInteractive)
noBackup, _ := cmd.Flags().GetBool(flagNoBackup)
showMnemonic := !noBackup
keyringAlgos, _ := kb.SupportedAlgorithms()
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
if err != nil {
return err
}
if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); !dryRun {
_, err = kb.Key(name)
if err == nil {
// account exists, ask for user confirmation
response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf, cmd.ErrOrStderr())
if err2 != nil {
return err2
}
if !response {
return errors.New("aborted")
}
err2 = kb.Delete(name)
if err2 != nil {
return err2
}
}
multisigKeys, _ := cmd.Flags().GetStringSlice(flagMultisig)
if len(multisigKeys) != 0 {
var pks []cryptotypes.PubKey
multisigThreshold, _ := cmd.Flags().GetInt(flagMultiSigThreshold)
if err := validateMultisigThreshold(multisigThreshold, len(multisigKeys)); err != nil {
return err
}
for _, keyname := range multisigKeys {
k, err := kb.Key(keyname)
if err != nil {
return err
}
pks = append(pks, k.GetPubKey())
}
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
sort.Slice(pks, func(i, j int) bool {
return bytes.Compare(pks[i].Address(), pks[j].Address()) < 0
})
}
pk := multisig.NewLegacyAminoPubKey(multisigThreshold, pks)
if _, err := kb.SaveMultisig(name, pk); err != nil {
return err
}
cmd.PrintErrf("Key %q saved to disk.\n", name)
return nil
}
}
pubKey, _ := cmd.Flags().GetString(keys.FlagPublicKey)
if pubKey != "" {
pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, pubKey)
if err != nil {
return err
}
if _, err := kb.SavePubKey(name, pk, algo.Name()); err != nil {
return err
}
return nil
}
coinType, _ := cmd.Flags().GetUint32(flagCoinType)
account, _ := cmd.Flags().GetUint32(flagAccount)
index, _ := cmd.Flags().GetUint32(flagIndex)
hdPath, _ := cmd.Flags().GetString(flagHDPath)
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
if len(hdPath) == 0 {
hdPath = hd.CreateHDPath(coinType, account, index).String()
} else if useLedger {
return errors.New("cannot set custom bip32 path with ledger")
}
// If we're using ledger, only thing we need is the path and the bech32 prefix.
if useLedger {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
info, err := kb.SaveLedgerKey(name, hd.Secp256k1, bech32PrefixAccAddr, coinType, account, index)
if err != nil {
return err
}
return printCreate(cmd, info, false, "")
}
// Get bip39 mnemonic
var mnemonic, bip39Passphrase string
recover, _ := cmd.Flags().GetBool(flagRecover)
if recover {
mnemonic, err = input.GetString("Enter your bip39 mnemonic", inBuf)
if err != nil {
return err
}
if !bip39.IsMnemonicValid(mnemonic) {
return errors.New("invalid mnemonic")
}
} else if interactive {
mnemonic, err = input.GetString("Enter your bip39 mnemonic, or hit enter to generate one.", inBuf)
if err != nil {
return err
}
if !bip39.IsMnemonicValid(mnemonic) && mnemonic != "" {
return errors.New("invalid mnemonic")
}
}
if len(mnemonic) == 0 {
// read entropy seed straight from tmcrypto.Rand and convert to mnemonic
entropySeed, err := bip39.NewEntropy(mnemonicEntropySize)
if err != nil {
return err
}
mnemonic, err = bip39.NewMnemonic(entropySeed)
if err != nil {
return err
}
}
// override bip39 passphrase
if interactive {
bip39Passphrase, err = input.GetString(
"Enter your bip39 passphrase. This is combined with the mnemonic to derive the seed. "+
"Most users should just hit enter to use the default, \"\"", inBuf)
if err != nil {
return err
}
// if they use one, make them re-enter it
if len(bip39Passphrase) != 0 {
p2, err := input.GetString("Repeat the passphrase:", inBuf)
if err != nil {
return err
}
if bip39Passphrase != p2 {
return errors.New("passphrases don't match")
}
}
}
info, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
if err != nil {
return err
}
// Recover key from seed passphrase
if recover {
// Hide mnemonic from output
showMnemonic = false
mnemonic = ""
}
return printCreate(cmd, info, showMnemonic, mnemonic)
}
func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemonic string) error {
output, _ := cmd.Flags().GetString(cli.OutputFlag)
switch output {
case keys.OutputFormatText:
cmd.PrintErrln()
printKeyInfo(cmd.OutOrStdout(), info, keyring.Bech32KeyOutput, output)
// print mnemonic unless requested not to.
if showMnemonic {
fmt.Fprintln(cmd.ErrOrStderr(), "\n**Important** write this mnemonic phrase in a safe place.")
fmt.Fprintln(cmd.ErrOrStderr(), "It is the only way to recover your account if you ever forget your password.")
fmt.Fprintln(cmd.ErrOrStderr(), "")
fmt.Fprintln(cmd.ErrOrStderr(), mnemonic)
}
case keys.OutputFormatJSON:
out, err := keyring.Bech32KeyOutput(info)
if err != nil {
return err
}
if showMnemonic {
out.Mnemonic = mnemonic
}
jsonString, err := keys.KeysCdc.MarshalJSON(out)
if err != nil {
return err
}
cmd.Println(string(jsonString))
default:
return fmt.Errorf("invalid output format %s", output)
}
return nil
}
func validateMultisigThreshold(k, nKeys int) error {
if k <= 0 {
return fmt.Errorf("threshold must be a positive integer")
}
if nKeys < k {
return fmt.Errorf(
"threshold k of n multisignature: %d < %d", nKeys, k)
}
return nil
}

103
client/keys/utils.go Normal file
View File

@ -0,0 +1,103 @@
package keys
import (
"fmt"
"io"
"path/filepath"
yaml "gopkg.in/yaml.v2"
"github.com/cosmos/cosmos-sdk/client/keys"
cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
)
// available output formats.
const (
OutputFormatText = "text"
OutputFormatJSON = "json"
// defaultKeyDBName is the client's subdirectory where keys are stored.
defaultKeyDBName = "keys"
)
type bechKeyOutFn func(keyInfo cryptokeyring.Info) (cryptokeyring.KeyOutput, error)
// NewLegacyKeyBaseFromDir initializes a legacy keybase at the rootDir directory. Keybase
// options can be applied when generating this new Keybase.
func NewLegacyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption) (cryptokeyring.LegacyKeybase, error) {
return getLegacyKeyBaseFromDir(rootDir, opts...)
}
func getLegacyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption) (cryptokeyring.LegacyKeybase, error) {
return cryptokeyring.NewLegacy(defaultKeyDBName, filepath.Join(rootDir, "keys"), opts...)
}
func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn, output string) {
ko, err := bechKeyOut(keyInfo)
if err != nil {
panic(err)
}
switch output {
case OutputFormatText:
printTextInfos(w, []cryptokeyring.KeyOutput{ko})
case OutputFormatJSON:
out, err := keys.KeysCdc.MarshalJSON(ko)
if err != nil {
panic(err)
}
fmt.Fprintln(w, string(out))
}
}
//nolint
func printInfos(w io.Writer, infos []cryptokeyring.Info, output string) {
kos, err := cryptokeyring.Bech32KeysOutput(infos)
if err != nil {
panic(err)
}
switch output {
case OutputFormatText:
printTextInfos(w, kos)
case OutputFormatJSON:
out, err := keys.KeysCdc.MarshalJSON(kos)
if err != nil {
panic(err)
}
fmt.Fprintf(w, "%s", out)
}
}
func printTextInfos(w io.Writer, kos []cryptokeyring.KeyOutput) {
out, err := yaml.Marshal(&kos)
if err != nil {
panic(err)
}
fmt.Fprintln(w, string(out))
}
//nolint
func printKeyAddress(w io.Writer, info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
ko, err := bechKeyOut(info)
if err != nil {
panic(err)
}
fmt.Fprintln(w, ko.Address)
}
//nolint
func printPubKey(w io.Writer, info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
ko, err := bechKeyOut(info)
if err != nil {
panic(err)
}
fmt.Fprintln(w, ko.PubKey)
}

View File

@ -5,59 +5,59 @@ package client
import ( import (
"bufio" "bufio"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/spf13/cobra" "github.com/spf13/cobra"
tmconfig "github.com/tendermint/tendermint/config" tmconfig "github.com/tendermint/tendermint/config"
tmcrypto "github.com/tendermint/tendermint/crypto"
tmos "github.com/tendermint/tendermint/libs/os" tmos "github.com/tendermint/tendermint/libs/os"
tmrand "github.com/tendermint/tendermint/libs/rand" tmrand "github.com/tendermint/tendermint/libs/rand"
tmtypes "github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time" tmtime "github.com/tendermint/tendermint/types/time"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/crisis" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/mint" mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/ethermint/crypto/hd" "github.com/cosmos/ethermint/crypto/hd"
srvconfig "github.com/cosmos/ethermint/server/config"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
) )
var ( var (
flagNodeDirPrefix = "node-dir-prefix" flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v" flagNumValidators = "v"
flagOutputDir = "output-dir" flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home" flagNodeDaemonHome = "node-daemon-home"
flagNodeCLIHome = "node-cli-home" flagCoinDenom = "coin-denom"
flagStartingIPAddress = "starting-ip-address" flagIPAddrs = "ip-addresses"
flagCoinDenom = "coin-denom"
flagKeyAlgo = "algo"
flagIPAddrs = "ip-addrs"
) )
const nodeDirPerm = 0755 const nodeDirPerm = 0755
// TestnetCmd initializes all files for tendermint testnet and application // TestnetCmd initializes all files for tendermint testnet and application
func TestnetCmd(ctx *server.Context, cdc *codec.Codec, func TestnetCmd(
mbm module.BasicManager, genAccIterator authtypes.GenesisAccountIterator, mbm module.BasicManager, genBalancesIterator banktypes.GenesisBalancesIterator,
) *cobra.Command { ) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "testnet", Use: "testnet",
@ -67,9 +67,12 @@ necessary files (private validator, genesis, config, etc.).
Note, strict routability for addresses is turned off in the config file.`, Note, strict routability for addresses is turned off in the config file.`,
Example: "ethermintd testnet --v 4 --keyring-backend test --output-dir ./output --starting-ip-address 192.168.10.2", Example: "ethermintd testnet --v 4 --keyring-backend test --output-dir ./output --ip-addresses 192.168.10.2",
RunE: func(cmd *cobra.Command, _ []string) error { RunE: func(cmd *cobra.Command, _ []string) error {
config := ctx.Config clientCtx := client.GetClientContextFromCmd(cmd)
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
outputDir, _ := cmd.Flags().GetString(flagOutputDir) outputDir, _ := cmd.Flags().GetString(flagOutputDir)
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
@ -77,53 +80,51 @@ Note, strict routability for addresses is turned off in the config file.`,
minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices) minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices)
nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix) nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix)
nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome) nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome)
nodeCLIHome, _ := cmd.Flags().GetString(flagNodeCLIHome)
startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress)
ipAddresses, _ := cmd.Flags().GetStringSlice(flagIPAddrs) ipAddresses, _ := cmd.Flags().GetStringSlice(flagIPAddrs)
numValidators, _ := cmd.Flags().GetInt(flagNumValidators) numValidators, _ := cmd.Flags().GetInt(flagNumValidators)
algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
coinDenom, _ := cmd.Flags().GetString(flagCoinDenom) coinDenom, _ := cmd.Flags().GetString(flagCoinDenom)
algo, _ := cmd.Flags().GetString(flagKeyAlgo)
if len(ipAddresses) == 0 {
return errors.New("IP address list cannot be empty")
}
return InitTestnet( return InitTestnet(
cmd, config, cdc, mbm, genAccIterator, outputDir, chainID, coinDenom, minGasPrices, clientCtx, cmd, config, mbm, genBalancesIterator, outputDir, chainID, coinDenom, minGasPrices,
nodeDirPrefix, nodeDaemonHome, nodeCLIHome, startingIPAddress, ipAddresses, keyringBackend, algo, numValidators, nodeDirPrefix, nodeDaemonHome, keyringBackend, algo, ipAddresses, numValidators,
) )
}, },
} }
cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with") cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with")
cmd.Flags().StringP(flagOutputDir, "o", "./build", "Directory to store initialization data for the testnet") cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet", "Directory to store initialization data for the testnet")
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "ethermintd", "Home directory of the node's daemon configuration") cmd.Flags().String(flagNodeDaemonHome, "simd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagNodeCLIHome, "ethermintcli", "Home directory of the node's cli configuration") cmd.Flags().StringSlice(flagIPAddrs, []string{"192.168.0.1"}, "List of IP addresses to use (i.e. `192.168.0.1,172.168.0.1` results in persistent peers list ID0@192.168.0.1:46656, ID1@172.168.0.1)")
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
cmd.Flags().StringSlice(flagIPAddrs, []string{}, "List of IP addresses to use (i.e. `192.168.0.1,172.168.0.1` results in persistent peers list ID0@192.168.0.1:46656, ID1@172.168.0.1)")
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(flagCoinDenom, ethermint.AttoPhoton, "Coin denomination used for staking, governance, mint, crisis and evm parameters")
cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", ethermint.AttoPhoton), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01aphoton,0.001stake)") cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", ethermint.AttoPhoton), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01aphoton,0.001stake)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().String(flagKeyAlgo, string(hd.EthSecp256k1), "Key signing algorithm to generate keys for") cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.EthSecp256k1Type), "Key signing algorithm to generate keys for")
cmd.Flags().String(flagCoinDenom, ethermint.AttoPhoton, "Coin denomination used for staking, governance, mint, crisis and evm parameters")
return cmd return cmd
} }
// InitTestnet initializes the testnet configuration // InitTestnet initializes the testnet configuration
func InitTestnet( func InitTestnet(
clientCtx client.Context,
cmd *cobra.Command, cmd *cobra.Command,
config *tmconfig.Config, nodeConfig *tmconfig.Config,
cdc *codec.Codec,
mbm module.BasicManager, mbm module.BasicManager,
genAccIterator authtypes.GenesisAccountIterator, genBalIterator banktypes.GenesisBalancesIterator,
outputDir, outputDir,
chainID, chainID,
coinDenom, coinDenom,
minGasPrices, minGasPrices,
nodeDirPrefix, nodeDirPrefix,
nodeDaemonHome, nodeDaemonHome,
nodeCLIHome,
startingIPAddress string,
ipAddresses []string,
keyringBackend, keyringBackend,
algo string, algoStr string,
ipAddresses []string,
numValidators int, numValidators int,
) error { ) error {
@ -144,13 +145,19 @@ func InitTestnet(
} }
nodeIDs := make([]string, numValidators) nodeIDs := make([]string, numValidators)
valPubKeys := make([]tmcrypto.PubKey, numValidators) valPubKeys := make([]cryptotypes.PubKey, numValidators)
simappConfig := srvconfig.DefaultConfig() appConfig := srvconfig.DefaultConfig()
simappConfig.MinGasPrices = minGasPrices appConfig.MinGasPrices = minGasPrices
appConfig.API.Enable = true
appConfig.Telemetry.Enabled = true
appConfig.Telemetry.PrometheusRetentionTime = 60
appConfig.Telemetry.EnableHostnameLabel = false
appConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", chainID}}
var ( var (
genAccounts []authexported.GenesisAccount genAccounts []authtypes.GenesisAccount
genBalances []banktypes.Balance
genFiles []string genFiles []string
) )
@ -159,28 +166,25 @@ func InitTestnet(
for i := 0; i < numValidators; i++ { for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i) nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome) nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
clientDir := filepath.Join(outputDir, nodeDirName, nodeCLIHome)
gentxsDir := filepath.Join(outputDir, "gentxs") gentxsDir := filepath.Join(outputDir, "gentxs")
config.SetRoot(nodeDir) nodeConfig.SetRoot(nodeDir)
config.RPC.ListenAddress = "tcp://0.0.0.0:26657" nodeConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657"
if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil { if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(outputDir)
return err return err
} }
if err := os.MkdirAll(clientDir, nodeDirPerm); err != nil { nodeConfig.Moniker = nodeDirName
_ = os.RemoveAll(outputDir)
return err
}
config.Moniker = nodeDirName var (
ip string
err error
)
var ip string if len(ipAddresses) == 1 {
var err error ip, err = getIP(i, ipAddresses[0])
if len(ipAddresses) == 0 {
ip, err = getIP(i, startingIPAddress)
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(outputDir)
return err return err
@ -189,32 +193,33 @@ func InitTestnet(
ip = ipAddresses[i] ip = ipAddresses[i]
} }
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(config) nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig)
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(outputDir)
return err return err
} }
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip) memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
genFiles = append(genFiles, config.GenesisFile()) genFiles = append(genFiles, nodeConfig.GenesisFile())
kb, err := keys.NewKeyring( kb, err := keyring.New(
sdk.KeyringServiceName(), sdk.KeyringServiceName(),
keyringBackend, keyringBackend,
clientDir, nodeDir,
inBuf, inBuf,
hd.EthSecp256k1Options()..., hd.EthSecp256k1Option(),
) )
if err != nil { if err != nil {
return err return err
} }
cmd.Printf( keyringAlgos, _ := kb.SupportedAlgorithms()
"Password for account '%s' :\n", nodeDirName, algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
) if err != nil {
return err
}
keyPass := clientkeys.DefaultKeyPass addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo)
addr, secret, err := GenerateSaveCoinKey(kb, nodeDirName, keyPass, true, keys.SigningAlgo(algo))
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir) _ = os.RemoveAll(outputDir)
return err return err
@ -228,7 +233,7 @@ func InitTestnet(
} }
// save private key seed words // save private key seed words
if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint); err != nil { if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), nodeDir, cliPrint); err != nil {
return err return err
} }
@ -237,13 +242,14 @@ func InitTestnet(
sdk.NewCoin(coinDenom, accStakingTokens), sdk.NewCoin(coinDenom, accStakingTokens),
) )
genAccounts = append(genAccounts, ethermint.EthAccount{ genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins})
BaseAccount: authtypes.NewBaseAccount(addr, coins, nil, 0, 0), genAccounts = append(genAccounts, &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0),
CodeHash: ethcrypto.Keccak256(nil), CodeHash: ethcrypto.Keccak256(nil),
}) })
valTokens := sdk.TokensFromConsensusPower(100) valTokens := sdk.TokensFromConsensusPower(100)
msg := stakingtypes.NewMsgCreateValidator( createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addr), sdk.ValAddress(addr),
valPubKeys[i], valPubKeys[i],
sdk.NewCoin(coinDenom, valTokens), sdk.NewCoin(coinDenom, valTokens),
@ -252,37 +258,47 @@ func InitTestnet(
sdk.OneInt(), sdk.OneInt(),
) )
tx := authtypes.NewStdTx([]sdk.Msg{msg}, authtypes.StdFee{}, []authtypes.StdSignature{}, memo) //nolint:staticcheck // SA1019: authtypes.StdFee is deprecated
txBldr := authtypes.NewTxBuilderFromCLI(inBuf).WithChainID(chainID).WithMemo(memo).WithKeybase(kb)
signedTx, err := txBldr.SignStdTx(nodeDirName, clientkeys.DefaultKeyPass, tx, false)
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir)
return err return err
} }
txBytes, err := cdc.MarshalJSON(signedTx) txBuilder := clientCtx.TxConfig.NewTxBuilder()
if err := txBuilder.SetMsgs(createValMsg); err != nil {
return err
}
txBuilder.SetMemo(memo)
txFactory := tx.Factory{}
txFactory = txFactory.
WithChainID(chainID).
WithMemo(memo).
WithKeybase(kb).
WithTxConfig(clientCtx.TxConfig)
if err := tx.Sign(txFactory, nodeDirName, txBuilder, false); err != nil {
return err
}
txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
if err != nil { if err != nil {
_ = os.RemoveAll(outputDir)
return err return err
} }
// gather gentxs folder if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes); err != nil {
_ = os.RemoveAll(outputDir)
return err return err
} }
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), simappConfig) srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appConfig)
} }
if err := initGenFiles(cdc, mbm, chainID, coinDenom, genAccounts, genFiles, numValidators); err != nil { if err := initGenFiles(clientCtx, mbm, chainID, coinDenom, genAccounts, genBalances, genFiles, numValidators); err != nil {
return err return err
} }
err := collectGenFiles( err := collectGenFiles(
cdc, config, chainID, nodeIDs, valPubKeys, numValidators, clientCtx, nodeConfig, chainID, nodeIDs, valPubKeys, numValidators,
outputDir, nodeDirPrefix, nodeDaemonHome, genAccIterator, outputDir, nodeDirPrefix, nodeDaemonHome, genBalIterator,
) )
if err != nil { if err != nil {
return err return err
@ -293,57 +309,73 @@ func InitTestnet(
} }
func initGenFiles( func initGenFiles(
cdc *codec.Codec, mbm module.BasicManager, clientCtx client.Context,
chainID, coinDenom string, mbm module.BasicManager,
genAccounts []authexported.GenesisAccount, chainID,
genFiles []string, numValidators int, coinDenom string,
genAccounts []authtypes.GenesisAccount,
genBalances []banktypes.Balance,
genFiles []string,
numValidators int,
) error { ) error {
appGenState := mbm.DefaultGenesis() appGenState := mbm.DefaultGenesis(clientCtx.JSONMarshaler)
// set the accounts in the genesis state // set the accounts in the genesis state
var authGenState authtypes.GenesisState var authGenState authtypes.GenesisState
cdc.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState) clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState)
authGenState.Accounts = genAccounts accounts, err := authtypes.PackAccounts(genAccounts)
appGenState[authtypes.ModuleName] = cdc.MustMarshalJSON(authGenState)
var stakingGenState stakingtypes.GenesisState
cdc.MustUnmarshalJSON(appGenState[stakingtypes.ModuleName], &stakingGenState)
stakingGenState.Params.BondDenom = coinDenom
appGenState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingGenState)
var govGenState govtypes.GenesisState
cdc.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
appGenState[govtypes.ModuleName] = cdc.MustMarshalJSON(govGenState)
var mintGenState mint.GenesisState
cdc.MustUnmarshalJSON(appGenState[mint.ModuleName], &mintGenState)
mintGenState.Params.MintDenom = coinDenom
appGenState[mint.ModuleName] = cdc.MustMarshalJSON(mintGenState)
var crisisGenState crisis.GenesisState
cdc.MustUnmarshalJSON(appGenState[crisis.ModuleName], &crisisGenState)
crisisGenState.ConstantFee.Denom = coinDenom
appGenState[crisis.ModuleName] = cdc.MustMarshalJSON(crisisGenState)
var evmGenState evmtypes.GenesisState
cdc.MustUnmarshalJSON(appGenState[evmtypes.ModuleName], &evmGenState)
evmGenState.Params.EvmDenom = coinDenom
appGenState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmGenState)
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
if err != nil { if err != nil {
return err return err
} }
genDoc := tmtypes.GenesisDoc{ authGenState.Accounts = accounts
appGenState[authtypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&authGenState)
// set the balances in the genesis state
var bankGenState banktypes.GenesisState
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState)
bankGenState.Balances = genBalances
appGenState[banktypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&bankGenState)
var stakingGenState stakingtypes.GenesisState
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[stakingtypes.ModuleName], &stakingGenState)
stakingGenState.Params.BondDenom = coinDenom
appGenState[stakingtypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&stakingGenState)
var govGenState govtypes.GenesisState
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
appGenState[govtypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&govGenState)
var mintGenState mintypes.GenesisState
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[mintypes.ModuleName], &mintGenState)
mintGenState.Params.MintDenom = coinDenom
appGenState[mintypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&mintGenState)
var crisisGenState crisistypes.GenesisState
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[crisistypes.ModuleName], &crisisGenState)
crisisGenState.ConstantFee.Denom = coinDenom
appGenState[crisistypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&crisisGenState)
var evmGenState evmtypes.GenesisState
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[evmtypes.ModuleName], &evmGenState)
evmGenState.Params.EvmDenom = coinDenom
appGenState[evmtypes.ModuleName] = clientCtx.JSONMarshaler.MustMarshalJSON(&evmGenState)
appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ")
if err != nil {
return err
}
genDoc := types.GenesisDoc{
ChainID: chainID, ChainID: chainID,
AppState: appGenStateJSON, AppState: appGenStateJSON,
Validators: nil, Validators: nil,
@ -358,32 +390,10 @@ func initGenFiles(
return nil return nil
} }
// GenerateSaveCoinKey returns the address of a public key, along with the secret
// phrase to recover the private key.
func GenerateSaveCoinKey(keybase keys.Keybase, keyName, keyPass string, overwrite bool, algo keys.SigningAlgo) (sdk.AccAddress, string, error) {
// ensure no overwrite
if !overwrite {
_, err := keybase.Get(keyName)
if err == nil {
return sdk.AccAddress([]byte{}), "", fmt.Errorf(
"key already exists, overwrite is disabled")
}
}
// generate a private key, with recovery phrase
info, secret, err := keybase.CreateMnemonic(keyName, keys.English, keyPass, algo)
if err != nil {
return sdk.AccAddress([]byte{}), "", err
}
return sdk.AccAddress(info.GetPubKey().Address()), secret, nil
}
func collectGenFiles( func collectGenFiles(
cdc *codec.Codec, config *tmconfig.Config, chainID string, clientCtx client.Context, nodeConfig *tmconfig.Config, chainID string,
nodeIDs []string, valPubKeys []tmcrypto.PubKey, nodeIDs []string, valPubKeys []cryptotypes.PubKey, numValidators int,
numValidators int, outputDir, nodeDirPrefix, nodeDaemonHome string, outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator,
genAccIterator authtypes.GenesisAccountIterator,
) error { ) error {
var appState json.RawMessage var appState json.RawMessage
@ -393,19 +403,19 @@ func collectGenFiles(
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i) nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome) nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
gentxsDir := filepath.Join(outputDir, "gentxs") gentxsDir := filepath.Join(outputDir, "gentxs")
config.Moniker = nodeDirName nodeConfig.Moniker = nodeDirName
config.SetRoot(nodeDir) nodeConfig.SetRoot(nodeDir)
nodeID, valPubKey := nodeIDs[i], valPubKeys[i] nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, nodeID, valPubKey) initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, valPubKey)
genDoc, err := tmtypes.GenesisDocFromFile(config.GenesisFile()) genDoc, err := types.GenesisDocFromFile(nodeConfig.GenesisFile())
if err != nil { if err != nil {
return err return err
} }
nodeAppState, err := genutil.GenAppStateFromConfig(cdc, config, initCfg, *genDoc, genAccIterator) nodeAppState, err := genutil.GenAppStateFromConfig(clientCtx.JSONMarshaler, clientCtx.TxConfig, nodeConfig, initCfg, *genDoc, genBalIterator)
if err != nil { if err != nil {
return err return err
} }
@ -415,7 +425,7 @@ func collectGenFiles(
appState = nodeAppState appState = nodeAppState
} }
genFile := config.GenesisFile() genFile := nodeConfig.GenesisFile()
// overwrite each validator's genesis file to have a canonical genesis time // overwrite each validator's genesis file to have a canonical genesis time
if err := genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime); err != nil { if err := genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime); err != nil {

View File

@ -1,142 +0,0 @@
package main
import (
"fmt"
"github.com/spf13/cobra"
tmamino "github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/tendermint/tendermint/libs/cli"
sdkclient "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
clientrpc "github.com/cosmos/cosmos-sdk/client/rpc"
sdkcodec "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/auth"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/bank"
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
"github.com/cosmos/ethermint/app"
"github.com/cosmos/ethermint/client"
"github.com/cosmos/ethermint/codec"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/rpc"
ethermint "github.com/cosmos/ethermint/types"
)
var (
cdc = codec.MakeCodec(app.ModuleBasics)
)
func main() {
// Configure cobra to sort commands
cobra.EnableCommandSorting = false
tmamino.RegisterKeyType(ethsecp256k1.PubKey{}, ethsecp256k1.PubKeyName)
tmamino.RegisterKeyType(ethsecp256k1.PrivKey{}, ethsecp256k1.PrivKeyName)
keys.CryptoCdc = cdc
clientkeys.KeysCdc = cdc
// Read in the configuration file for the sdk
config := sdk.GetConfig()
ethermint.SetBech32Prefixes(config)
ethermint.SetBip44CoinType(config)
config.Seal()
rootCmd := &cobra.Command{
Use: "ethermintcli",
Short: "Command line interface for interacting with ethermintd",
}
// Add --chain-id to persistent flags and mark it required
rootCmd.PersistentFlags().String(flags.FlagChainID, "", "Chain ID of tendermint node")
rootCmd.PersistentPreRunE = func(_ *cobra.Command, _ []string) error {
return client.InitConfig(rootCmd)
}
// Construct Root Command
rootCmd.AddCommand(
clientrpc.StatusCommand(),
sdkclient.ConfigCmd(app.DefaultCLIHome),
queryCmd(cdc),
txCmd(cdc),
client.ValidateChainID(
rpc.ServeCmd(cdc),
),
flags.LineBreak,
client.KeyCommands(),
flags.LineBreak,
version.Cmd,
flags.NewCompletionCmd(rootCmd, true),
)
// Add flags and prefix all env exposed with EM
executor := cli.PrepareMainCmd(rootCmd, "EM", app.DefaultCLIHome)
err := executor.Execute()
if err != nil {
panic(fmt.Errorf("failed executing CLI command: %w", err))
}
}
func queryCmd(cdc *sdkcodec.Codec) *cobra.Command {
queryCmd := &cobra.Command{
Use: "query",
Aliases: []string{"q"},
Short: "Querying subcommands",
}
queryCmd.AddCommand(
authcmd.GetAccountCmd(cdc),
flags.LineBreak,
authcmd.QueryTxsByEventsCmd(cdc),
authcmd.QueryTxCmd(cdc),
flags.LineBreak,
)
// add modules' query commands
app.ModuleBasics.AddQueryCommands(queryCmd, cdc)
return queryCmd
}
func txCmd(cdc *sdkcodec.Codec) *cobra.Command {
txCmd := &cobra.Command{
Use: "tx",
Short: "Transactions subcommands",
}
txCmd.AddCommand(
bankcmd.SendTxCmd(cdc),
flags.LineBreak,
authcmd.GetSignCommand(cdc),
authcmd.GetMultiSignCommand(cdc),
flags.LineBreak,
authcmd.GetBroadcastCommand(cdc),
authcmd.GetEncodeCommand(cdc),
authcmd.GetDecodeCommand(cdc),
flags.LineBreak,
)
// add modules' tx commands
app.ModuleBasics.AddTxCommands(txCmd, cdc)
// remove auth and bank commands as they're mounted under the root tx command
var cmdsToRemove []*cobra.Command
for _, cmd := range txCmd.Commands() {
if cmd.Use == auth.ModuleName || cmd.Use == bank.ModuleName {
cmdsToRemove = append(cmdsToRemove, cmd)
}
}
txCmd.RemoveCommand(cmdsToRemove...)
return txCmd
}

View File

@ -0,0 +1,28 @@
package main_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client/flags"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"github.com/cosmos/ethermint/app"
ethermintd "github.com/cosmos/ethermint/cmd/ethermintd"
)
func TestInitCmd(t *testing.T) {
rootCmd, _ := ethermintd.NewRootCmd()
rootCmd.SetArgs([]string{
"init", // Test the init cmd
"ethermint-test", // Moniker
fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists
fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint-1"),
})
err := svrcmd.Execute(rootCmd, app.DefaultNodeHome)
require.NoError(t, err)
}

View File

@ -2,23 +2,23 @@ package main
import ( import (
"bufio" "bufio"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/ethermint/crypto/hd" "github.com/cosmos/ethermint/crypto/hd"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
@ -27,17 +27,13 @@ import (
) )
const ( const (
flagClientHome = "home-client"
flagVestingStart = "vesting-start-time" flagVestingStart = "vesting-start-time"
flagVestingEnd = "vesting-end-time" flagVestingEnd = "vesting-end-time"
flagVestingAmt = "vesting-amount" flagVestingAmt = "vesting-amount"
) )
// AddGenesisAccountCmd returns add-genesis-account cobra Command. // AddGenesisAccountCmd returns add-genesis-account cobra Command.
func AddGenesisAccountCmd( func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command {
ctx *server.Context, cdc *codec.Codec, defaultNodeHome, defaultClientHome string,
) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
Short: "Add a genesis account to genesis.json", Short: "Add a genesis account to genesis.json",
@ -48,58 +44,65 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
`, `,
Args: cobra.ExactArgs(2), Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
config := ctx.Config clientCtx := client.GetClientContextFromCmd(cmd)
config.SetRoot(viper.GetString(cli.HomeFlag)) depCdc := clientCtx.JSONMarshaler
cdc := depCdc.(codec.Marshaler)
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
config.SetRoot(clientCtx.HomeDir)
addr, err := sdk.AccAddressFromBech32(args[0]) addr, err := sdk.AccAddressFromBech32(args[0])
inBuf := bufio.NewReader(cmd.InOrStdin())
if err != nil { if err != nil {
// attempt to lookup address from Keybase if no address was provided inBuf := bufio.NewReader(cmd.InOrStdin())
kb, err := keys.NewKeyring( keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
// attempt to lookup address from Keyring if no address was provided
kr, err := keyring.New(
sdk.KeyringServiceName(), sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend), keyringBackend,
viper.GetString(flagClientHome), clientCtx.HomeDir,
inBuf, inBuf,
hd.EthSecp256k1Options()..., hd.EthSecp256k1Option(),
) )
if err != nil { if err != nil {
return err return err
} }
info, err := kb.Get(args[0]) info, err := kr.Key(args[0])
if err != nil { if err != nil {
return fmt.Errorf("failed to get address from Keybase: %w", err) return fmt.Errorf("failed to get address from Keyring: %w", err)
} }
addr = info.GetAddress() addr = info.GetAddress()
} }
coins, err := sdk.ParseCoins(args[1]) coins, err := sdk.ParseCoinsNormalized(args[1])
if err != nil { if err != nil {
return fmt.Errorf("failed to parse coins: %w", err) return fmt.Errorf("failed to parse coins: %w", err)
} }
vestingStart := viper.GetInt64(flagVestingStart) vestingStart, _ := cmd.Flags().GetInt64(flagVestingStart)
vestingEnd := viper.GetInt64(flagVestingEnd) vestingEnd, _ := cmd.Flags().GetInt64(flagVestingEnd)
vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt)) vestingAmtStr, _ := cmd.Flags().GetString(flagVestingAmt)
vestingAmt, err := sdk.ParseCoinsNormalized(vestingAmtStr)
if err != nil { if err != nil {
return fmt.Errorf("failed to parse vesting amount: %w", err) return fmt.Errorf("failed to parse vesting amount: %w", err)
} }
// create concrete account type based on input parameters // create concrete account type based on input parameters
var genAccount authexported.GenesisAccount var genAccount authtypes.GenesisAccount
balances := banktypes.Balance{Address: addr.String(), Coins: coins.Sort()}
baseAccount := authtypes.NewBaseAccount(addr, nil, 0, 0)
// balances := bank.Balance{Address: addr, Coins: coins.Sort()}
coins = coins.Sort()
baseAccount := auth.NewBaseAccount(addr, coins, nil, 0, 0)
if !vestingAmt.IsZero() { if !vestingAmt.IsZero() {
baseVestingAccount, err := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd) baseVestingAccount := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd)
if err != nil {
return err
}
if (coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) || if (balances.Coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) ||
baseVestingAccount.OriginalVesting.IsAnyGT(coins) { baseVestingAccount.OriginalVesting.IsAnyGT(balances.Coins) {
return errors.New("vesting amount cannot be greater than total amount") return errors.New("vesting amount cannot be greater than total amount")
} }
@ -114,7 +117,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
return errors.New("invalid vesting parameters; must supply start and end time or end time") return errors.New("invalid vesting parameters; must supply start and end time or end time")
} }
} else { } else {
genAccount = ethermint.EthAccount{ genAccount = &ethermint.EthAccount{
BaseAccount: baseAccount, BaseAccount: baseAccount,
CodeHash: ethcrypto.Keccak256(nil), CodeHash: ethcrypto.Keccak256(nil),
} }
@ -125,30 +128,53 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
} }
genFile := config.GenesisFile() genFile := config.GenesisFile()
appState, genDoc, err := genutil.GenesisStateFromGenFile(cdc, genFile) appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile)
if err != nil { if err != nil {
return fmt.Errorf("failed to unmarshal genesis state: %w", err) return fmt.Errorf("failed to unmarshal genesis state: %w", err)
} }
authGenState := auth.GetGenesisStateFromAppState(cdc, appState) authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState)
if authGenState.Accounts.Contains(addr) { accs, err := authtypes.UnpackAccounts(authGenState.Accounts)
if err != nil {
return fmt.Errorf("failed to get accounts from any: %w", err)
}
if accs.Contains(addr) {
return fmt.Errorf("cannot add account at existing address %s", addr) return fmt.Errorf("cannot add account at existing address %s", addr)
} }
// Add the new account to the set of genesis accounts and sanitize the // Add the new account to the set of genesis accounts and sanitize the
// accounts afterwards. // accounts afterwards.
authGenState.Accounts = append(authGenState.Accounts, genAccount) accs = append(accs, genAccount)
authGenState.Accounts = auth.SanitizeGenesisAccounts(authGenState.Accounts) accs = authtypes.SanitizeGenesisAccounts(accs)
authGenStateBz, err := cdc.MarshalJSON(authGenState) genAccs, err := authtypes.PackAccounts(accs)
if err != nil {
return fmt.Errorf("failed to convert accounts into any's: %w", err)
}
authGenState.Accounts = genAccs
authGenStateBz, err := cdc.MarshalJSON(&authGenState)
if err != nil { if err != nil {
return fmt.Errorf("failed to marshal auth genesis state: %w", err) return fmt.Errorf("failed to marshal auth genesis state: %w", err)
} }
appState[auth.ModuleName] = authGenStateBz appState[authtypes.ModuleName] = authGenStateBz
appStateJSON, err := cdc.MarshalJSON(appState) bankGenState := banktypes.GetGenesisStateFromAppState(depCdc, appState)
bankGenState.Balances = append(bankGenState.Balances, balances)
bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances)
bankGenState.Supply = bankGenState.Supply.Add(balances.Coins...)
bankGenStateBz, err := cdc.MarshalJSON(bankGenState)
if err != nil {
return fmt.Errorf("failed to marshal bank genesis state: %w", err)
}
appState[banktypes.ModuleName] = bankGenStateBz
appStateJSON, err := json.Marshal(appState)
if err != nil { if err != nil {
return fmt.Errorf("failed to marshal application genesis state: %w", err) return fmt.Errorf("failed to marshal application genesis state: %w", err)
} }
@ -158,12 +184,12 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
}, },
} }
cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory") cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
cmd.Flags().String(flagClientHome, defaultClientHome, "client's home directory")
cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts")
cmd.Flags().Uint64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") cmd.Flags().Int64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts")
cmd.Flags().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") cmd.Flags().Int64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts")
flags.AddQueryFlagsToCmd(cmd)
return cmd return cmd
} }

View File

@ -1,129 +1,24 @@
package main package main
import ( import (
"encoding/json" "os"
"io"
"github.com/spf13/cobra"
"github.com/spf13/viper"
abci "github.com/tendermint/tendermint/abci/types"
tmamino "github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client/flags"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
storetypes "github.com/cosmos/cosmos-sdk/store/types" svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/ethermint/app" "github.com/cosmos/ethermint/app"
"github.com/cosmos/ethermint/client"
"github.com/cosmos/ethermint/codec"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
ethermint "github.com/cosmos/ethermint/types"
) )
const flagInvCheckPeriod = "inv-check-period"
var invCheckPeriod uint
func main() { func main() {
cobra.EnableCommandSorting = false rootCmd, _ := NewRootCmd()
cdc := codec.MakeCodec(app.ModuleBasics) if err := svrcmd.Execute(rootCmd, app.DefaultNodeHome); err != nil {
switch e := err.(type) {
case server.ErrorCode:
os.Exit(e.Code)
tmamino.RegisterKeyType(ethsecp256k1.PubKey{}, ethsecp256k1.PubKeyName) default:
tmamino.RegisterKeyType(ethsecp256k1.PrivKey{}, ethsecp256k1.PrivKeyName) os.Exit(1)
keys.CryptoCdc = cdc
genutil.ModuleCdc = cdc
genutiltypes.ModuleCdc = cdc
clientkeys.KeysCdc = cdc
config := sdk.GetConfig()
ethermint.SetBech32Prefixes(config)
ethermint.SetBip44CoinType(config)
config.Seal()
ctx := server.NewDefaultContext()
rootCmd := &cobra.Command{
Use: "ethermintd",
Short: "Ethermint App Daemon (server)",
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
// CLI commands to initialize the chain
rootCmd.AddCommand(
client.GenerateChainID(
client.ValidateChainID(
genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, app.DefaultNodeHome),
),
),
genutilcli.CollectGenTxsCmd(ctx, cdc, auth.GenesisAccountIterator{}, app.DefaultNodeHome),
genutilcli.MigrateGenesisCmd(ctx, cdc),
genutilcli.GenTxCmd(
ctx, cdc, app.ModuleBasics, staking.AppModuleBasic{}, auth.GenesisAccountIterator{},
app.DefaultNodeHome, app.DefaultCLIHome,
),
genutilcli.ValidateGenesisCmd(ctx, cdc, app.ModuleBasics),
client.TestnetCmd(ctx, cdc, app.ModuleBasics, auth.GenesisAccountIterator{}),
// AddGenesisAccountCmd allows users to add accounts to the genesis file
AddGenesisAccountCmd(ctx, cdc, app.DefaultNodeHome, app.DefaultCLIHome),
flags.NewCompletionCmd(rootCmd, true),
)
// Tendermint node base commands
server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
// prepare and add flags
executor := cli.PrepareBaseCmd(rootCmd, "EM", app.DefaultNodeHome)
rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
0, "Assert registered invariants every N blocks")
err := executor.Execute()
if err != nil {
panic(err)
}
}
func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application {
return app.NewEthermintApp(
logger,
db,
traceStore,
true,
map[int64]bool{},
0,
baseapp.SetPruning(storetypes.NewPruningOptionsFromString(viper.GetString("pruning"))),
baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
baseapp.SetHaltHeight(uint64(viper.GetInt(server.FlagHaltHeight))),
)
}
func exportAppStateAndTMValidators(
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string,
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
var ethermintApp *app.EthermintApp
if height != -1 {
ethermintApp = app.NewEthermintApp(logger, db, traceStore, false, map[int64]bool{}, 0)
if err := ethermintApp.LoadHeight(height); err != nil {
return nil, nil, err
} }
} else {
ethermintApp = app.NewEthermintApp(logger, db, traceStore, true, map[int64]bool{}, 0)
} }
return ethermintApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
} }

233
cmd/ethermintd/root.go Normal file
View File

@ -0,0 +1,233 @@
package main
import (
"errors"
"io"
"os"
"path/filepath"
"github.com/spf13/cast"
"github.com/spf13/cobra"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/rpc"
sdkserver "github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/snapshots"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/auth/types"
vestingcli "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/crisis"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"github.com/cosmos/ethermint/app"
ethermintclient "github.com/cosmos/ethermint/client"
ethermintclientKey "github.com/cosmos/ethermint/client/keys"
"github.com/cosmos/ethermint/server"
)
// NewRootCmd creates a new root command for simd. It is called once in the
// main function.
func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
encodingConfig := app.MakeEncodingConfig()
initClientCtx := client.Context{}.
WithJSONMarshaler(encodingConfig.Marshaler).
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithLegacyAmino(encodingConfig.Amino).
WithInput(os.Stdin).
WithAccountRetriever(types.AccountRetriever{}).
WithBroadcastMode(flags.BroadcastSync).
WithHomeDir(app.DefaultNodeHome)
rootCmd := &cobra.Command{
Use: "ethermintd",
Short: "ethermint app daemon",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil {
return err
}
return server.InterceptConfigsPreRunHandler(cmd)
},
}
initRootCmd(rootCmd, encodingConfig)
return rootCmd, encodingConfig
}
func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
authclient.Codec = encodingConfig.Marshaler
rootCmd.AddCommand(
ethermintclient.GenerateChainID(
ethermintclient.ValidateChainID(
genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome),
),
),
genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome),
genutilcli.MigrateGenesisCmd(),
genutilcli.GenTxCmd(app.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome),
genutilcli.ValidateGenesisCmd(app.ModuleBasics),
AddGenesisAccountCmd(app.DefaultNodeHome),
tmcli.NewCompletionCmd(rootCmd, true),
ethermintclient.TestnetCmd(app.ModuleBasics, banktypes.GenesisBalancesIterator{}),
debug.Cmd(),
)
a := appCreator{encCfg: encodingConfig}
server.AddCommands(rootCmd, app.DefaultNodeHome, a.newApp, a.appExport, addModuleInitFlags)
// add keybase, auxiliary RPC, query, and tx child commands
rootCmd.AddCommand(
rpc.StatusCommand(),
queryCommand(),
txCommand(),
ethermintclientKey.Commands(app.DefaultNodeHome),
)
}
func addModuleInitFlags(startCmd *cobra.Command) {
crisis.AddModuleInitFlags(startCmd)
}
func queryCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Aliases: []string{"q"},
Short: "Querying subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
authcmd.GetAccountCmd(),
rpc.ValidatorCommand(),
rpc.BlockCommand(),
authcmd.QueryTxsByEventsCmd(),
authcmd.QueryTxCmd(),
)
app.ModuleBasics.AddQueryCommands(cmd)
cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID")
return cmd
}
func txCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "tx",
Short: "Transactions subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
authcmd.GetSignCommand(),
authcmd.GetSignBatchCommand(),
authcmd.GetMultiSignCommand(),
authcmd.GetValidateSignaturesCommand(),
flags.LineBreak,
authcmd.GetBroadcastCommand(),
authcmd.GetEncodeCommand(),
authcmd.GetDecodeCommand(),
flags.LineBreak,
vestingcli.GetTxCmd(),
)
app.ModuleBasics.AddTxCommands(cmd)
cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID")
return cmd
}
type appCreator struct {
encCfg params.EncodingConfig
}
// newApp create a new SDK application binary
func (a appCreator) newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
var cache sdk.MultiStorePersistentCache
if cast.ToBool(appOpts.Get(sdkserver.FlagInterBlockCache)) {
cache = store.NewCommitKVStoreCacheManager()
}
skipUpgradeHeights := make(map[int64]bool)
for _, h := range cast.ToIntSlice(appOpts.Get(sdkserver.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
pruningOpts, err := sdkserver.GetPruningOptionsFromFlags(appOpts)
if err != nil {
panic(err)
}
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")
snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDir)
if err != nil {
panic(err)
}
snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir)
if err != nil {
panic(err)
}
return app.NewEthermintApp(
logger, db, traceStore, true, skipUpgradeHeights,
cast.ToString(appOpts.Get(flags.FlagHome)),
cast.ToUint(appOpts.Get(sdkserver.FlagInvCheckPeriod)),
a.encCfg,
appOpts,
baseapp.SetPruning(pruningOpts),
baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(sdkserver.FlagMinGasPrices))),
baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(sdkserver.FlagHaltHeight))),
baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(sdkserver.FlagHaltTime))),
baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(sdkserver.FlagMinRetainBlocks))),
baseapp.SetInterBlockCache(cache),
baseapp.SetTrace(cast.ToBool(appOpts.Get(sdkserver.FlagTrace))),
baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))),
baseapp.SetSnapshotStore(snapshotStore),
baseapp.SetSnapshotInterval(cast.ToUint64(appOpts.Get(sdkserver.FlagStateSyncSnapshotInterval))),
baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent))),
)
}
// appExport creates a new Ethermint app (optionally at a given height)
// and exports state.
func (a appCreator) appExport(
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
appOpts servertypes.AppOptions) (servertypes.ExportedApp, error) {
var ethermintApp *app.EthermintApp
homePath, ok := appOpts.Get(flags.FlagHome).(string)
if !ok || homePath == "" {
return servertypes.ExportedApp{}, errors.New("application home not set")
}
if height != -1 {
ethermintApp = app.NewEthermintApp(logger, db, traceStore, false, map[int64]bool{}, homePath, 0, a.encCfg, appOpts)
if err := ethermintApp.LoadHeight(height); err != nil {
return servertypes.ExportedApp{}, err
}
} else {
ethermintApp = app.NewEthermintApp(logger, db, traceStore, true, map[int64]bool{}, homePath, 0, a.encCfg, appOpts)
}
return ethermintApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs)
}

View File

@ -2,30 +2,23 @@ package codec
import ( import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/std"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
cryptocodec "github.com/cosmos/ethermint/crypto/ethsecp256k1" cryptocodec "github.com/cosmos/ethermint/crypto/codec"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
) )
// MakeCodec registers the necessary types and interfaces for an sdk.App. This // RegisterLegacyAminoCodec registers Interfaces from types, crypto, and SDK std.
// codec is provided to all the modules the application depends on. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
// sdk.RegisterLegacyAminoCodec(cdc)
// NOTE: This codec will be deprecated in favor of AppCodec once all modules are cryptocodec.RegisterCrypto(cdc)
// migrated to protobuf. }
func MakeCodec(bm module.BasicManager) *codec.Codec {
cdc := codec.New() // RegisterInterfaces registers Interfaces from types, crypto, and SDK std.
func RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) {
bm.RegisterCodec(cdc) std.RegisterInterfaces(interfaceRegistry)
vesting.RegisterCodec(cdc) cryptocodec.RegisterInterfaces(interfaceRegistry)
sdk.RegisterCodec(cdc) ethermint.RegisterInterfaces(interfaceRegistry)
cryptocodec.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
ethermint.RegisterCodec(cdc)
keys.RegisterCodec(cdc) // temporary. Used to register keyring.Info
return cdc
} }

28
crypto/codec/amino.go Normal file
View File

@ -0,0 +1,28 @@
package codec
import (
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/legacy"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
)
// RegisterCrypto registers all crypto dependency types with the provided Amino
// codec.
func RegisterCrypto(cdc *codec.LegacyAmino) {
cdc.RegisterConcrete(&ethsecp256k1.PubKey{},
ethsecp256k1.PubKeyName, nil)
cdc.RegisterConcrete(&ethsecp256k1.PrivKey{},
ethsecp256k1.PrivKeyName, nil)
keyring.RegisterLegacyAminoCodec(cdc)
cryptocodec.RegisterCrypto(cdc)
// NOTE: update SDK's amino codec to include the ethsecp256k1 keys.
// DO NOT REMOVE unless deprecated on the SDK.
legacy.Cdc = cdc
keys.KeysCdc = cdc
}

13
crypto/codec/codec.go Normal file
View File

@ -0,0 +1,13 @@
package codec
import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
)
// RegisterInterfaces register the Ethermint key concrete types.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &ethsecp256k1.PubKey{})
}

View File

@ -1,27 +0,0 @@
package ethsecp256k1
import (
cryptoamino "github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
)
// CryptoCodec is the default amino codec used by ethermint
var CryptoCodec = codec.New()
func init() {
// replace the keyring codec with the ethermint crypto codec to prevent
// amino panics because of unregistered Priv/PubKey
keys.CryptoCdc = CryptoCodec
keys.RegisterCodec(CryptoCodec)
cryptoamino.RegisterAmino(CryptoCodec)
RegisterCodec(CryptoCodec)
}
// RegisterCodec registers all the necessary types with amino for the given
// codec.
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterConcrete(PubKey{}, PubKeyName, nil)
cdc.RegisterConcrete(PrivKey{}, PrivKeyName, nil)
}

View File

@ -3,17 +3,25 @@ package ethsecp256k1
import ( import (
"bytes" "bytes"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/subtle"
"fmt"
ethcrypto "github.com/ethereum/go-ethereum/crypto" ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
tmcrypto "github.com/tendermint/tendermint/crypto" tmcrypto "github.com/tendermint/tendermint/crypto"
) )
const ( const (
// PrivKeySize defines the size of the PrivKey bytes // PrivKeySize defines the size of the PrivKey bytes
PrivKeySize = 32 PrivKeySize = 32
// KeyType is the string constant for the EthSecp256k1 algorithm // PubKeySize defines the size of the PubKey bytes
PubKeySize = 33
// KeyType is the string constant for the Secp256k1 algorithm
KeyType = "eth_secp256k1" KeyType = "eth_secp256k1"
) )
@ -28,54 +36,85 @@ const (
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// secp256k1 Private Key // secp256k1 Private Key
var _ tmcrypto.PrivKey = PrivKey{} var (
_ cryptotypes.PrivKey = &PrivKey{}
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements _ codec.AminoMarshaler = &PrivKey{}
// Tendermint's PrivateKey interface. )
type PrivKey []byte
// GenerateKey generates a new random private key. It returns an error upon // GenerateKey generates a new random private key. It returns an error upon
// failure. // failure.
func GenerateKey() (PrivKey, error) { func GenerateKey() (*PrivKey, error) {
priv, err := ethcrypto.GenerateKey() priv, err := ethcrypto.GenerateKey()
if err != nil { if err != nil {
return PrivKey{}, err return nil, err
} }
return PrivKey(ethcrypto.FromECDSA(priv)), nil return &PrivKey{
Key: ethcrypto.FromECDSA(priv),
}, nil
}
// Bytes returns the byte representation of the ECDSA Private Key.
func (privKey PrivKey) Bytes() []byte {
return privKey.Key
} }
// PubKey returns the ECDSA private key's public key. // PubKey returns the ECDSA private key's public key.
func (privkey PrivKey) PubKey() tmcrypto.PubKey { func (privKey PrivKey) PubKey() cryptotypes.PubKey {
ecdsaPKey := privkey.ToECDSA() ecdsaPrivKey := privKey.ToECDSA()
return PubKey(ethcrypto.CompressPubkey(&ecdsaPKey.PublicKey)) return &PubKey{
Key: ethcrypto.CompressPubkey(&ecdsaPrivKey.PublicKey),
}
} }
// Bytes returns the raw ECDSA private key bytes. // Equals returns true if two ECDSA private keys are equal and false otherwise.
func (privkey PrivKey) Bytes() []byte { func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
return CryptoCodec.MustMarshalBinaryBare(privkey) return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1
}
// Type returns eth_secp256k1
func (privKey PrivKey) Type() string {
return KeyType
}
// MarshalAmino overrides Amino binary marshalling.
func (privKey PrivKey) MarshalAmino() ([]byte, error) {
return privKey.Key, nil
}
// UnmarshalAmino overrides Amino binary marshalling.
func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
if len(bz) != PrivKeySize {
return fmt.Errorf("invalid privkey size, expected %d got %d", PrivKeySize, len(bz))
}
privKey.Key = bz
return nil
}
// MarshalAminoJSON overrides Amino JSON marshalling.
func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
// just its contents (i.e. the key bytes).
return privKey.MarshalAmino()
}
// UnmarshalAminoJSON overrides Amino JSON marshalling.
func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
return privKey.UnmarshalAmino(bz)
} }
// Sign creates a recoverable ECDSA signature on the secp256k1 curve over the // Sign creates a recoverable ECDSA signature on the secp256k1 curve over the
// Keccak256 hash of the provided message. The produced signature is 65 bytes // Keccak256 hash of the provided message. The produced signature is 65 bytes
// where the last byte contains the recovery ID. // where the last byte contains the recovery ID.
func (privkey PrivKey) Sign(msg []byte) ([]byte, error) { func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
return ethcrypto.Sign(ethcrypto.Keccak256Hash(msg).Bytes(), privkey.ToECDSA()) return ethcrypto.Sign(ethcrypto.Keccak256Hash(msg).Bytes(), privKey.ToECDSA())
}
// Equals returns true if two ECDSA private keys are equal and false otherwise.
func (privkey PrivKey) Equals(other tmcrypto.PrivKey) bool {
if other, ok := other.(PrivKey); ok {
return bytes.Equal(privkey.Bytes(), other.Bytes())
}
return false
} }
// ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type. // ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type.
// The function will panic if the private key is invalid. // The function will panic if the private key is invalid.
func (privkey PrivKey) ToECDSA() *ecdsa.PrivateKey { func (privKey PrivKey) ToECDSA() *ecdsa.PrivateKey {
key, err := ethcrypto.ToECDSA(privkey) key, err := ethcrypto.ToECDSA(privKey.Bytes())
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -85,16 +124,15 @@ func (privkey PrivKey) ToECDSA() *ecdsa.PrivateKey {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// secp256k1 Public Key // secp256k1 Public Key
var _ tmcrypto.PubKey = (*PubKey)(nil) var (
_ cryptotypes.PubKey = &PubKey{}
// PubKey defines a type alias for an ecdsa.PublicKey that implements Tendermint's PubKey _ codec.AminoMarshaler = &PubKey{}
// interface. It represents the 33-byte compressed public key format. )
type PubKey []byte
// Address returns the address of the ECDSA public key. // Address returns the address of the ECDSA public key.
// The function will panic if the public key is invalid. // The function will panic if the public key is invalid.
func (key PubKey) Address() tmcrypto.Address { func (pubKey PubKey) Address() tmcrypto.Address {
pubk, err := ethcrypto.DecompressPubkey(key) pubk, err := ethcrypto.DecompressPubkey(pubKey.Key)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -103,33 +141,61 @@ func (key PubKey) Address() tmcrypto.Address {
} }
// Bytes returns the raw bytes of the ECDSA public key. // Bytes returns the raw bytes of the ECDSA public key.
// The function panics if the key cannot be marshaled to bytes. func (pubKey PubKey) Bytes() []byte {
func (key PubKey) Bytes() []byte { return pubKey.Key
bz, err := CryptoCodec.MarshalBinaryBare(key)
if err != nil {
panic(err)
}
return bz
} }
// VerifyBytes verifies that the ECDSA public key created a given signature over // String implements the fmt.Stringer interface.
func (pubKey PubKey) String() string {
return fmt.Sprintf("EthPubKeySecp256k1{%X}", pubKey.Key)
}
// Type returns eth_secp256k1
func (pubKey PubKey) Type() string {
return KeyType
}
// Equals returns true if the pubkey type is the same and their bytes are deeply equal.
func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool {
return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
}
// MarshalAmino overrides Amino binary marshalling.
func (pubKey PubKey) MarshalAmino() ([]byte, error) {
return pubKey.Key, nil
}
// UnmarshalAmino overrides Amino binary marshalling.
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
if len(bz) != PubKeySize {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
}
pubKey.Key = bz
return nil
}
// MarshalAminoJSON overrides Amino JSON marshalling.
func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) {
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
// just its contents (i.e. the key bytes).
return pubKey.MarshalAmino()
}
// UnmarshalAminoJSON overrides Amino JSON marshalling.
func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
return pubKey.UnmarshalAmino(bz)
}
// VerifySignature verifies that the ECDSA public key created a given signature over
// the provided message. It will calculate the Keccak256 hash of the message // the provided message. It will calculate the Keccak256 hash of the message
// prior to verification. // prior to verification.
func (key PubKey) VerifyBytes(msg []byte, sig []byte) bool { func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool {
if len(sig) == 65 { if len(sig) == 65 {
// remove recovery ID if contained in the signature // remove recovery ID if contained in the signature
sig = sig[:len(sig)-1] sig = sig[:len(sig)-1]
} }
// the signature needs to be in [R || S] format when provided to VerifySignature // the signature needs to be in [R || S] format when provided to VerifySignature
return secp256k1.VerifySignature(key, ethcrypto.Keccak256Hash(msg).Bytes(), sig) return secp256k1.VerifySignature(pubKey.Key, ethcrypto.Keccak256Hash(msg).Bytes(), sig)
}
// Equals returns true if two ECDSA public keys are equal and false otherwise.
func (key PubKey) Equals(other tmcrypto.PubKey) bool {
if other, ok := other.(PubKey); ok {
return bytes.Equal(key.Bytes(), other.Bytes())
}
return false
} }

View File

@ -1,22 +1,25 @@
package ethsecp256k1 package ethsecp256k1
import ( import (
"encoding/base64"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
ethcrypto "github.com/ethereum/go-ethereum/crypto" "github.com/cosmos/cosmos-sdk/codec"
ethsecp256k1 "github.com/ethereum/go-ethereum/crypto/secp256k1"
tmcrypto "github.com/tendermint/tendermint/crypto" ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
) )
func TestPrivKeyPrivKey(t *testing.T) { func TestPrivKey(t *testing.T) {
// validate type and equality // validate type and equality
privKey, err := GenerateKey() privKey, err := GenerateKey()
require.NoError(t, err) require.NoError(t, err)
require.True(t, privKey.Equals(privKey)) require.True(t, privKey.Equals(privKey))
require.Implements(t, (*tmcrypto.PrivKey)(nil), privKey) require.Implements(t, (*cryptotypes.PrivKey)(nil), privKey)
// validate inequality // validate inequality
privKey2, err := GenerateKey() privKey2, err := GenerateKey()
@ -31,20 +34,23 @@ func TestPrivKeyPrivKey(t *testing.T) {
// validate we can sign some bytes // validate we can sign some bytes
msg := []byte("hello world") msg := []byte("hello world")
sigHash := ethcrypto.Keccak256Hash(msg) sigHash := ethcrypto.Keccak256Hash(msg)
expectedSig, _ := ethsecp256k1.Sign(sigHash.Bytes(), privKey) expectedSig, err := secp256k1.Sign(sigHash.Bytes(), privKey.Bytes())
require.NoError(t, err)
sig, err := privKey.Sign(msg) sig, err := privKey.Sign(msg)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expectedSig, sig) require.Equal(t, expectedSig, sig)
} }
func TestPrivKeyPubKey(t *testing.T) { func TestPrivKey_PubKey(t *testing.T) {
privKey, err := GenerateKey() privKey, err := GenerateKey()
require.NoError(t, err) require.NoError(t, err)
// validate type and equality // validate type and equality
pubKey := privKey.PubKey().(PubKey) pubKey := &PubKey{
require.Implements(t, (*tmcrypto.PubKey)(nil), pubKey) Key: privKey.PubKey().Bytes(),
}
require.Implements(t, (*cryptotypes.PubKey)(nil), pubKey)
// validate inequality // validate inequality
privKey2, err := GenerateKey() privKey2, err := GenerateKey()
@ -56,6 +62,61 @@ func TestPrivKeyPubKey(t *testing.T) {
sig, err := privKey.Sign(msg) sig, err := privKey.Sign(msg)
require.NoError(t, err) require.NoError(t, err)
res := pubKey.VerifyBytes(msg, sig) res := pubKey.VerifySignature(msg, sig)
require.True(t, res) require.True(t, res)
} }
func TestMarshalAmino(t *testing.T) {
aminoCdc := codec.NewLegacyAmino()
privKey, err := GenerateKey()
require.NoError(t, err)
pubKey := privKey.PubKey().(*PubKey)
testCases := []struct {
desc string
msg codec.AminoMarshaler
typ interface{}
expBinary []byte
expJSON string
}{
{
"ethsecp256k1 private key",
privKey,
&PrivKey{},
append([]byte{32}, privKey.Bytes()...), // Length-prefixed.
"\"" + base64.StdEncoding.EncodeToString(privKey.Bytes()) + "\"",
},
{
"ethsecp256k1 public key",
pubKey,
&PubKey{},
append([]byte{33}, pubKey.Bytes()...), // Length-prefixed.
"\"" + base64.StdEncoding.EncodeToString(pubKey.Bytes()) + "\"",
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
// Do a round trip of encoding/decoding binary.
bz, err := aminoCdc.MarshalBinaryBare(tc.msg)
require.NoError(t, err)
require.Equal(t, tc.expBinary, bz)
err = aminoCdc.UnmarshalBinaryBare(bz, tc.typ)
require.NoError(t, err)
require.Equal(t, tc.msg, tc.typ)
// Do a round trip of encoding/decoding JSON.
bz, err = aminoCdc.MarshalJSON(tc.msg)
require.NoError(t, err)
require.Equal(t, tc.expJSON, string(bz))
err = aminoCdc.UnmarshalJSON(bz, tc.typ)
require.NoError(t, err)
require.Equal(t, tc.msg, tc.typ)
})
}
}

View File

@ -0,0 +1,504 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto
package ethsecp256k1
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// PubKey defines a type alias for an ecdsa.PublicKey that implements
// Tendermint's PubKey interface. It represents the 33-byte compressed public
// key format.
type PubKey struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (m *PubKey) Reset() { *m = PubKey{} }
func (*PubKey) ProtoMessage() {}
func (*PubKey) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbc409ef04b39de, []int{0}
}
func (m *PubKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PubKey.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PubKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_PubKey.Merge(m, src)
}
func (m *PubKey) XXX_Size() int {
return m.Size()
}
func (m *PubKey) XXX_DiscardUnknown() {
xxx_messageInfo_PubKey.DiscardUnknown(m)
}
var xxx_messageInfo_PubKey proto.InternalMessageInfo
func (m *PubKey) GetKey() []byte {
if m != nil {
return m.Key
}
return nil
}
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
// Tendermint's PrivateKey interface.
type PrivKey struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (m *PrivKey) Reset() { *m = PrivKey{} }
func (m *PrivKey) String() string { return proto.CompactTextString(m) }
func (*PrivKey) ProtoMessage() {}
func (*PrivKey) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbc409ef04b39de, []int{1}
}
func (m *PrivKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PrivKey.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PrivKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_PrivKey.Merge(m, src)
}
func (m *PrivKey) XXX_Size() int {
return m.Size()
}
func (m *PrivKey) XXX_DiscardUnknown() {
xxx_messageInfo_PrivKey.DiscardUnknown(m)
}
var xxx_messageInfo_PrivKey proto.InternalMessageInfo
func (m *PrivKey) GetKey() []byte {
if m != nil {
return m.Key
}
return nil
}
func init() {
proto.RegisterType((*PubKey)(nil), "ethermint.crypto.v1alpha1.ethsecp256k1.PubKey")
proto.RegisterType((*PrivKey)(nil), "ethermint.crypto.v1alpha1.ethsecp256k1.PrivKey")
}
func init() {
proto.RegisterFile("ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto", fileDescriptor_8bbc409ef04b39de)
}
var fileDescriptor_8bbc409ef04b39de = []byte{
// 201 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0x4c, 0x2d, 0xc9, 0x48,
0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x33, 0x4c,
0xcc, 0x29, 0xc8, 0x48, 0x34, 0xd4, 0x4f, 0x2d, 0xc9, 0x28, 0x4e, 0x4d, 0x2e, 0x30, 0x32, 0x35,
0xcb, 0x36, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x83,
0x6b, 0xd1, 0x83, 0x68, 0xd1, 0x83, 0x69, 0xd1, 0x43, 0xd6, 0x22, 0x25, 0x92, 0x9e, 0x9f, 0x9e,
0x0f, 0xd6, 0xa2, 0x0f, 0x62, 0x41, 0x74, 0x2b, 0x29, 0x70, 0xb1, 0x05, 0x94, 0x26, 0x79, 0xa7,
0x56, 0x0a, 0x09, 0x70, 0x31, 0x67, 0xa7, 0x56, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81,
0x98, 0x56, 0x2c, 0x33, 0x16, 0xc8, 0x33, 0x28, 0x49, 0x73, 0xb1, 0x07, 0x14, 0x65, 0x96, 0x61,
0x55, 0xe2, 0xe4, 0x79, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31,
0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0xfa, 0xe9,
0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5,
0xfa, 0x18, 0x7e, 0x43, 0x76, 0x5f, 0x12, 0x1b, 0xd8, 0x41, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
0xff, 0x06, 0xa5, 0x4e, 0xba, 0x03, 0x01, 0x00, 0x00,
}
func (m *PubKey) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PubKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *PrivKey) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PrivKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintKeys(dAtA []byte, offset int, v uint64) int {
offset -= sovKeys(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *PubKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
n += 1 + l + sovKeys(uint64(l))
}
return n
}
func (m *PrivKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
n += 1 + l + sovKeys(uint64(l))
}
return n
}
func sovKeys(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozKeys(x uint64) (n int) {
return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *PubKey) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PubKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthKeys
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthKeys
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PrivKey) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PrivKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PrivKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthKeys
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthKeys
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipKeys(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKeys
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKeys
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKeys
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthKeys
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupKeys
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthKeys
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthKeys = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowKeys = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupKeys = fmt.Errorf("proto: unexpected end of group")
)

View File

@ -1,96 +1,105 @@
package hd package hd
import ( import (
"fmt"
"github.com/pkg/errors"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcutil/hdkeychain"
"github.com/tyler-smith/go-bip39" bip39 "github.com/tyler-smith/go-bip39"
ethaccounts "github.com/ethereum/go-ethereum/accounts" ethaccounts "github.com/ethereum/go-ethereum/accounts"
ethcrypto "github.com/ethereum/go-ethereum/crypto" ethcrypto "github.com/ethereum/go-ethereum/crypto"
tmcrypto "github.com/tendermint/tendermint/crypto" "github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" "github.com/cosmos/ethermint/crypto/ethsecp256k1"
) )
const ( const (
// EthSecp256k1 defines the ECDSA secp256k1 used on Ethereum // EthSecp256k1Type defines the ECDSA secp256k1 used on Ethereum
EthSecp256k1 = keys.SigningAlgo(ethsecp256k1.KeyType) EthSecp256k1Type = hd.PubKeyType(ethsecp256k1.KeyType)
) )
// SupportedAlgorithms defines the list of signing algorithms used on Ethermint: var (
// - eth_secp256k1 (Ethereum) // SupportedAlgorithms defines the list of signing algorithms used on Ethermint:
// - secp256k1 (Tendermint) // - eth_secp256k1 (Ethereum)
var SupportedAlgorithms = []keys.SigningAlgo{EthSecp256k1, keys.Secp256k1} // - secp256k1 (Tendermint)
SupportedAlgorithms = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
// SupportedAlgorithmsLedger defines the list of signing algorithms used on Ethermint for the Ledger device:
// - eth_secp256k1 (Ethereum)
// - secp256k1 (Tendermint)
SupportedAlgorithmsLedger = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
)
// EthSecp256k1Options defines a keys options for the ethereum Secp256k1 curve. // EthSecp256k1Option defines a function keys options for the ethereum Secp256k1 curve.
func EthSecp256k1Options() []keys.KeybaseOption { // It supports eth_secp256k1 and secp256k1 keys for accounts.
return []keys.KeybaseOption{ func EthSecp256k1Option() keyring.Option {
keys.WithKeygenFunc(EthermintKeygenFunc), return func(options *keyring.Options) {
keys.WithDeriveFunc(DeriveKey), options.SupportedAlgos = SupportedAlgorithms
keys.WithSupportedAlgos(SupportedAlgorithms), options.SupportedAlgosLedger = SupportedAlgorithmsLedger
keys.WithSupportedAlgosLedger(SupportedAlgorithms),
} }
} }
func DeriveKey(mnemonic, bip39Passphrase, hdPath string, algo keys.SigningAlgo) ([]byte, error) { var (
switch algo { _ keyring.SignatureAlgo = EthSecp256k1
case keys.Secp256k1:
return keys.StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo) // EthSecp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
case EthSecp256k1: EthSecp256k1 = ethSecp256k1Algo{}
return DeriveSecp256k1(mnemonic, bip39Passphrase, hdPath) )
default:
return nil, errors.Wrap(keys.ErrUnsupportedSigningAlgo, string(algo)) type ethSecp256k1Algo struct {
}
} }
// EthermintKeygenFunc is the key generation function to generate secp256k1 ToECDSA // Name returns eth_secp256k1
// from ethereum. func (s ethSecp256k1Algo) Name() hd.PubKeyType {
func EthermintKeygenFunc(bz []byte, algo keys.SigningAlgo) (tmcrypto.PrivKey, error) { return EthSecp256k1Type
if algo != EthSecp256k1 {
return nil, fmt.Errorf("signing algorithm must be %s, got %s", EthSecp256k1, algo)
}
return ethsecp256k1.PrivKey(bz), nil
} }
// DeriveSecp256k1 derives and returns the eth_secp256k1 private key for the given mnemonic and HD path. // Derive derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
func DeriveSecp256k1(mnemonic, bip39Passphrase, path string) ([]byte, error) { func (s ethSecp256k1Algo) Derive() hd.DeriveFn {
hdpath, err := ethaccounts.ParseDerivationPath(path) return func(mnemonic string, bip39Passphrase, path string) ([]byte, error) {
if err != nil { hdpath, err := ethaccounts.ParseDerivationPath(path)
return nil, err
}
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}
masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
if err != nil {
return nil, err
}
key := masterKey
for _, n := range hdpath {
key, err = key.Child(n)
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
privateKey, err := key.ECPrivKey() seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil { if err != nil {
return nil, err return nil, err
} }
privateKeyECDSA := privateKey.ToECDSA() masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
derivedKey := ethsecp256k1.PrivKey(ethcrypto.FromECDSA(privateKeyECDSA)) if err != nil {
return derivedKey, nil return nil, err
}
key := masterKey
for _, n := range hdpath {
key, err = key.Child(n)
if err != nil {
return nil, err
}
}
privateKey, err := key.ECPrivKey()
if err != nil {
return nil, err
}
privateKeyECDSA := privateKey.ToECDSA()
derivedKey := ethcrypto.FromECDSA(privateKeyECDSA)
return derivedKey, nil
}
}
// Generate generates a eth_secp256k1 private key from the given bytes.
func (s ethSecp256k1Algo) Generate() hd.GenerateFn {
return func(bz []byte) cryptotypes.PrivKey {
var bzArr = make([]byte, ethsecp256k1.PrivKeySize)
copy(bzArr, bz)
return &ethsecp256k1.PrivKey{Key: bzArr}
}
} }

View File

@ -7,110 +7,52 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
hdwallet "github.com/miguelmota/go-ethereum-hdwallet" hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
"github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/tests"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" cryptocodec "github.com/cosmos/ethermint/crypto/codec"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
) )
func TestEthermintKeygenFunc(t *testing.T) { func init() {
privkey, err := ethsecp256k1.GenerateKey() amino := codec.NewLegacyAmino()
require.NoError(t, err) cryptocodec.RegisterCrypto(amino)
testCases := []struct {
name string
privKey []byte
algo keys.SigningAlgo
expPass bool
}{
{
"valid ECDSA privKey",
ethcrypto.FromECDSA(privkey.ToECDSA()),
EthSecp256k1,
true,
},
{
"nil bytes, valid algo",
nil,
EthSecp256k1,
true,
},
{
"empty bytes, valid algo",
[]byte{},
EthSecp256k1,
true,
},
{
"invalid algo",
nil,
keys.MultiAlgo,
false,
},
}
for _, tc := range testCases {
privkey, err := EthermintKeygenFunc(tc.privKey, tc.algo)
if tc.expPass {
require.NoError(t, err, tc.name)
} else {
require.Error(t, err, tc.name)
require.Nil(t, privkey, tc.name)
}
}
} }
func TestKeyring(t *testing.T) { func TestKeyring(t *testing.T) {
dir, cleanup := tests.NewTestCaseDir(t) dir := t.TempDir()
mockIn := strings.NewReader("") mockIn := strings.NewReader("")
t.Cleanup(cleanup)
kr, err := keys.NewKeyring("ethermint", keys.BackendTest, dir, mockIn, EthSecp256k1Options()...) kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, EthSecp256k1Option())
require.NoError(t, err) require.NoError(t, err)
// fail in retrieving key // fail in retrieving key
info, err := kr.Get("foo") info, err := kr.Key("foo")
require.Error(t, err) require.Error(t, err)
require.Nil(t, info) require.Nil(t, info)
mockIn.Reset("password\npassword\n") mockIn.Reset("password\npassword\n")
info, mnemonic, err := kr.CreateMnemonic("foo", keys.English, ethermint.BIP44HDPath, EthSecp256k1) info, mnemonic, err := kr.NewMnemonic("foo", keyring.English, ethermint.BIP44HDPath, EthSecp256k1)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, mnemonic) require.NotEmpty(t, mnemonic)
require.Equal(t, "foo", info.GetName()) require.Equal(t, "foo", info.GetName())
require.Equal(t, "local", info.GetType().String()) require.Equal(t, "local", info.GetType().String())
require.Equal(t, EthSecp256k1, info.GetAlgo()) require.Equal(t, EthSecp256k1Type, info.GetAlgo())
params := *hd.NewFundraiserParams(0, ethermint.Bip44CoinType, 0) hdPath := ethermint.BIP44HDPath
hdPath := params.String()
bz, err := DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.Secp256k1) bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, hdPath)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, bz) require.NotEmpty(t, bz)
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, hdPath) wrongBz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, "/wrong/hdPath")
require.NoError(t, err)
require.NotEmpty(t, bz)
bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.SigningAlgo(""))
require.Error(t, err) require.Error(t, err)
require.Empty(t, bz) require.Empty(t, wrongBz)
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, "/wrong/hdPath") privkey := EthSecp256k1.Generate()(bz)
require.Error(t, err)
require.Empty(t, bz)
bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, bz)
privkey := ethsecp256k1.PrivKey(bz)
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes()) addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
wallet, err := hdwallet.NewFromMnemonic(mnemonic) wallet, err := hdwallet.NewFromMnemonic(mnemonic)
@ -126,25 +68,20 @@ func TestKeyring(t *testing.T) {
func TestDerivation(t *testing.T) { func TestDerivation(t *testing.T) {
mnemonic := "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret" mnemonic := "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
bz, err := DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, ethermint.BIP44HDPath) bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, ethermint.BIP44HDPath)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, bz) require.NotEmpty(t, bz)
badBz, err := DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, "44'/60'/0'/0/0") badBz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, "44'/60'/0'/0/0")
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, badBz) require.NotEmpty(t, badBz)
require.NotEqual(t, bz, badBz) require.NotEqual(t, bz, badBz)
privkey, err := EthermintKeygenFunc(bz, EthSecp256k1) privkey := EthSecp256k1.Generate()(bz)
require.NoError(t, err) badPrivKey := EthSecp256k1.Generate()(badBz)
require.NotEmpty(t, privkey)
badPrivKey, err := EthermintKeygenFunc(badBz, EthSecp256k1) require.False(t, privkey.Equals(badPrivKey))
require.NoError(t, err)
require.NotEmpty(t, badPrivKey)
require.NotEqual(t, privkey, badPrivKey)
wallet, err := hdwallet.NewFromMnemonic(mnemonic) wallet, err := hdwallet.NewFromMnemonic(mnemonic)
require.NoError(t, err) require.NoError(t, err)

749
docs/core/proto-docs.md Normal file
View File

@ -0,0 +1,749 @@
<!-- This file is auto-generated. Please do not modify it yourself. -->
# Protobuf Documentation
<a name="top"></a>
## Table of Contents
- [ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto](#ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto)
- [PrivKey](#ethermint.crypto.v1alpha1.ethsecp256k1.PrivKey)
- [PubKey](#ethermint.crypto.v1alpha1.ethsecp256k1.PubKey)
- [ethermint/evm/v1alpha1/evm.proto](#ethermint/evm/v1alpha1/evm.proto)
- [ChainConfig](#ethermint.evm.v1alpha1.ChainConfig)
- [Log](#ethermint.evm.v1alpha1.Log)
- [Params](#ethermint.evm.v1alpha1.Params)
- [State](#ethermint.evm.v1alpha1.State)
- [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs)
- [ethermint/evm/v1alpha1/genesis.proto](#ethermint/evm/v1alpha1/genesis.proto)
- [GenesisAccount](#ethermint.evm.v1alpha1.GenesisAccount)
- [GenesisState](#ethermint.evm.v1alpha1.GenesisState)
- [ethermint/evm/v1alpha1/query.proto](#ethermint/evm/v1alpha1/query.proto)
- [QueryAccountRequest](#ethermint.evm.v1alpha1.QueryAccountRequest)
- [QueryAccountResponse](#ethermint.evm.v1alpha1.QueryAccountResponse)
- [QueryBalanceRequest](#ethermint.evm.v1alpha1.QueryBalanceRequest)
- [QueryBalanceResponse](#ethermint.evm.v1alpha1.QueryBalanceResponse)
- [QueryBlockBloomRequest](#ethermint.evm.v1alpha1.QueryBlockBloomRequest)
- [QueryBlockBloomResponse](#ethermint.evm.v1alpha1.QueryBlockBloomResponse)
- [QueryBlockLogsRequest](#ethermint.evm.v1alpha1.QueryBlockLogsRequest)
- [QueryBlockLogsResponse](#ethermint.evm.v1alpha1.QueryBlockLogsResponse)
- [QueryCodeRequest](#ethermint.evm.v1alpha1.QueryCodeRequest)
- [QueryCodeResponse](#ethermint.evm.v1alpha1.QueryCodeResponse)
- [QueryParamsRequest](#ethermint.evm.v1alpha1.QueryParamsRequest)
- [QueryParamsResponse](#ethermint.evm.v1alpha1.QueryParamsResponse)
- [QueryStorageRequest](#ethermint.evm.v1alpha1.QueryStorageRequest)
- [QueryStorageResponse](#ethermint.evm.v1alpha1.QueryStorageResponse)
- [QueryTxLogsRequest](#ethermint.evm.v1alpha1.QueryTxLogsRequest)
- [QueryTxLogsResponse](#ethermint.evm.v1alpha1.QueryTxLogsResponse)
- [Query](#ethermint.evm.v1alpha1.Query)
- [ethermint/evm/v1alpha1/tx.proto](#ethermint/evm/v1alpha1/tx.proto)
- [EIP155Signer](#ethermint.evm.v1alpha1.EIP155Signer)
- [MsgEthereumTx](#ethermint.evm.v1alpha1.MsgEthereumTx)
- [MsgEthereumTxResponse](#ethermint.evm.v1alpha1.MsgEthereumTxResponse)
- [Recipient](#ethermint.evm.v1alpha1.Recipient)
- [SigCache](#ethermint.evm.v1alpha1.SigCache)
- [TxData](#ethermint.evm.v1alpha1.TxData)
- [Msg](#ethermint.evm.v1alpha1.Msg)
- [ethermint/types/v1alpha1/account.proto](#ethermint/types/v1alpha1/account.proto)
- [EthAccount](#ethermint.types.v1alpha1.EthAccount)
- [Scalar Value Types](#scalar-value-types)
<a name="ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## ethermint/crypto/v1alpha1/ethsecp256k1/keys.proto
<a name="ethermint.crypto.v1alpha1.ethsecp256k1.PrivKey"></a>
### PrivKey
PrivKey defines a type alias for an ecdsa.PrivateKey that implements
Tendermint's PrivateKey interface.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `key` | [bytes](#bytes) | | |
<a name="ethermint.crypto.v1alpha1.ethsecp256k1.PubKey"></a>
### PubKey
PubKey defines a type alias for an ecdsa.PublicKey that implements
Tendermint's PubKey interface. It represents the 33-byte compressed public
key format.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `key` | [bytes](#bytes) | | |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="ethermint/evm/v1alpha1/evm.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## ethermint/evm/v1alpha1/evm.proto
<a name="ethermint.evm.v1alpha1.ChainConfig"></a>
### ChainConfig
ChainConfig defines the Ethereum ChainConfig parameters using sdk.Int values
instead of big.Int.
NOTE 1: Since empty/uninitialized Ints (i.e with a nil big.Int value) are
parsed to zero, we need to manually specify that negative Int values will be
considered as nil. See getBlockValue for reference.
NOTE 2: This type is not a configurable Param since the SDK does not allow
for validation against a previous stored parameter values or the current
block height (retrieved from context). If you want to update the config
values, use an software upgrade procedure.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `homestead_block` | [string](#string) | | Homestead switch block (< 0 no fork, 0 = already homestead) |
| `dao_fork_block` | [string](#string) | | TheDAO hard-fork switch block (< 0 no fork) |
| `dao_fork_support` | [bool](#bool) | | Whether the nodes supports or opposes the DAO hard-fork |
| `eip150_block` | [string](#string) | | EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (< 0 no fork) |
| `eip150_hash` | [string](#string) | | EIP150 HF hash (needed for header only clients as only gas pricing changed) |
| `eip155_block` | [string](#string) | | EIP155Block HF block |
| `eip158_block` | [string](#string) | | EIP158 HF block |
| `byzantium_block` | [string](#string) | | Byzantium switch block (< 0 no fork, 0 = already on byzantium) |
| `constantinople_block` | [string](#string) | | Constantinople switch block (< 0 no fork, 0 = already activated) |
| `petersburg_block` | [string](#string) | | Petersburg switch block (< 0 same as Constantinople) |
| `istanbul_block` | [string](#string) | | Istanbul switch block (< 0 no fork, 0 = already on istanbul) |
| `muir_glacier_block` | [string](#string) | | Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated) |
| `yolo_v2_block` | [string](#string) | | YOLO v2: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet) |
| `ewasm_block` | [string](#string) | | EWASM switch block (< 0 no fork, 0 = already activated) |
<a name="ethermint.evm.v1alpha1.Log"></a>
### Log
Log represents an protobuf compatible Ethereum Log that defines a contract
log event. These events are generated by the LOG opcode and stored/indexed by
the node.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address of the contract that generated the event |
| `topics` | [string](#string) | repeated | list of topics provided by the contract. |
| `data` | [bytes](#bytes) | | supplied by the contract, usually ABI-encoded |
| `block_number` | [uint64](#uint64) | | block in which the transaction was included |
| `tx_hash` | [string](#string) | | hash of the transaction |
| `tx_index` | [uint64](#uint64) | | index of the transaction in the block |
| `block_hash` | [string](#string) | | hash of the block in which the transaction was included |
| `index` | [uint64](#uint64) | | index of the log in the block |
| `removed` | [bool](#bool) | | The Removed field is true if this log was reverted due to a chain reorganisation. You must pay attention to this field if you receive logs through a filter query. |
<a name="ethermint.evm.v1alpha1.Params"></a>
### Params
Params defines the EVM module parameters
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `evm_denom` | [string](#string) | | evm_denom represents the token denomination used to run the EVM state transitions. |
| `enable_create` | [bool](#bool) | | enable_create toggles state transitions that use the vm.Create function |
| `enable_call` | [bool](#bool) | | enable_call toggles state transitions that use the vm.Call function |
| `extra_eips` | [int64](#int64) | repeated | extra_eips defines the additional EIPs for the vm.Config |
<a name="ethermint.evm.v1alpha1.State"></a>
### State
State represents a single Storage key value pair item.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `key` | [string](#string) | | |
| `value` | [string](#string) | | |
<a name="ethermint.evm.v1alpha1.TransactionLogs"></a>
### TransactionLogs
TransactionLogs define the logs generated from a transaction execution
with a given hash. It it used for import/export data as transactions are not
persisted on blockchain state after an upgrade.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `hash` | [string](#string) | | |
| `logs` | [Log](#ethermint.evm.v1alpha1.Log) | repeated | |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="ethermint/evm/v1alpha1/genesis.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## ethermint/evm/v1alpha1/genesis.proto
<a name="ethermint.evm.v1alpha1.GenesisAccount"></a>
### GenesisAccount
GenesisAccount defines an account to be initialized in the genesis state.
Its main difference between with Geth's GenesisAccount is that it uses a
custom storage type and that it doesn't contain the private key field.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address defines an ethereum hex formated address of an account |
| `code` | [string](#string) | | code defines the hex bytes of the account code. |
| `storage` | [State](#ethermint.evm.v1alpha1.State) | repeated | storage defines the set of state key values for the account. |
<a name="ethermint.evm.v1alpha1.GenesisState"></a>
### GenesisState
GenesisState defines the evm module's genesis state.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `accounts` | [GenesisAccount](#ethermint.evm.v1alpha1.GenesisAccount) | repeated | accounts is an array containing the ethereum genesis accounts. |
| `chain_config` | [ChainConfig](#ethermint.evm.v1alpha1.ChainConfig) | | chain_config defines the Ethereum chain configuration. |
| `params` | [Params](#ethermint.evm.v1alpha1.Params) | | params defines all the paramaters of the module. |
| `txs_logs` | [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs) | repeated | |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="ethermint/evm/v1alpha1/query.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## ethermint/evm/v1alpha1/query.proto
<a name="ethermint.evm.v1alpha1.QueryAccountRequest"></a>
### QueryAccountRequest
QueryAccountRequest is the request type for the Query/Account RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address is the ethereum hex address to query the account for. |
<a name="ethermint.evm.v1alpha1.QueryAccountResponse"></a>
### QueryAccountResponse
QueryAccountResponse is the response type for the Query/Account RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `balance` | [string](#string) | | balance is the balance of the EVM denomination. |
| `code_hash` | [bytes](#bytes) | | code_hash is the code bytes from the EOA. |
| `nonce` | [uint64](#uint64) | | nonce is the account's sequence number. |
<a name="ethermint.evm.v1alpha1.QueryBalanceRequest"></a>
### QueryBalanceRequest
QueryBalanceRequest is the request type for the Query/Balance RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address is the ethereum hex address to query the balance for. |
<a name="ethermint.evm.v1alpha1.QueryBalanceResponse"></a>
### QueryBalanceResponse
QueryBalanceResponse is the response type for the Query/Balance RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `balance` | [string](#string) | | balance is the balance of the EVM denomination. |
<a name="ethermint.evm.v1alpha1.QueryBlockBloomRequest"></a>
### QueryBlockBloomRequest
QueryBlockBloomRequest is the request type for the Query/BlockBloom RPC
method.
<a name="ethermint.evm.v1alpha1.QueryBlockBloomResponse"></a>
### QueryBlockBloomResponse
QueryBlockBloomResponse is the response type for the Query/BlockBloom RPC
method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `bloom` | [bytes](#bytes) | | bloom represents bloom filter for the given block hash. |
<a name="ethermint.evm.v1alpha1.QueryBlockLogsRequest"></a>
### QueryBlockLogsRequest
QueryBlockLogsRequest is the request type for the Query/BlockLogs RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `hash` | [string](#string) | | hash is the block hash to query the logs for. |
<a name="ethermint.evm.v1alpha1.QueryBlockLogsResponse"></a>
### QueryBlockLogsResponse
QueryTxLogs is the response type for the Query/BlockLogs RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `tx_logs` | [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs) | repeated | logs represents the ethereum logs generated at the given block hash. |
<a name="ethermint.evm.v1alpha1.QueryCodeRequest"></a>
### QueryCodeRequest
QueryCodeRequest is the request type for the Query/Code RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address is the ethereum hex address to query the code for. |
<a name="ethermint.evm.v1alpha1.QueryCodeResponse"></a>
### QueryCodeResponse
QueryCodeResponse is the response type for the Query/Code RPC
method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `code` | [bytes](#bytes) | | code represents the code bytes from an ethereum address. |
<a name="ethermint.evm.v1alpha1.QueryParamsRequest"></a>
### QueryParamsRequest
QueryParamsRequest defines the request type for querying x/evm parameters.
<a name="ethermint.evm.v1alpha1.QueryParamsResponse"></a>
### QueryParamsResponse
QueryParamsResponse defines the response type for querying x/evm parameters.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `params` | [Params](#ethermint.evm.v1alpha1.Params) | | params define the evm module parameters. |
<a name="ethermint.evm.v1alpha1.QueryStorageRequest"></a>
### QueryStorageRequest
QueryStorageRequest is the request type for the Query/Storage RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address is the ethereum hex address to query the storage state for. |
| `key` | [string](#string) | | key defines the key of the storage state |
<a name="ethermint.evm.v1alpha1.QueryStorageResponse"></a>
### QueryStorageResponse
QueryStorageResponse is the response type for the Query/Storage RPC
method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `value` | [string](#string) | | key defines the storage state value hash associated with the given key. |
<a name="ethermint.evm.v1alpha1.QueryTxLogsRequest"></a>
### QueryTxLogsRequest
QueryTxLogsRequest is the request type for the Query/TxLogs RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `hash` | [string](#string) | | hash is the ethereum transaction hex hash to query the logs for. |
<a name="ethermint.evm.v1alpha1.QueryTxLogsResponse"></a>
### QueryTxLogsResponse
QueryTxLogs is the response type for the Query/TxLogs RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `logs` | [Log](#ethermint.evm.v1alpha1.Log) | repeated | logs represents the ethereum logs generated from the given transaction. |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<a name="ethermint.evm.v1alpha1.Query"></a>
### Query
Query defines the gRPC querier service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `Account` | [QueryAccountRequest](#ethermint.evm.v1alpha1.QueryAccountRequest) | [QueryAccountResponse](#ethermint.evm.v1alpha1.QueryAccountResponse) | Account queries an Ethereum account. | GET|/ethermint/evm/v1alpha1/account/{address}|
| `Balance` | [QueryBalanceRequest](#ethermint.evm.v1alpha1.QueryBalanceRequest) | [QueryBalanceResponse](#ethermint.evm.v1alpha1.QueryBalanceResponse) | Balance queries the balance of a the EVM denomination for a single EthAccount. | GET|/ethermint/evm/v1alpha1/balances/{address}|
| `Storage` | [QueryStorageRequest](#ethermint.evm.v1alpha1.QueryStorageRequest) | [QueryStorageResponse](#ethermint.evm.v1alpha1.QueryStorageResponse) | Storage queries the balance of all coins for a single account. | GET|/ethermint/evm/v1alpha1/storage/{address}/{key}|
| `Code` | [QueryCodeRequest](#ethermint.evm.v1alpha1.QueryCodeRequest) | [QueryCodeResponse](#ethermint.evm.v1alpha1.QueryCodeResponse) | Code queries the balance of all coins for a single account. | GET|/ethermint/evm/v1alpha1/codes/{address}|
| `TxLogs` | [QueryTxLogsRequest](#ethermint.evm.v1alpha1.QueryTxLogsRequest) | [QueryTxLogsResponse](#ethermint.evm.v1alpha1.QueryTxLogsResponse) | TxLogs queries ethereum logs from a transaction. | GET|/ethermint/evm/v1alpha1/tx_logs/{hash}|
| `BlockLogs` | [QueryBlockLogsRequest](#ethermint.evm.v1alpha1.QueryBlockLogsRequest) | [QueryBlockLogsResponse](#ethermint.evm.v1alpha1.QueryBlockLogsResponse) | BlockLogs queries all the ethereum logs for a given block hash. | GET|/ethermint/evm/v1alpha1/block_logs/{hash}|
| `BlockBloom` | [QueryBlockBloomRequest](#ethermint.evm.v1alpha1.QueryBlockBloomRequest) | [QueryBlockBloomResponse](#ethermint.evm.v1alpha1.QueryBlockBloomResponse) | BlockBloom queries the block bloom filter bytes at a given height. | GET|/ethermint/evm/v1alpha1/block_bloom|
| `Params` | [QueryParamsRequest](#ethermint.evm.v1alpha1.QueryParamsRequest) | [QueryParamsResponse](#ethermint.evm.v1alpha1.QueryParamsResponse) | Params queries the parameters of x/evm module. | GET|/ethermint/evm/v1alpha1/params|
<!-- end services -->
<a name="ethermint/evm/v1alpha1/tx.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## ethermint/evm/v1alpha1/tx.proto
<a name="ethermint.evm.v1alpha1.EIP155Signer"></a>
### EIP155Signer
EIP155Transaction implements Signer using the EIP155 rules.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `chain_id` | [bytes](#bytes) | | |
| `chain_id_mul` | [bytes](#bytes) | | |
<a name="ethermint.evm.v1alpha1.MsgEthereumTx"></a>
### MsgEthereumTx
MsgEthereumTx encapsulates an Ethereum transaction as an SDK message.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `data` | [TxData](#ethermint.evm.v1alpha1.TxData) | | |
| `size` | [double](#double) | | caches |
| `from` | [SigCache](#ethermint.evm.v1alpha1.SigCache) | | |
<a name="ethermint.evm.v1alpha1.MsgEthereumTxResponse"></a>
### MsgEthereumTxResponse
MsgEthereumTxResponse defines the Msg/EthereumTx response type.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `contract_address` | [string](#string) | | contract_address contains the ethereum address of the created contract (if any). If the state transition is an evm.Call, the contract address will be empty. |
| `bloom` | [bytes](#bytes) | | bloom represents the bloom filter bytes |
| `tx_logs` | [TransactionLogs](#ethermint.evm.v1alpha1.TransactionLogs) | | tx_logs contains the transaction hash and the proto-compatible ethereum logs. |
| `ret` | [bytes](#bytes) | | ret defines the bytes from the execution. |
<a name="ethermint.evm.v1alpha1.Recipient"></a>
### Recipient
Recipient defines a protobuf-compatible wrapper for an Ethereum address
pointer. It is required for RLP encoding.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address defines the hex-formated ethereum address of the recipient |
<a name="ethermint.evm.v1alpha1.SigCache"></a>
### SigCache
SigCache is used to cache the derived sender and contains the signer used
to derive it.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `signer` | [EIP155Signer](#ethermint.evm.v1alpha1.EIP155Signer) | | |
| `address` | [string](#string) | | |
<a name="ethermint.evm.v1alpha1.TxData"></a>
### TxData
TxData implements the Ethereum transaction data structure. It is used
solely as intended in Ethereum abiding by the protocol.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `nonce` | [uint64](#uint64) | | nonce corresponds to the account nonce (transaction sequence). |
| `price` | [string](#string) | | price defines the unsigned integer value of the gas price in bytes. |
| `gas` | [uint64](#uint64) | | gas defines the gas limit defined for the transaction. |
| `to` | [Recipient](#ethermint.evm.v1alpha1.Recipient) | | |
| `value` | [string](#string) | | value defines the unsigned integer value of the transaction amount. |
| `input` | [bytes](#bytes) | | input defines the data payload bytes of the transaction. |
| `v` | [bytes](#bytes) | | v defines the signature value |
| `r` | [bytes](#bytes) | | r defines the signature value |
| `s` | [bytes](#bytes) | | s define the signature value |
| `hash` | [string](#string) | | hash defines the tx data hash, which is only used when marshaling to JSON. |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<a name="ethermint.evm.v1alpha1.Msg"></a>
### Msg
Msg defines the evm Msg service.
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `EthereumTx` | [MsgEthereumTx](#ethermint.evm.v1alpha1.MsgEthereumTx) | [MsgEthereumTxResponse](#ethermint.evm.v1alpha1.MsgEthereumTxResponse) | EthereumTx defines a method submitting Ethereum transactions. | |
<!-- end services -->
<a name="ethermint/types/v1alpha1/account.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## ethermint/types/v1alpha1/account.proto
<a name="ethermint.types.v1alpha1.EthAccount"></a>
### EthAccount
EthAccount implements the authtypes.AccountI interface and embeds an
authtypes.BaseAccount type. It is compatible with the auth AccountKeeper.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `base_account` | [cosmos.auth.v1beta1.BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | |
| `code_hash` | [bytes](#bytes) | | |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
## Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- |
| <a name="double" /> double | | double | double | float | float64 | double | float | Float |
| <a name="float" /> float | | float | float | float | float32 | float | float | Float |
| <a name="int32" /> int32 | Uses variable-length encoding. Inefficient for encoding negative numbers if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="int64" /> int64 | Uses variable-length encoding. Inefficient for encoding negative numbers if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="uint32" /> uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| <a name="uint64" /> uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| <a name="sint32" /> sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="sint64" /> sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="fixed32" /> fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| <a name="fixed64" /> fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| <a name="sfixed32" /> sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| <a name="sfixed64" /> sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| <a name="bool" /> bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass |
| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |

105
docs/protodoc-markdown.tmpl Normal file
View File

@ -0,0 +1,105 @@
<!-- This file is auto-generated. Please do not modify it yourself. -->
# Protobuf Documentation
<a name="top"></a>
## Table of Contents
{{range .Files}}
{{$file_name := .Name}}- [{{.Name}}](#{{.Name}})
{{- if .Messages }}
{{range .Messages}} - [{{.LongName}}](#{{.FullName}})
{{end}}
{{- end -}}
{{- if .Enums }}
{{range .Enums}} - [{{.LongName}}](#{{.FullName}})
{{end}}
{{- end -}}
{{- if .Extensions }}
{{range .Extensions}} - [File-level Extensions](#{{$file_name}}-extensions)
{{end}}
{{- end -}}
{{- if .Services }}
{{range .Services}} - [{{.Name}}](#{{.FullName}})
{{end}}
{{- end -}}
{{end}}
- [Scalar Value Types](#scalar-value-types)
{{range .Files}}
{{$file_name := .Name}}
<a name="{{.Name}}"></a>
<p align="right"><a href="#top">Top</a></p>
## {{.Name}}
{{.Description}}
{{range .Messages}}
<a name="{{.FullName}}"></a>
### {{.LongName}}
{{.Description}}
{{if .HasFields}}
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
{{range .Fields -}}
| `{{.Name}}` | [{{.LongType}}](#{{.FullType}}) | {{.Label}} | {{if (index .Options "deprecated"|default false)}}**Deprecated.** {{end}}{{nobr .Description}}{{if .DefaultValue}} Default: {{.DefaultValue}}{{end}} |
{{end}}
{{end}}
{{if .HasExtensions}}
| Extension | Type | Base | Number | Description |
| --------- | ---- | ---- | ------ | ----------- |
{{range .Extensions -}}
| `{{.Name}}` | {{.LongType}} | {{.ContainingLongType}} | {{.Number}} | {{nobr .Description}}{{if .DefaultValue}} Default: {{.DefaultValue}}{{end}} |
{{end}}
{{end}}
{{end}} <!-- end messages -->
{{range .Enums}}
<a name="{{.FullName}}"></a>
### {{.LongName}}
{{.Description}}
| Name | Number | Description |
| ---- | ------ | ----------- |
{{range .Values -}}
| {{.Name}} | {{.Number}} | {{nobr .Description}} |
{{end}}
{{end}} <!-- end enums -->
{{if .HasExtensions}}
<a name="{{$file_name}}-extensions"></a>
### File-level Extensions
| Extension | Type | Base | Number | Description |
| --------- | ---- | ---- | ------ | ----------- |
{{range .Extensions -}}
| `{{.Name}}` | {{.LongType}} | {{.ContainingLongType}} | {{.Number}} | {{nobr .Description}}{{if .DefaultValue}} Default: `{{.DefaultValue}}`{{end}} |
{{end}}
{{end}} <!-- end HasExtensions -->
{{range .Services}}
<a name="{{.FullName}}"></a>
### {{.Name}}
{{.Description}}
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
{{range .Methods -}}
| `{{.Name}}` | [{{.RequestLongType}}](#{{.RequestFullType}}){{if .RequestStreaming}} stream{{end}} | [{{.ResponseLongType}}](#{{.ResponseFullType}}){{if .ResponseStreaming}} stream{{end}} | {{nobr .Description}} | {{with (index .Options "google.api.http")}}{{range .Rules}}{{.Method}}|{{.Pattern}}{{end}}{{end}}|
{{end}}
{{end}} <!-- end services -->
{{end}}
## Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- |
{{range .Scalars -}}
| <a name="{{.ProtoType}}" /> {{.ProtoType}} | {{.Notes}} | {{.CppType}} | {{.JavaType}} | {{.PythonType}} | {{.GoType}} | {{.CSharp}} | {{.PhpType}} | {{.RubyType}} |
{{end}}

33
go.mod
View File

@ -3,32 +3,41 @@ module github.com/cosmos/ethermint
go 1.15 go 1.15
require ( require (
github.com/aristanetworks/goarista v0.0.0-20200331225509-2cc472e8fbd6 // indirect github.com/aristanetworks/goarista v0.0.0-20201012165903-2cb20defcd66 // indirect
github.com/armon/go-metrics v0.3.6
github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcd v0.21.0-beta
github.com/btcsuite/btcutil v1.0.2 github.com/btcsuite/btcutil v1.0.2
github.com/cespare/cp v1.1.1 // indirect github.com/cespare/cp v1.1.1 // indirect
github.com/cosmos/cosmos-sdk v0.39.3 github.com/cosmos/cosmos-sdk v0.42.4
github.com/cosmos/go-bip39 v1.0.0
github.com/deckarep/golang-set v1.7.1 // indirect github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.9.25 github.com/ethereum/go-ethereum v1.9.25
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/golang/protobuf v1.4.3 // indirect github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.2.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/mattn/go-colorable v0.1.7 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/prometheus/tsdb v0.9.1 // indirect github.com/prometheus/tsdb v0.10.0 // indirect
github.com/spf13/afero v1.2.2 // indirect github.com/regen-network/cosmos-proto v0.3.1
github.com/rs/zerolog v1.20.0
github.com/spf13/cast v1.3.1
github.com/spf13/cobra v1.1.1 github.com/spf13/cobra v1.1.1
github.com/spf13/viper v1.7.1 github.com/spf13/viper v1.7.1
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/tendermint/tendermint v0.33.9 github.com/tendermint/tendermint v0.34.9
github.com/tendermint/tm-db v0.5.2 github.com/tendermint/tm-db v0.6.4
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef github.com/tyler-smith/go-bip39 v1.0.2
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
google.golang.org/grpc v1.30.0 // indirect google.golang.org/genproto v0.0.0-20210405174219-a39eb2f71cb9
google.golang.org/grpc v1.36.1
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )
replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4 replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alpha.regen.4

341
go.sum
View File

@ -31,8 +31,13 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs=
@ -46,16 +51,17 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI=
github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks= github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
@ -63,20 +69,20 @@ github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm
github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA= github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns= github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
github.com/aristanetworks/goarista v0.0.0-20200331225509-2cc472e8fbd6 h1:Pcu4aKyFfpH0aXLnYJrsTjdRvXNY4SbODsb0pMTZxhA= github.com/aristanetworks/goarista v0.0.0-20201012165903-2cb20defcd66 h1:bylzF2sl5pWmmHcdwEku/BPHp5wYjcdjmOnW4siw688=
github.com/aristanetworks/goarista v0.0.0-20200331225509-2cc472e8fbd6/go.mod h1:QZe5Yh80Hp1b6JxQdpfSEEe8X7hTyTEZSosSrFf/oJE= github.com/aristanetworks/goarista v0.0.0-20201012165903-2cb20defcd66/go.mod h1:QZe5Yh80Hp1b6JxQdpfSEEe8X7hTyTEZSosSrFf/oJE=
github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc= github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.6 h1:x/tmtOF9cDBoXH7XoAGOz2qqm1DknFD1590XmD/DUJ8=
github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8=
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -87,27 +93,20 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= 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 h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M=
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
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-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/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 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 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= 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/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= 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 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/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 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/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/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
@ -119,33 +118,42 @@ 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 v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg=
github.com/confio/ics23/go v0.6.3 h1:PuGK2V1NJWZ8sSkNDq91jgT/cahFEW9RGp4Y5jxulf0=
github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+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/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosmos/cosmos-sdk v0.39.2 h1:nLfCJMkUuFt7ansi/YvCxwwxLFrgHCA3cYP4sJKYQdk= github.com/cosmos/cosmos-sdk v0.42.4 h1:yaD4PyOx0LnyfiWasC5egg1U76lT83GRxjJjupPo7Gk=
github.com/cosmos/cosmos-sdk v0.39.2/go.mod h1:VNUluciWBFj2vkhpMcp8rYZL/kCw0FtNc7SseUjE1KM= github.com/cosmos/cosmos-sdk v0.42.4/go.mod h1:I1Zw1zmU4rA/NITaakTb71pXQnQrWyFBhqo3WSeg0vA=
github.com/cosmos/cosmos-sdk v0.39.3 h1:zqd8gmjbwIrvdjY9JL49qH9we+MxLtQHjiEbhYu4xM8=
github.com/cosmos/cosmos-sdk v0.39.3/go.mod h1:PbSREFoyGIOW2OD6muga691A1WiBMcEqLhMy7m+hUJs=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
github.com/cosmos/iavl v0.15.0-rc3.0.20201009144442-230e9bdf52cd/go.mod h1:3xOIaNNX19p0QrX0VqWa6voPRoJRGGYtny+DH8NEPvE=
github.com/cosmos/iavl v0.15.0-rc5/go.mod h1:WqoPL9yPTQ85QBMT45OOUzPxG/U/JcJoN7uMjgxke/I=
github.com/cosmos/iavl v0.15.3 h1:xE9r6HW8GeKeoYJN4zefpljZ1oukVScP/7M8oj6SUts=
github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mVvSA4=
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
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/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
@ -158,14 +166,24 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.7.1/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/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
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/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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
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/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/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/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/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
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/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ=
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
@ -177,10 +195,13 @@ github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/elastic/gosigar v0.10.5/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk=
github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 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.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/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.9.5/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/ethereum/go-ethereum v1.9.5/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.9.25 h1:mMiw/zOOtCLdGLWfcekua0qPrJTe7FVIiHJ4IKNTfR0= github.com/ethereum/go-ethereum v1.9.25 h1:mMiw/zOOtCLdGLWfcekua0qPrJTe7FVIiHJ4IKNTfR0=
@ -193,6 +214,8 @@ github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQD
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
@ -201,7 +224,6 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@ -210,6 +232,7 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqG
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
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.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
@ -226,6 +249,8 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0=
github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -233,9 +258,9 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -246,16 +271,15 @@ github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 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.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/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg= github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg=
github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@ -265,32 +289,33 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 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.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.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.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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us=
github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@ -298,13 +323,19 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277 h1:E0whKxgp2ojts0FDgUA8dl62bmH0LxKanMoBr6MDTDM=
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
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/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
@ -317,15 +348,19 @@ github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoP
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
@ -342,7 +377,6 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw= github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo= github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
@ -350,7 +384,6 @@ github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883 h1:FSeK4fZCo8u40n2JMnyAsd6x7+SbvoOMHvQOU/n10P4=
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
@ -361,23 +394,24 @@ github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 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/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/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/karalabe/hid v1.0.0/go.mod h1:Vr51f8rUOLYrfrWDFlV12GGQgM5AT8sVh+2fY4MPeu8= github.com/karalabe/hid v1.0.0/go.mod h1:Vr51f8rUOLYrfrWDFlV12GGQgM5AT8sVh+2fY4MPeu8=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
@ -385,8 +419,8 @@ github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
@ -394,9 +428,10 @@ github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo
github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 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/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
@ -408,12 +443,13 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/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-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-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@ -432,8 +468,8 @@ github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c h1
github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c/go.mod h1:Z4zI+CdJB1fyrZ1jfevFH6flNV9izrLZnQAeuD6Wkjk= github.com/miguelmota/go-ethereum-hdwallet v0.0.0-20200123000308-a60dcd172b4c/go.mod h1:Z4zI+CdJB1fyrZ1jfevFH6flNV9izrLZnQAeuD6Wkjk=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA= github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@ -451,6 +487,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= 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/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
@ -460,6 +497,8 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
@ -487,23 +526,34 @@ github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/otiai10/copy v1.4.2 h1:RTiz2sol3eoXPLF4o+YWqEybwfUa/Q2Nkc4ZIUs3fwI=
github.com/otiai10/copy v1.4.2/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@ -513,6 +563,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
@ -522,9 +573,11 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw=
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -538,40 +591,55 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.0.10 h1:QJQN3jYQhkamO4mhfUWqdDH2asK7ONOI9MTWjyAxNKM=
github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.9.1 h1:IWaAmWkYlgG7/S4iw4IpAQt5Y35QaZM6/GsZ7GsjAuk= github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.9.1/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
github.com/rakyll/statik v0.1.6 h1:uICcfUXpgqtw2VopbIncslhAmE5hwc4g20TEyEENBNs= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg=
github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM=
github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE= github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE=
github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig= github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4=
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil v2.20.5+incompatible h1:tYH07UPoQt0OCQdgWWMgYHy3/a9bcxNpBIysykNIP7I= github.com/shirou/gopsutil v2.20.5+incompatible h1:tYH07UPoQt0OCQdgWWMgYHy3/a9bcxNpBIysykNIP7I=
@ -579,6 +647,7 @@ github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
@ -587,14 +656,16 @@ github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPH
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
@ -605,14 +676,14 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
@ -628,15 +699,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/goleveldb v0.0.0-20180621010148-0d5a0ceb10cf/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v0.0.0-20180621010148-0d5a0ceb10cf/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk=
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
@ -648,28 +716,28 @@ github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s
github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U=
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI=
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
github.com/tendermint/iavl v0.14.1 h1:jz7YOvGiPwmcqqVMcSMjxCu4WXtQYGhKdKrWTTJ5EKs= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
github.com/tendermint/iavl v0.14.1/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
github.com/tendermint/iavl v0.14.3 h1:tuiUAqJdA3OOyPU/9P3pMYnAcd+OL7BUdzNiE3ytUwQ= github.com/tendermint/tendermint v0.34.9 h1:9P2MXDEPOcPW0NBcHQ/HDSfvczZm+q5nUUw7AZ6f1Vc=
github.com/tendermint/iavl v0.14.3/go.mod h1:vHLYxU/zuxBmxxr1v+5Vnd/JzcIsyK17n9P9RDubPVU= github.com/tendermint/tendermint v0.34.9/go.mod h1:kl4Z1JwGx1I+u1SXIzMDy7Z3T8LiMeCAOnzNn6AIMT4=
github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI=
github.com/tendermint/tendermint v0.33.9 h1:rRKIfu5qAXX5f9bwX1oUXSZz/ALFJjDuivhkbGUQxiU= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8=
github.com/tendermint/tendermint v0.33.9/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM= github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ=
github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw=
github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4=
github.com/tendermint/tm-db v0.5.2 h1:QG3IxQZBubWlr7kGQcYIavyTNmZRO+r//nENxoq0g34=
github.com/tendermint/tm-db v0.5.2/go.mod h1:VrPTx04QJhQ9d8TFUTc2GpPBvBf/U9vIdBIzkjBk7Lk=
github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
@ -681,12 +749,13 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -704,11 +773,13 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -717,19 +788,23 @@ golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
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-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/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -739,14 +814,16 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 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-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/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.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.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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.1.1-0.20191209134235-331c550502dd/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-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-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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -767,29 +844,33 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/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-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -799,6 +880,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/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-20190215142949-d0b11bdaac8a/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -809,6 +891,7 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -816,33 +899,43 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/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-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-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/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 h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/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 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4=
golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb h1:HS9IzC4UFbpMBLQUDSQcU+ViVT1vdFCQVjdPVpTlZrs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.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/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -860,6 +953,7 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -870,11 +964,12 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200110213125-a7a6caa82ab2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200110213125-a7a6caa82ab2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd h1:hHkvGJK23seRCflePJnVa9IMv8fsuavSCWKd11kDQFs= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-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-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 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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -900,13 +995,20 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200218151345-dad8c97a84f5 h1:jB9+PJSvu5tBfmJHy/OVapFdjDF3WvpkqRhxqrmzoEU=
google.golang.org/genproto v0.0.0-20200218151345-dad8c97a84f5/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200218151345-dad8c97a84f5/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210405174219-a39eb2f71cb9 h1:Uga0hMhZnzB159cnlmhVPgEmZTwoZqwOb7e0pu+rlNI=
google.golang.org/genproto v0.0.0-20210405174219-a39eb2f71cb9/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -919,32 +1021,39 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1 h1:cmUfbeGKnz9+2DD/UYsMQXeqbHZqZDs4eQwW0sFOpBY=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 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.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.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.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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610= gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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-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/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fatih/set.v0 v0.2.1/go.mod h1:5eLWEndGL4zGGemXWrKuts+wTJR0y+w+auqUJZbmyBg= gopkg.in/fatih/set.v0 v0.2.1/go.mod h1:5eLWEndGL4zGGemXWrKuts+wTJR0y+w+auqUJZbmyBg=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
@ -958,7 +1067,6 @@ gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLv
gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951/go.mod h1:owOxCRGGeAx1uugABik6K9oeNu1cgxP/R9ItzLDxNWA= gopkg.in/karalabe/cookiejar.v2 v2.0.0-20150724131613-8dcd6a7f4951/go.mod h1:owOxCRGGeAx1uugABik6K9oeNu1cgxP/R9ItzLDxNWA=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/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 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA= gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@ -970,15 +1078,16 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
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= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -13,20 +13,25 @@ import (
"testing" "testing"
"time" "time"
"github.com/google/uuid"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
sdkcodec "github.com/cosmos/cosmos-sdk/codec" sdkcodec "github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store"
sdkstore "github.com/cosmos/cosmos-sdk/store/types" sdkstore "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/bank" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/params" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
paramkeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/cosmos/ethermint/codec"
"github.com/cosmos/ethermint/core" "github.com/cosmos/ethermint/core"
cryptocodec "github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/types" "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm" evmkeeper "github.com/cosmos/ethermint/x/evm/keeper"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
@ -38,8 +43,8 @@ import (
ethparams "github.com/ethereum/go-ethereum/params" ethparams "github.com/ethereum/go-ethereum/params"
ethrlp "github.com/ethereum/go-ethereum/rlp" ethrlp "github.com/ethereum/go-ethereum/rlp"
abci "github.com/tendermint/tendermint/abci/types"
tmlog "github.com/tendermint/tendermint/libs/log" tmlog "github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
) )
@ -64,18 +69,16 @@ func init() {
flag.Parse() flag.Parse()
} }
func newTestCodec() *sdkcodec.Codec { func newTestCodec() (sdkcodec.BinaryMarshaler, *sdkcodec.LegacyAmino) {
cdc := sdkcodec.New() interfaceRegistry := codectypes.NewInterfaceRegistry()
cdc := sdkcodec.NewProtoCodec(interfaceRegistry)
amino := sdkcodec.NewLegacyAmino()
evmtypes.RegisterCodec(cdc) sdk.RegisterLegacyAminoCodec(amino)
types.RegisterCodec(cdc)
auth.RegisterCodec(cdc)
bank.RegisterCodec(cdc)
sdk.RegisterCodec(cdc)
cryptocodec.RegisterCodec(cdc)
sdkcodec.RegisterCrypto(cdc)
return cdc codec.RegisterInterfaces(interfaceRegistry)
return cdc, amino
} }
func cleanup() { func cleanup() {
@ -99,10 +102,10 @@ func trapSignals() {
} }
// nolint: interfacer // nolint: interfacer
func createAndTestGenesis(t *testing.T, cms sdk.CommitMultiStore, ak auth.AccountKeeper, evmKeeper *evm.Keeper) { func createAndTestGenesis(t *testing.T, cms sdk.CommitMultiStore, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper, evmKeeper *evmkeeper.Keeper) {
genBlock := ethcore.DefaultGenesisBlock() genBlock := ethcore.DefaultGenesisBlock()
ms := cms.CacheMultiStore() ms := cms.CacheMultiStore()
ctx := sdk.NewContext(ms, abci.Header{}, false, logger) ctx := sdk.NewContext(ms, tmproto.Header{}, false, logger)
// Set the default Ethermint parameters to the parameter keeper store // Set the default Ethermint parameters to the parameter keeper store
evmKeeper.SetParams(ctx, evmtypes.DefaultParams()) evmKeeper.SetParams(ctx, evmtypes.DefaultParams())
@ -151,7 +154,7 @@ func createAndTestGenesis(t *testing.T, cms sdk.CommitMultiStore, ak auth.Accoun
require.NotNil(t, genAcc) require.NotNil(t, genAcc)
evmDenom := evmKeeper.GetParams(ctx).EvmDenom evmDenom := evmKeeper.GetParams(ctx).EvmDenom
balance := sdk.NewCoin(evmDenom, genAcc.GetCoins().AmountOf(evmDenom)) balance := bk.GetBalance(ctx, genAcc.GetAddress(), evmDenom)
require.Equal(t, sdk.NewIntFromBigInt(b), balance.Amount) require.Equal(t, sdk.NewIntFromBigInt(b), balance.Amount)
} }
@ -168,43 +171,50 @@ func TestImportBlocks(t *testing.T) {
require.NoError(t, err, "failed to start CPU profile") require.NoError(t, err, "failed to start CPU profile")
} }
db := dbm.NewDB("state", dbm.GoLevelDBBackend, flagDataDir) db, err := dbm.NewDB("state_test"+uuid.New().String(), dbm.GoLevelDBBackend, flagDataDir)
require.NoError(t, err)
defer cleanup() defer cleanup()
trapSignals() trapSignals()
cdc := newTestCodec() cdc, amino := newTestCodec()
cms := store.NewCommitMultiStore(db) cms := store.NewCommitMultiStore(db)
authStoreKey := sdk.NewKVStoreKey(auth.StoreKey) authStoreKey := sdk.NewKVStoreKey(authtypes.StoreKey)
bankStoreKey := sdk.NewKVStoreKey(banktypes.StoreKey)
evmStoreKey := sdk.NewKVStoreKey(evmtypes.StoreKey) evmStoreKey := sdk.NewKVStoreKey(evmtypes.StoreKey)
paramsStoreKey := sdk.NewKVStoreKey(params.StoreKey) paramsStoreKey := sdk.NewKVStoreKey(paramtypes.StoreKey)
paramsTransientStoreKey := sdk.NewTransientStoreKey(params.TStoreKey) paramsTransientStoreKey := sdk.NewTransientStoreKey(paramtypes.TStoreKey)
// mount stores // mount stores
keys := []*sdk.KVStoreKey{authStoreKey, evmStoreKey, paramsStoreKey} keys := []*sdk.KVStoreKey{authStoreKey, bankStoreKey, evmStoreKey, paramsStoreKey}
for _, key := range keys { for _, key := range keys {
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, nil) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, nil)
} }
cms.MountStoreWithDB(paramsTransientStoreKey, sdk.StoreTypeTransient, nil) cms.MountStoreWithDB(paramsTransientStoreKey, sdk.StoreTypeTransient, nil)
paramsKeeper := params.NewKeeper(cdc, paramsStoreKey, paramsTransientStoreKey) paramsKeeper := paramkeeper.NewKeeper(cdc, amino, paramsStoreKey, paramsTransientStoreKey)
// Set specific subspaces // Set specific subspaces
authSubspace := paramsKeeper.Subspace(auth.DefaultParamspace) authSubspace := paramsKeeper.Subspace(authtypes.ModuleName)
evmSubspace := paramsKeeper.Subspace(evmtypes.DefaultParamspace).WithKeyTable(evmtypes.ParamKeyTable()) bankSubspace := paramsKeeper.Subspace(banktypes.ModuleName)
ak := auth.NewAccountKeeper(cdc, authStoreKey, authSubspace, types.ProtoAccount) evmSubspace := paramsKeeper.Subspace(evmtypes.ModuleName).WithKeyTable(evmtypes.ParamKeyTable())
evmKeeper := evm.NewKeeper(cdc, evmStoreKey, evmSubspace, ak)
// create keepers
ak := authkeeper.NewAccountKeeper(cdc, authStoreKey, authSubspace, types.ProtoAccount, nil)
bk := bankkeeper.NewBaseKeeper(cdc, bankStoreKey, ak, bankSubspace, nil)
evmKeeper := evmkeeper.NewKeeper(cdc, evmStoreKey, evmSubspace, ak, bk)
cms.SetPruning(sdkstore.PruneNothing) cms.SetPruning(sdkstore.PruneNothing)
// load latest version (root) // load latest version (root)
err := cms.LoadLatestVersion() err = cms.LoadLatestVersion()
require.NoError(t, err) require.NoError(t, err)
// set and test genesis block // set and test genesis block
createAndTestGenesis(t, cms, ak, evmKeeper) createAndTestGenesis(t, cms, ak, bk, evmKeeper)
// open blockchain export file // open blockchain export file
blockchainInput, err := os.Open(flagBlockchain) blockchainInput, err := os.Open(flagBlockchain)
@ -246,7 +256,7 @@ func TestImportBlocks(t *testing.T) {
// Create a cached-wrapped multi-store based on the commit multi-store and // Create a cached-wrapped multi-store based on the commit multi-store and
// create a new context based off of that. // create a new context based off of that.
ms := cms.CacheMultiStore() ms := cms.CacheMultiStore()
ctx := sdk.NewContext(ms, abci.Header{}, false, logger) ctx := sdk.NewContext(ms, tmproto.Header{}, false, logger)
ctx = ctx.WithBlockHeight(int64(block.NumberU64())) ctx = ctx.WithBlockHeight(int64(block.NumberU64()))
if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number()) == 0 { if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number()) == 0 {
@ -286,7 +296,7 @@ func TestImportBlocks(t *testing.T) {
// reward. The total reward consists of the static block reward and rewards for // reward. The total reward consists of the static block reward and rewards for
// included uncles. The coinbase of each uncle block is also rewarded. // included uncles. The coinbase of each uncle block is also rewarded.
func accumulateRewards( func accumulateRewards(
config *ethparams.ChainConfig, evmKeeper *evm.Keeper, config *ethparams.ChainConfig, evmKeeper *evmkeeper.Keeper,
header *ethtypes.Header, uncles []*ethtypes.Header, header *ethtypes.Header, uncles []*ethtypes.Header,
) { ) {
@ -319,7 +329,7 @@ func accumulateRewards(
// Code is pulled from go-ethereum 1.9 because the StateDB interface does not include the // Code is pulled from go-ethereum 1.9 because the StateDB interface does not include the
// SetBalance function implementation // SetBalance function implementation
// Ref: https://github.com/ethereum/go-ethereum/blob/52f2461774bcb8cdd310f86b4bc501df5b783852/consensus/misc/dao.go#L74 // Ref: https://github.com/ethereum/go-ethereum/blob/52f2461774bcb8cdd310f86b4bc501df5b783852/consensus/misc/dao.go#L74
func applyDAOHardFork(evmKeeper *evm.Keeper) { func applyDAOHardFork(evmKeeper *evmkeeper.Keeper) {
// Retrieve the contract to refund balances into // Retrieve the contract to refund balances into
if !evmKeeper.CommitStateDB.Exist(ethparams.DAORefundContract) { if !evmKeeper.CommitStateDB.Exist(ethparams.DAORefundContract) {
evmKeeper.CommitStateDB.CreateAccount(ethparams.DAORefundContract) evmKeeper.CommitStateDB.CreateAccount(ethparams.DAORefundContract)
@ -340,7 +350,7 @@ func applyDAOHardFork(evmKeeper *evm.Keeper) {
// Ref: https://github.com/ethereum/go-ethereum/blob/52f2461774bcb8cdd310f86b4bc501df5b783852/core/state_processor.go#L88 // Ref: https://github.com/ethereum/go-ethereum/blob/52f2461774bcb8cdd310f86b4bc501df5b783852/core/state_processor.go#L88
func applyTransaction( func applyTransaction(
config *ethparams.ChainConfig, bc ethcore.ChainContext, author *ethcmn.Address, config *ethparams.ChainConfig, bc ethcore.ChainContext, author *ethcmn.Address,
gp *ethcore.GasPool, evmKeeper *evm.Keeper, header *ethtypes.Header, gp *ethcore.GasPool, evmKeeper *evmkeeper.Keeper, header *ethtypes.Header,
tx *ethtypes.Transaction, usedGas *uint64, cfg ethvm.Config, tx *ethtypes.Transaction, usedGas *uint64, cfg ethvm.Config,
) (*ethtypes.Receipt, uint64, error) { ) (*ethtypes.Receipt, uint64, error) {
msg, err := tx.AsMessage(ethtypes.MakeSigner(config, header.Number)) msg, err := tx.AsMessage(ethtypes.MakeSigner(config, header.Number))

74
init.sh
View File

@ -1,7 +1,6 @@
#!/bin/bash
KEY="mykey" KEY="mykey"
CHAINID="ethermint-1" CHAINID="ethermint-2"
MONIKER="localtestnet" MONIKER="localtestnet"
# remove existing daemon and client # remove existing daemon and client
@ -9,46 +8,57 @@ rm -rf ~/.ethermint*
make install make install
ethermintcli config keyring-backend test
# Set up config for CLI
ethermintcli config chain-id $CHAINID
ethermintcli config output json
ethermintcli config indent true
ethermintcli config trust-node true
# if $KEY exists it should be deleted # if $KEY exists it should be deleted
ethermintcli keys add $KEY ethermintd keys add $KEY --keyring-backend test --algo "eth_secp256k1"
# Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer) # Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
ethermintd init $MONIKER --chain-id $CHAINID ethermintd init $MONIKER --chain-id $CHAINID
# Change parameter token denominations to aphoton # Change parameter token denominations to aphoton
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="stake"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="aphoton"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="aphoton"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aphoton"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
# increase block time (?) # increase block time (?)
cat $HOME/.ethermintd/config/genesis.json | jq '.consensus_params["block"]["time_iota_ms"]="30000"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.consensus_params["block"]["time_iota_ms"]="30000"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
# disable produce empty block
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.ethermint/config/config.toml
else
sed -i 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.ethermint/config/config.toml
fi
if [[ $1 == "pending" ]]; then if [[ $1 == "pending" ]]; then
echo "pending mode on; block times will be set to 30s." if [[ "$OSTYPE" == "darwin"* ]]; then
# sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.ethermintd/config/config.toml sed -i '' 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.ethermint/config/config.toml
sed -i '' 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $HOME/.ethermint/config/config.toml
else
sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.ethermint/config/config.toml
sed -i 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $HOME/.ethermint/config/config.toml
fi
fi fi
# Allocate genesis accounts (cosmos formatted addresses) # Allocate genesis accounts (cosmos formatted addresses)
ethermintd add-genesis-account $(ethermintcli keys show $KEY -a) 100000000000000000000aphoton ethermintd add-genesis-account $KEY 1000000000000000000000aphoton,1000000000000000000stake --keyring-backend test
# Sign genesis transaction # Sign genesis transaction
ethermintd gentx --name $KEY --amount=1000000000000000000aphoton --keyring-backend test ethermintd gentx $KEY 1000000000000000000stake --amount=1000000000000000000000aphoton --keyring-backend test --chain-id $CHAINID
# Collect genesis tx # Collect genesis tx
ethermintd collect-gentxs ethermintd collect-gentxs
@ -56,9 +66,9 @@ ethermintd collect-gentxs
# Run this to ensure everything worked and that the genesis file is setup correctly # Run this to ensure everything worked and that the genesis file is setup correctly
ethermintd validate-genesis ethermintd validate-genesis
# Command to run the rest server in a different terminal/window if [[ $1 == "pending" ]]; then
echo -e '\nrun the following command in a different terminal/window to run the REST server and JSON-RPC:' echo "pending mode is on, please wait for the first block committed."
echo -e "ethermintcli rest-server --laddr \"tcp://localhost:8545\" --unlock-key $KEY --chain-id $CHAINID --trace\n" fi
# Start the node (remove the --pruning=nothing flag if historical queries are not needed) # Start the node (remove the --pruning=nothing flag if historical queries are not needed)
ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace ethermintd start --pruning=nothing --rpc.unsafe --rpc-api "web3, eth, personal, net" --keyring-backend test --trace --log_level info

View File

@ -23,10 +23,9 @@ RUN apt-get update
# Copy over binaries from the build-env # Copy over binaries from the build-env
COPY --from=build-env /go/src/github.com/cosmos/ethermint/build/ethermintd /usr/bin/ethermintd COPY --from=build-env /go/src/github.com/cosmos/ethermint/build/ethermintd /usr/bin/ethermintd
COPY --from=build-env /go/src/github.com/cosmos/ethermint/build/ethermintcli /usr/bin/ethermintcli
COPY --from=build-env /go/src/github.com/cosmos/ethermint/scripts/start.sh / COPY --from=build-env /go/src/github.com/cosmos/ethermint/scripts/start.sh /
EXPOSE 26656 26657 1317 8545 8546 EXPOSE 26656 26657 1317 8545 8546
# Run ethermintd by default, omit entrypoint to ease using container with ethermintcli # Run ethermintd by default, omit entrypoint to ease using container with ethermintd
ENTRYPOINT ["/bin/bash", "-c"] ENTRYPOINT ["/bin/bash", "-c"]

View File

@ -30,15 +30,10 @@ message GenesisState {
message GenesisAccount { message GenesisAccount {
// address defines an ethereum hex formated address of an account // address defines an ethereum hex formated address of an account
string address = 1; string address = 1;
// balance defines the available evm tokens for the account
string balance = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
// code defines the hex bytes of the account code. // code defines the hex bytes of the account code.
string code = 3; string code = 2;
// storage defines the set of state key values for the account. // storage defines the set of state key values for the account.
repeated State storage = 4 [ repeated State storage = 3 [
(gogoproto.nullable) = false, (gogoproto.nullable) = false,
(gogoproto.castrepeated) = "Storage" (gogoproto.castrepeated) = "Storage"
]; ];

View File

@ -1,18 +1,19 @@
package rpc package rpc
import ( import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/rpc/backend"
"github.com/cosmos/ethermint/rpc/namespaces/eth"
"github.com/cosmos/ethermint/rpc/namespaces/eth/filters" "github.com/cosmos/ethermint/rpc/namespaces/eth/filters"
"github.com/cosmos/ethermint/rpc/namespaces/net" "github.com/cosmos/ethermint/rpc/namespaces/net"
"github.com/cosmos/ethermint/rpc/namespaces/personal" "github.com/cosmos/ethermint/rpc/namespaces/personal"
"github.com/cosmos/ethermint/rpc/namespaces/web3" "github.com/cosmos/ethermint/rpc/namespaces/web3"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/rpc/backend"
"github.com/cosmos/ethermint/rpc/namespaces/eth"
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
"github.com/cosmos/cosmos-sdk/client"
) )
// RPC namespaces and API version // RPC namespaces and API version
@ -24,33 +25,17 @@ const (
flagRPCAPI = "rpc-api" flagRPCAPI = "rpc-api"
apiVersion = "1.0" apiVersion = "1.0"
flagRPCAPI = "rpc-api"
) )
// GetAPIs returns the list of all APIs from the Ethereum namespaces // GetAPIs returns the list of all APIs from the Ethereum namespaces
func GetAPIs(clientCtx context.CLIContext, selectedApis []string, keys ...ethsecp256k1.PrivKey) []rpc.API { func GetAPIs(clientCtx client.Context, selectedApis []string, keys ...ethsecp256k1.PrivKey) []rpc.API {
nonceLock := new(rpctypes.AddrLocker) nonceLock := new(rpctypes.AddrLocker)
backend := backend.New(clientCtx) backend := backend.New(clientCtx)
ethAPI := eth.NewAPI(clientCtx, backend, nonceLock, keys...) ethAPI := eth.NewAPI(clientCtx, backend, nonceLock, keys...)
var apis []rpc.API var apis []rpc.API
apis = append(apis,
rpc.API{
Namespace: EthNamespace,
Version: apiVersion,
Service: ethAPI,
Public: true,
},
)
apis = append(apis,
rpc.API{
Namespace: EthNamespace,
Version: apiVersion,
Service: filters.NewAPI(clientCtx, backend),
Public: true,
},
)
for _, api := range selectedApis { for _, api := range selectedApis {
switch api { switch api {
case Web3Namespace: case Web3Namespace:
@ -62,6 +47,21 @@ func GetAPIs(clientCtx context.CLIContext, selectedApis []string, keys ...ethsec
Public: true, Public: true,
}, },
) )
case EthNamespace:
apis = append(apis,
rpc.API{
Namespace: EthNamespace,
Version: apiVersion,
Service: ethAPI,
Public: true,
},
rpc.API{
Namespace: EthNamespace,
Version: apiVersion,
Service: filters.NewAPI(clientCtx, backend),
Public: true,
},
)
case PersonalNamespace: case PersonalNamespace:
apis = append(apis, apis = append(apis,
rpc.API{ rpc.API{

View File

@ -2,7 +2,7 @@ package backend
import ( import (
"context" "context"
"fmt" "errors"
"os" "os"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
@ -10,7 +10,7 @@ import (
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
clientcontext "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -43,131 +43,104 @@ var _ Backend = (*EthermintBackend)(nil)
// EthermintBackend implements the Backend interface // EthermintBackend implements the Backend interface
type EthermintBackend struct { type EthermintBackend struct {
ctx context.Context ctx context.Context
clientCtx clientcontext.CLIContext clientCtx client.Context
logger log.Logger queryClient *rpctypes.QueryClient // gRPC query client
gasLimit int64 logger log.Logger
} }
// New creates a new EthermintBackend instance // New creates a new EthermintBackend instance
func New(clientCtx clientcontext.CLIContext) *EthermintBackend { func New(clientCtx client.Context) *EthermintBackend {
return &EthermintBackend{ return &EthermintBackend{
ctx: context.Background(), ctx: context.Background(),
clientCtx: clientCtx, clientCtx: clientCtx,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"), queryClient: rpctypes.NewQueryClient(clientCtx),
gasLimit: int64(^uint32(0)), logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"),
} }
} }
// BlockNumber returns the current block number. // BlockNumber returns the current block number.
func (b *EthermintBackend) BlockNumber() (hexutil.Uint64, error) { func (b *EthermintBackend) BlockNumber() (hexutil.Uint64, error) {
blockNumber, err := b.LatestBlockNumber() // NOTE: using 0 as min and max height returns the blockchain info up to the latest block.
info, err := b.clientCtx.Client.BlockchainInfo(b.ctx, 0, 0)
if err != nil { if err != nil {
return hexutil.Uint64(0), err return hexutil.Uint64(0), err
} }
return hexutil.Uint64(blockNumber), nil return hexutil.Uint64(info.LastHeight), nil
} }
// GetBlockByNumber returns the block identified by number. // GetBlockByNumber returns the block identified by number.
func (b *EthermintBackend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { func (b *EthermintBackend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) {
height := blockNum.Int64() var height *int64
if height <= 0 { // NOTE: here pending and latest are defined as a nil height, which fetches the latest block
// get latest block height if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
num, err := b.BlockNumber() height = blockNum.TmHeight()
if err != nil {
return nil, err
}
height = int64(num)
} }
resBlock, err := b.clientCtx.Client.Block(&height) resBlock, err := b.clientCtx.Client.Block(b.ctx, height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return rpctypes.EthBlockFromTendermint(b.clientCtx, resBlock.Block) if resBlock.BlockID.IsZero() {
return nil, errors.New("failed to query block by number: nil block returned")
}
return rpctypes.EthBlockFromTendermint(b.clientCtx, b.queryClient, resBlock.Block)
} }
// GetBlockByHash returns the block identified by hash. // GetBlockByHash returns the block identified by hash.
func (b *EthermintBackend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { func (b *EthermintBackend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
res, _, err := b.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, hash.Hex())) resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes())
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out evmtypes.QueryResBlockNumber return rpctypes.EthBlockFromTendermint(b.clientCtx, b.queryClient, resBlock.Block)
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
resBlock, err := b.clientCtx.Client.Block(&out.Number)
if err != nil {
return nil, err
}
return rpctypes.EthBlockFromTendermint(b.clientCtx, resBlock.Block)
} }
// HeaderByNumber returns the block header identified by height. // HeaderByNumber returns the block header identified by height.
func (b *EthermintBackend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) { func (b *EthermintBackend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) {
height := blockNum.Int64() var height *int64
if height <= 0 { // NOTE: here pending and latest are defined as a nil height, which fetches the latest header
// get latest block height if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
num, err := b.BlockNumber() height = blockNum.TmHeight()
if err != nil {
return nil, err
}
height = int64(num)
} }
resBlock, err := b.clientCtx.Client.Block(&height) resBlock, err := b.clientCtx.Client.Block(b.ctx, height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
res, _, err := b.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%d", evmtypes.ModuleName, evmtypes.QueryBloom, resBlock.Block.Height)) req := &evmtypes.QueryBlockBloomRequest{}
res, err := b.queryClient.BlockBloom(rpctypes.ContextWithHeight(blockNum.Int64()), req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var bloomRes evmtypes.QueryBloomFilter
b.clientCtx.Codec.MustUnmarshalJSON(res, &bloomRes)
ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header) ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header)
ethHeader.Bloom = bloomRes.Bloom ethHeader.Bloom = ethtypes.BytesToBloom(res.Bloom)
return ethHeader, nil return ethHeader, nil
} }
// HeaderByHash returns the block header identified by hash. // HeaderByHash returns the block header identified by hash.
func (b *EthermintBackend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { func (b *EthermintBackend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) {
res, _, err := b.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, blockHash.Hex())) resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes())
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out evmtypes.QueryResBlockNumber req := &evmtypes.QueryBlockBloomRequest{}
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
resBlock, err := b.clientCtx.Client.Block(&out.Number) res, err := b.queryClient.BlockBloom(rpctypes.ContextWithHeight(resBlock.Block.Height), req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
res, _, err = b.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%d", evmtypes.ModuleName, evmtypes.QueryBloom, resBlock.Block.Height))
if err != nil {
return nil, err
}
var bloomRes evmtypes.QueryBloomFilter
b.clientCtx.Codec.MustUnmarshalJSON(res, &bloomRes)
ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header) ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header)
ethHeader.Bloom = bloomRes.Bloom ethHeader.Bloom = ethtypes.BytesToBloom(res.Bloom)
return ethHeader, nil return ethHeader, nil
} }
@ -175,23 +148,23 @@ func (b *EthermintBackend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header
// It returns an error if there's an encoding error. // It returns an error if there's an encoding error.
// If no logs are found for the tx hash, the error is nil. // If no logs are found for the tx hash, the error is nil.
func (b *EthermintBackend) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error) { func (b *EthermintBackend) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error) {
res, _, err := b.clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryTransactionLogs, txHash.String()), nil) req := &evmtypes.QueryTxLogsRequest{
Hash: txHash.String(),
}
res, err := b.queryClient.TxLogs(b.ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
out := new(evmtypes.QueryETHLogs) return evmtypes.LogsToEthereum(res.Logs), nil
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
return out.Logs, nil
} }
// PendingTransactions returns the transactions that are in the transaction pool // PendingTransactions returns the transactions that are in the transaction pool
// and have a from address that is one of the accounts this node manages. // and have a from address that is one of the accounts this node manages.
func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error) { func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error) {
pendingTxs, err := b.clientCtx.Client.UnconfirmedTxs(1000) limit := 1000
pendingTxs, err := b.clientCtx.Client.UnconfirmedTxs(b.ctx, &limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -216,35 +189,19 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error
// GetLogs returns all the logs from all the ethereum transactions in a block. // GetLogs returns all the logs from all the ethereum transactions in a block.
func (b *EthermintBackend) GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) { func (b *EthermintBackend) GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) {
res, _, err := b.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, blockHash.Hex())) // NOTE: we query the state in case the tx result logs are not persisted after an upgrade.
if err != nil { req := &evmtypes.QueryBlockLogsRequest{
return nil, err Hash: blockHash.String(),
} }
var out evmtypes.QueryResBlockNumber res, err := b.queryClient.BlockLogs(b.ctx, req)
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
block, err := b.clientCtx.Client.Block(&out.Number)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var blockLogs = [][]*ethtypes.Log{} var blockLogs = [][]*ethtypes.Log{}
for _, tx := range block.Block.Txs { for _, txLog := range res.TxLogs {
// NOTE: we query the state in case the tx result logs are not persisted after an upgrade. blockLogs = append(blockLogs, txLog.EthLogs())
res, _, err := b.clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryTransactionLogs, common.BytesToHash(tx.Hash()).String()), nil)
if err != nil {
continue
}
out := new(evmtypes.QueryETHLogs)
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
blockLogs = append(blockLogs, out.Logs)
} }
return blockLogs, nil return blockLogs, nil
@ -259,7 +216,7 @@ func (b *EthermintBackend) BloomStatus() (uint64, uint64) {
// LatestBlockNumber gets the latest block height in int64 format. // LatestBlockNumber gets the latest block height in int64 format.
func (b *EthermintBackend) LatestBlockNumber() (int64, error) { func (b *EthermintBackend) LatestBlockNumber() (int64, error) {
// NOTE: using 0 as min and max height returns the blockchain info up to the latest block. // NOTE: using 0 as min and max height returns the blockchain info up to the latest block.
info, err := b.clientCtx.Client.BlockchainInfo(0, 0) info, err := b.clientCtx.Client.BlockchainInfo(context.Background(), 0, 0)
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -1,21 +0,0 @@
package rpc
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/lcd"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/spf13/cobra"
)
// ServeCmd creates a CLI command to start Cosmos REST server with web3 RPC API and
// Cosmos rest-server endpoints
func ServeCmd(cdc *codec.Codec) *cobra.Command {
cmd := lcd.ServeCommand(cdc, RegisterRoutes)
cmd.Flags().String(flagRPCAPI, "", fmt.Sprintf("Comma separated list of RPC API modules to enable: %s, %s, %s, %s", Web3Namespace, EthNamespace, PersonalNamespace, NetNamespace))
cmd.Flags().String(flagUnlockKey, "", "Select a key to unlock on the RPC server")
cmd.Flags().String(flagWebsocket, "8546", "websocket port to listen to")
cmd.Flags().StringP(flags.FlagBroadcastMode, "b", flags.BroadcastSync, "Transaction broadcasting mode (sync|async|block)")
return cmd
}

View File

@ -1,68 +1,27 @@
package rpc package rpc
import ( import (
"bufio"
"fmt"
"os"
"strings" "strings"
"github.com/cosmos/cosmos-sdk/client" "github.com/gorilla/mux"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/client/lcd"
"github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/app"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/crypto/hd"
"github.com/cosmos/ethermint/rpc/websockets"
evmrest "github.com/cosmos/ethermint/x/evm/client/rest"
"github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/ethereum/go-ethereum/rpc"
) )
const ( // RegisterEthereum creates a new ethereum JSON-RPC server and recreates a CLI command to start Cosmos REST server with web3 RPC API and
flagUnlockKey = "unlock-key" // Cosmos rest-server endpoints
flagWebsocket = "wsport" func RegisterEthereum(clientCtx client.Context, r *mux.Router) {
)
// RegisterRoutes creates a new server and registers the `/rpc` endpoint.
// Rpc calls are enabled based on their associated module (eg. "eth").
func RegisterRoutes(rs *lcd.RestServer) {
server := rpc.NewServer() server := rpc.NewServer()
accountName := viper.GetString(flagUnlockKey) r.HandleFunc("/", server.ServeHTTP).Methods("POST", "OPTIONS")
accountNames := strings.Split(accountName, ",")
var privkeys []ethsecp256k1.PrivKey
if len(accountName) > 0 {
var err error
inBuf := bufio.NewReader(os.Stdin)
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
passphrase := ""
switch keyringBackend {
case keys.BackendOS:
break
case keys.BackendFile:
passphrase, err = input.GetPassword(
"Enter password to unlock key for RPC API: ",
inBuf)
if err != nil {
panic(err)
}
}
privkeys, err = unlockKeyFromNameAndPassphrase(accountNames, passphrase)
if err != nil {
panic(err)
}
}
rpcapi := viper.GetString(flagRPCAPI) rpcapi := viper.GetString(flagRPCAPI)
rpcapi = strings.ReplaceAll(rpcapi, " ", "") rpcapi = strings.ReplaceAll(rpcapi, " ", "")
rpcapiArr := strings.Split(rpcapi, ",") rpcapiArr := strings.Split(rpcapi, ",")
apis := GetAPIs(rs.CliCtx, rpcapiArr, privkeys...) apis := GetAPIs(clientCtx, rpcapiArr)
// Register all the APIs exposed by the namespace services // Register all the APIs exposed by the namespace services
// TODO: handle allowlist and private APIs // TODO: handle allowlist and private APIs
@ -71,50 +30,4 @@ func RegisterRoutes(rs *lcd.RestServer) {
panic(err) panic(err)
} }
} }
// Web3 RPC API route
rs.Mux.HandleFunc("/", server.ServeHTTP).Methods("POST", "OPTIONS")
// Register all other Cosmos routes
client.RegisterRoutes(rs.CliCtx, rs.Mux)
evmrest.RegisterRoutes(rs.CliCtx, rs.Mux)
app.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
// start websockets server
websocketAddr := viper.GetString(flagWebsocket)
ws := websockets.NewServer(rs.CliCtx, websocketAddr)
ws.Start()
}
func unlockKeyFromNameAndPassphrase(accountNames []string, passphrase string) ([]ethsecp256k1.PrivKey, error) {
keybase, err := keys.NewKeyring(
sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend),
viper.GetString(flags.FlagHome),
os.Stdin,
hd.EthSecp256k1Options()...,
)
if err != nil {
return []ethsecp256k1.PrivKey{}, err
}
// try the for loop with array []string accountNames
// run through the bottom code inside the for loop
keys := make([]ethsecp256k1.PrivKey, len(accountNames))
for i, acc := range accountNames {
// With keyring keybase, password is not required as it is pulled from the OS prompt
privKey, err := keybase.ExportPrivateKeyObject(acc, passphrase)
if err != nil {
return []ethsecp256k1.PrivKey{}, err
}
var ok bool
keys[i], ok = privKey.(ethsecp256k1.PrivKey)
if !ok {
panic(fmt.Sprintf("invalid private key type %T at index %d", privKey, i))
}
}
return keys, nil
} }

View File

@ -7,9 +7,11 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"strings"
"sync" "sync"
"time" "time"
"github.com/gogo/protobuf/jsonpb"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" "github.com/cosmos/ethermint/crypto/ethsecp256k1"
@ -17,13 +19,10 @@ import (
"github.com/cosmos/ethermint/rpc/backend" "github.com/cosmos/ethermint/rpc/backend"
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/utils"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/rpc/client"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
@ -32,19 +31,18 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
clientcontext "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authclient "github.com/cosmos/cosmos-sdk/x/auth/client/utils"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
) )
// PublicEthereumAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. // PublicEthereumAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicEthereumAPI struct { type PublicEthereumAPI struct {
ctx context.Context ctx context.Context
clientCtx clientcontext.CLIContext clientCtx client.Context
queryClient *rpctypes.QueryClient // gRPC query client
chainIDEpoch *big.Int chainIDEpoch *big.Int
logger log.Logger logger log.Logger
backend backend.Backend backend backend.Backend
@ -55,7 +53,7 @@ type PublicEthereumAPI struct {
// NewAPI creates an instance of the public ETH Web3 API. // NewAPI creates an instance of the public ETH Web3 API.
func NewAPI( func NewAPI(
clientCtx clientcontext.CLIContext, backend backend.Backend, nonceLock *rpctypes.AddrLocker, clientCtx client.Context, backend backend.Backend, nonceLock *rpctypes.AddrLocker,
keys ...ethsecp256k1.PrivKey, keys ...ethsecp256k1.PrivKey,
) *PublicEthereumAPI { ) *PublicEthereumAPI {
@ -67,6 +65,7 @@ func NewAPI(
api := &PublicEthereumAPI{ api := &PublicEthereumAPI{
ctx: context.Background(), ctx: context.Background(),
clientCtx: clientCtx, clientCtx: clientCtx,
queryClient: rpctypes.NewQueryClient(clientCtx),
chainIDEpoch: epoch, chainIDEpoch: epoch,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc", "namespace", "eth"), logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc", "namespace", "eth"),
backend: backend, backend: backend,
@ -87,27 +86,26 @@ func (api *PublicEthereumAPI) GetKeyringInfo() error {
api.keyringLock.Lock() api.keyringLock.Lock()
defer api.keyringLock.Unlock() defer api.keyringLock.Unlock()
if api.clientCtx.Keybase != nil { /*api.clientCtx.keyring won't be nil because we init node with ethermintd keys add CLI
return nil we need to create a new keyring here with initialized account info merged by using the same api.clientCtx.KeyringDir
} we also need to add eth_secp256k1 key type here*/
keybase, err := keyring.New(
keybase, err := keys.NewKeyring(
sdk.KeyringServiceName(), sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagKeyringBackend),
viper.GetString(flags.FlagHome), api.clientCtx.KeyringDir,
api.clientCtx.Input, api.clientCtx.Input,
hd.EthSecp256k1Options()..., hd.EthSecp256k1Option(),
) )
if err != nil { if err != nil {
return err return err
} }
api.clientCtx.Keybase = keybase api.clientCtx.Keyring = keybase
return nil return nil
} }
// ClientCtx returns the Cosmos SDK client context. // ClientCtx returns the Cosmos SDK client context.
func (api *PublicEthereumAPI) ClientCtx() clientcontext.CLIContext { func (api *PublicEthereumAPI) ClientCtx() client.Context {
return api.clientCtx return api.clientCtx
} }
@ -138,7 +136,7 @@ func (api *PublicEthereumAPI) ChainId() (hexutil.Uint, error) { // nolint
func (api *PublicEthereumAPI) Syncing() (interface{}, error) { func (api *PublicEthereumAPI) Syncing() (interface{}, error) {
api.logger.Debug("eth_syncing") api.logger.Debug("eth_syncing")
status, err := api.clientCtx.Client.Status() status, err := api.clientCtx.Client.Status(api.ctx)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -165,7 +163,7 @@ func (api *PublicEthereumAPI) Coinbase() (common.Address, error) {
return common.Address{}, err return common.Address{}, err
} }
status, err := node.Status() status, err := node.Status(api.ctx)
if err != nil { if err != nil {
return common.Address{}, err return common.Address{}, err
} }
@ -200,7 +198,7 @@ func (api *PublicEthereumAPI) Accounts() ([]common.Address, error) {
addresses := make([]common.Address, 0) // return [] instead of nil if empty addresses := make([]common.Address, 0) // return [] instead of nil if empty
infos, err := api.clientCtx.Keybase.List() infos, err := api.clientCtx.Keyring.List()
if err != nil { if err != nil {
return addresses, err return addresses, err
} }
@ -220,28 +218,33 @@ func (api *PublicEthereumAPI) BlockNumber() (hexutil.Uint64, error) {
} }
// GetBalance returns the provided account's balance up to the provided block number. // GetBalance returns the provided account's balance up to the provided block number.
//nolint:interfacer
func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) { func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) {
api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum)
clientCtx := api.clientCtx req := &evmtypes.QueryBalanceRequest{
if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) { Address: address.String(),
clientCtx = api.clientCtx.WithHeight(blockNum.Int64())
} }
res, _, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) ctx := api.ctx
if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
// wrap the context with the requested height
ctx = rpctypes.ContextWithHeight(blockNum.Int64())
}
res, err := api.queryClient.Balance(ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out evmtypes.QueryResBalance balance := big.NewInt(0)
api.clientCtx.Codec.MustUnmarshalJSON(res, &out) err = balance.UnmarshalText([]byte(res.Balance))
val, err := utils.UnmarshalBigInt(out.Balance)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if blockNum != rpctypes.PendingBlockNumber { if blockNum != rpctypes.PendingBlockNumber {
return (*hexutil.Big)(val), nil return (*hexutil.Big)(balance), nil
} }
// update the address balance with the pending transactions value (if applicable) // update the address balance with the pending transactions value (if applicable)
@ -256,28 +259,33 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp
} }
if tx.From == address { if tx.From == address {
val = new(big.Int).Sub(val, tx.Value.ToInt()) balance = new(big.Int).Sub(balance, tx.Value.ToInt())
} }
if *tx.To == address { if *tx.To == address {
val = new(big.Int).Add(val, tx.Value.ToInt()) balance = new(big.Int).Add(balance, tx.Value.ToInt())
} }
} }
return (*hexutil.Big)(val), nil return (*hexutil.Big)(balance), nil
} }
// GetStorageAt returns the contract storage at the given address, block number, and key. // GetStorageAt returns the contract storage at the given address, block number, and key.
//nolint:interfacer
func (api *PublicEthereumAPI) GetStorageAt(address common.Address, key string, blockNum rpctypes.BlockNumber) (hexutil.Bytes, error) { func (api *PublicEthereumAPI) GetStorageAt(address common.Address, key string, blockNum rpctypes.BlockNumber) (hexutil.Bytes, error) {
api.logger.Debug("eth_getStorageAt", "address", address, "key", key, "block number", blockNum) api.logger.Debug("eth_getStorageAt", "address", address, "key", key, "block number", blockNum)
clientCtx := api.clientCtx.WithHeight(blockNum.Int64())
res, _, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/storage/%s/%s", evmtypes.ModuleName, address.Hex(), key), nil) req := &evmtypes.QueryStorageRequest{
Address: address.String(),
Key: key,
}
res, err := api.queryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out evmtypes.QueryResStorage value := common.HexToHash(res.Value)
api.clientCtx.Codec.MustUnmarshalJSON(res, &out) return value.Bytes(), nil
return out.Value, nil
} }
// GetTransactionCount returns the number of transactions at the given address up to the given block number. // GetTransactionCount returns the number of transactions at the given address up to the given block number.
@ -304,17 +312,8 @@ func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockN
// GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash. // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash.
func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint {
api.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash) api.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash)
res, _, err := api.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, hash.Hex()))
if err != nil {
return nil
}
var out evmtypes.QueryResBlockNumber resBlock, err := api.clientCtx.Client.BlockByHash(api.ctx, hash.Bytes())
if err := api.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil
}
resBlock, err := api.clientCtx.Client.Block(&out.Number)
if err != nil { if err != nil {
return nil return nil
} }
@ -329,40 +328,45 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes
var ( var (
height int64 height int64
err error
txCount hexutil.Uint txCount hexutil.Uint
txs int txs int
) )
switch blockNum { switch blockNum {
case rpctypes.PendingBlockNumber: case rpctypes.PendingBlockNumber:
height, err = api.backend.LatestBlockNumber() // NOTE: pending fetches the latest block
resBlock, err := api.clientCtx.Client.Block(api.ctx, nil)
if err != nil { if err != nil {
return nil return nil
} }
resBlock, err := api.clientCtx.Client.Block(&height)
if err != nil { var resBlockTxLength = 0
return nil if !resBlock.BlockID.IsZero() {
resBlockTxLength = len(resBlock.Block.Txs)
} }
// get the pending transaction count // get the pending transaction count
pendingTxs, err := api.backend.PendingTransactions() pendingTxs, err := api.backend.PendingTransactions()
if err != nil { if err != nil {
return nil return nil
} }
txs = len(resBlock.Block.Txs) + len(pendingTxs)
txs = resBlockTxLength + len(pendingTxs)
case rpctypes.LatestBlockNumber: case rpctypes.LatestBlockNumber:
height, err = api.backend.LatestBlockNumber() resBlock, err := api.clientCtx.Client.Block(api.ctx, nil)
if err != nil { if err != nil {
return nil return nil
} }
resBlock, err := api.clientCtx.Client.Block(&height)
if err != nil { var resBlockTxLength = 0
return nil if !resBlock.BlockID.IsZero() {
resBlockTxLength = len(resBlock.Block.Txs)
} }
txs = len(resBlock.Block.Txs)
txs = resBlockTxLength
default: default:
height = blockNum.Int64() height = blockNum.Int64()
resBlock, err := api.clientCtx.Client.Block(&height) resBlock, err := api.clientCtx.Client.Block(api.ctx, &height)
if err != nil { if err != nil {
return nil return nil
} }
@ -373,28 +377,37 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes
return &txCount return &txCount
} }
// GetUncleCountByBlockHash returns the number of uncles in the block idenfied by hash. Always zero. // GetUncleCountByBlockHash returns the number of uncles in the block identified by hash. Always zero.
func (api *PublicEthereumAPI) GetUncleCountByBlockHash(_ common.Hash) hexutil.Uint { func (api *PublicEthereumAPI) GetUncleCountByBlockHash(_ common.Hash) hexutil.Uint {
return 0 return 0
} }
// GetUncleCountByBlockNumber returns the number of uncles in the block idenfied by number. Always zero. // GetUncleCountByBlockNumber returns the number of uncles in the block identified by number. Always zero.
func (api *PublicEthereumAPI) GetUncleCountByBlockNumber(_ rpctypes.BlockNumber) hexutil.Uint { func (api *PublicEthereumAPI) GetUncleCountByBlockNumber(_ rpctypes.BlockNumber) hexutil.Uint {
return 0 return 0
} }
// GetCode returns the contract code at the given address and block number. // GetCode returns the contract code at the given address and block number.
//nolint:interfacer
func (api *PublicEthereumAPI) GetCode(address common.Address, blockNumber rpctypes.BlockNumber) (hexutil.Bytes, error) { func (api *PublicEthereumAPI) GetCode(address common.Address, blockNumber rpctypes.BlockNumber) (hexutil.Bytes, error) {
api.logger.Debug("eth_getCode", "address", address, "block number", blockNumber) api.logger.Debug("eth_getCode", "address", address, "block number", blockNumber)
clientCtx := api.clientCtx.WithHeight(blockNumber.Int64())
res, _, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryCode, address.Hex()), nil) req := &evmtypes.QueryCodeRequest{
Address: address.String(),
}
ctx := api.ctx
if !(blockNumber == rpctypes.PendingBlockNumber || blockNumber == rpctypes.LatestBlockNumber) {
// wrap the context with the requested height
ctx = rpctypes.ContextWithHeight(blockNumber.Int64())
}
res, err := api.queryClient.Code(ctx, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out evmtypes.QueryResCode return res.Code, nil
api.clientCtx.Codec.MustUnmarshalJSON(res, &out)
return out.Code, nil
} }
// GetTransactionLogs returns the logs given a transaction hash. // GetTransactionLogs returns the logs given a transaction hash.
@ -459,7 +472,7 @@ func (api *PublicEthereumAPI) SendTransaction(args rpctypes.SendTxArgs) (common.
} }
// Encode transaction by default Tx encoder // Encode transaction by default Tx encoder
txEncoder := authclient.GetTxEncoder(api.clientCtx.Codec) txEncoder := api.clientCtx.TxConfig.TxEncoder()
txBytes, err := txEncoder(tx) txBytes, err := txEncoder(tx)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
@ -491,14 +504,13 @@ func (api *PublicEthereumAPI) SendRawTransaction(data hexutil.Bytes) (common.Has
} }
// Encode transaction by default Tx encoder // Encode transaction by default Tx encoder
txEncoder := authclient.GetTxEncoder(api.clientCtx.Codec) txBytes, err := api.clientCtx.TxConfig.TxEncoder()(tx)
txBytes, err := txEncoder(tx)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
// TODO: Possibly log the contract creation address (if recipient address is nil) or tx data // TODO: Possibly log the contract creation address (if recipient address is nil) or tx data
// If error is encountered on the node, the broadcast will not return an error // NOTE: If error is encountered on the node, the broadcast will not return an error
res, err := api.clientCtx.BroadcastTx(txBytes) res, err := api.clientCtx.BroadcastTx(txBytes)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
@ -519,7 +531,7 @@ func (api *PublicEthereumAPI) Call(args rpctypes.CallArgs, blockNr rpctypes.Bloc
return []byte{}, err return []byte{}, err
} }
data, err := evmtypes.DecodeResultData(simRes.Result.Data) data, err := evmtypes.DecodeTxResponse(simRes.Result.Data)
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
} }
@ -533,15 +545,18 @@ func (api *PublicEthereumAPI) doCall(
args rpctypes.CallArgs, blockNum rpctypes.BlockNumber, globalGasCap *big.Int, args rpctypes.CallArgs, blockNum rpctypes.BlockNumber, globalGasCap *big.Int,
) (*sdk.SimulationResponse, error) { ) (*sdk.SimulationResponse, error) {
clientCtx := api.clientCtx var height int64
// pass the given block height to the context if the height is not pending or latest // pass the given block height to the context if the height is not pending or latest
if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) { if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
clientCtx = api.clientCtx.WithHeight(blockNum.Int64()) height = blockNum.Int64()
} }
// Set sender address or use a default if none specified var (
var addr common.Address addr common.Address
err error
)
// Set sender address or use a default if none specified
if args.From == nil { if args.From == nil {
addrs, err := api.Accounts() addrs, err := api.Accounts()
if err == nil && len(addrs) > 0 { if err == nil && len(addrs) > 0 {
@ -554,7 +569,7 @@ func (api *PublicEthereumAPI) doCall(
nonce, _ := api.accountNonce(api.clientCtx, addr, true) nonce, _ := api.accountNonce(api.clientCtx, addr, true)
// Set default gas & gas price if none were set // Set default gas & gas price if none were set
// Change this to uint64(math.MaxUint64 / 2) if gas cap can be configured // TODO: Change this to uint64(math.MaxUint64 / 2) if gas cap can be configured
gas := uint64(ethermint.DefaultRPCGasLimit) gas := uint64(ethermint.DefaultRPCGasLimit)
if args.Gas != nil { if args.Gas != nil {
gas = uint64(*args.Gas) gas = uint64(*args.Gas)
@ -582,50 +597,90 @@ func (api *PublicEthereumAPI) doCall(
data = []byte(*args.Data) data = []byte(*args.Data)
} }
var accNum, seq uint64
// Set destination address for call // Set destination address for call
var toAddr sdk.AccAddress var fromAddr sdk.AccAddress
if args.To != nil { if args.From != nil {
toAddr = sdk.AccAddress(args.To.Bytes()) fromAddr = sdk.AccAddress(args.From.Bytes())
accNum, seq, err = api.clientCtx.AccountRetriever.GetAccountNumberSequence(api.clientCtx, fromAddr)
if err != nil {
return nil, err
}
} }
var msgs []sdk.Msg var msgs []sdk.Msg
// Create new call message // Create new call message
msg := evmtypes.NewMsgEthermint(nonce, &toAddr, sdk.NewIntFromBigInt(value), gas, msg := evmtypes.NewMsgEthereumTx(seq, args.To, value, gas, gasPrice, data)
sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes())) if err := msg.ValidateBasic(); err != nil {
return nil, err
}
msgs = append(msgs, msg) msgs = append(msgs, msg)
feeAmount := big.NewInt(0)
// convert the pending transactions into ethermint msgs // convert the pending transactions into ethermint msgs
if blockNum == rpctypes.PendingBlockNumber { if blockNum == rpctypes.PendingBlockNumber {
pendingMsgs, err := api.pendingMsgs() pendingMsgs, fee, err := api.pendingMsgs()
if err != nil { if err != nil {
return nil, err return nil, err
} }
feeAmount = new(big.Int).Add(feeAmount, fee)
msgs = append(msgs, pendingMsgs...) msgs = append(msgs, pendingMsgs...)
} }
// Generate tx to be used to simulate (signature isn't needed) privKey, exists := rpctypes.GetKeyByAddress(api.keys, addr)
var stdSig authtypes.StdSignature if !exists {
stdSigs := []authtypes.StdSignature{stdSig} return nil, fmt.Errorf("account with address %s does not exist in keyring", addr.String())
tx := authtypes.NewStdTx(msgs, authtypes.StdFee{}, stdSigs, "")
if err := tx.ValidateBasic(); err != nil {
return nil, err
} }
txEncoder := authclient.GetTxEncoder(clientCtx.Codec) // NOTE: we query the EVM denomination to allow other chains to use their custom denomination as
txBytes, err := txEncoder(tx) // the fee token
paramsRes, err := api.queryClient.Params(api.ctx, &evmtypes.QueryParamsRequest{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Transaction simulation through query // create the fee coins with the amount equal to the sum of all msg fees
res, _, err := clientCtx.QueryWithData("app/simulate", txBytes) fees := sdk.NewCoins(sdk.NewCoin(paramsRes.Params.EvmDenom, sdk.NewIntFromBigInt(feeAmount)))
finalMsgs := make([]sdk.Msg, 0, len(msgs))
for _, msg := range msgs {
m, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return nil, fmt.Errorf("invalid message type assertion")
}
err = m.Sign(api.chainIDEpoch, privKey.ToECDSA())
if err != nil {
return nil, fmt.Errorf("sign msg err: %s", err.Error())
}
_, err = m.VerifySig(api.chainIDEpoch)
if err != nil {
return nil, fmt.Errorf("verify msg signature err %s", err.Error())
}
finalMsgs = append(finalMsgs, m)
}
txBytes, err := rpctypes.BuildEthereumTx(api.clientCtx, finalMsgs, accNum, seq, gas, fees, privKey)
if err != nil {
return nil, err
}
// simulate by calling ABCI Query
query := abci.RequestQuery{
Path: "/app/simulate",
Data: txBytes,
Height: height,
}
queryResult, err := api.clientCtx.QueryABCI(query)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var simResponse sdk.SimulationResponse var simResponse sdk.SimulationResponse
if err := clientCtx.Codec.UnmarshalBinaryBare(res, &simResponse); err != nil { err = jsonpb.Unmarshal(strings.NewReader(string(queryResult.Value)), &simResponse)
if err != nil {
return nil, err return nil, err
} }
@ -663,19 +718,15 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu
return api.backend.GetBlockByNumber(blockNum, fullTx) return api.backend.GetBlockByNumber(blockNum, fullTx)
} }
height, err := api.backend.LatestBlockNumber() // fetch latest block
if err != nil { latestBlock, err := api.clientCtx.Client.Block(api.ctx, nil)
return nil, err
}
// latest block info
latestBlock, err := api.clientCtx.Client.Block(&height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// number of pending txs queried from the mempool // number of pending txs queried from the mempool
unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(1000) limit := 1000
unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(api.ctx, &limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -689,7 +740,7 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu
tmtypes.Header{ tmtypes.Header{
Version: latestBlock.Block.Version, Version: latestBlock.Block.Version,
ChainID: api.clientCtx.ChainID, ChainID: api.clientCtx.ChainID,
Height: height + 1, Height: latestBlock.Block.Height + 1,
Time: time.Unix(0, 0), Time: time.Unix(0, 0),
LastBlockID: latestBlock.Block.LastBlockID, LastBlockID: latestBlock.Block.LastBlockID,
ValidatorsHash: latestBlock.Block.NextValidatorsHash, ValidatorsHash: latestBlock.Block.NextValidatorsHash,
@ -707,8 +758,7 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu
// GetTransactionByHash returns the transaction identified by hash. // GetTransactionByHash returns the transaction identified by hash.
func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) { func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) {
api.logger.Debug("eth_getTransactionByHash", "hash", hash) api.logger.Debug("eth_getTransactionByHash", "hash", hash)
tx, err := api.clientCtx.Client.Tx(api.ctx, hash.Bytes(), false)
tx, err := api.clientCtx.Client.Tx(hash.Bytes(), false)
if err != nil { if err != nil {
// check if the tx is on the mempool // check if the tx is on the mempool
pendingTxs, pendingErr := api.PendingTransactions() pendingTxs, pendingErr := api.PendingTransactions()
@ -729,7 +779,7 @@ func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.
} }
// Can either cache or just leave this out if not necessary // Can either cache or just leave this out if not necessary
block, err := api.clientCtx.Client.Block(&tx.Height) block, err := api.clientCtx.Client.Block(api.ctx, &tx.Height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -748,19 +798,11 @@ func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.
// GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index.
func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.Transaction, error) { func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.Transaction, error) {
api.logger.Debug("eth_getTransactionByHashAndIndex", "hash", hash, "index", idx) api.logger.Debug("eth_getTransactionByHashAndIndex", "hash", hash, "index", idx)
res, _, err := api.clientCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, hash.Hex()))
resBlock, err := api.clientCtx.Client.BlockByHash(api.ctx, hash.Bytes())
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out evmtypes.QueryResBlockNumber
api.clientCtx.Codec.MustUnmarshalJSON(res, &out)
resBlock, err := api.clientCtx.Client.Block(&out.Number)
if err != nil {
return nil, err
}
return api.getTransactionByBlockAndIndex(resBlock.Block, idx) return api.getTransactionByBlockAndIndex(resBlock.Block, idx)
} }
@ -768,7 +810,7 @@ func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash
func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) { func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) {
api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
var ( var (
height int64 height *int64
err error err error
) )
@ -789,16 +831,15 @@ func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpcty
return pendingTxs[int(idx)], nil return pendingTxs[int(idx)], nil
case rpctypes.LatestBlockNumber: case rpctypes.LatestBlockNumber:
height, err = api.backend.LatestBlockNumber() // nil fetches the latest block
if err != nil { height = nil
return nil, err
}
default: default:
height = blockNum.Int64() h := blockNum.Int64()
height = &h
} }
resBlock, err := api.clientCtx.Client.Block(&height) resBlock, err := api.clientCtx.Client.Block(api.ctx, height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -827,14 +868,14 @@ func (api *PublicEthereumAPI) getTransactionByBlockAndIndex(block *tmtypes.Block
// GetTransactionReceipt returns the transaction receipt identified by hash. // GetTransactionReceipt returns the transaction receipt identified by hash.
func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
api.logger.Debug("eth_getTransactionReceipt", "hash", hash) api.logger.Debug("eth_getTransactionReceipt", "hash", hash)
tx, err := api.clientCtx.Client.Tx(hash.Bytes(), false) tx, err := api.clientCtx.Client.Tx(api.ctx, hash.Bytes(), false)
if err != nil { if err != nil {
// Return nil for transaction when not found // Return nil for transaction when not found
return nil, nil return nil, nil
} }
// Query block for consensus hash // Query block for consensus hash
block, err := api.clientCtx.Client.Block(&tx.Height) block, err := api.clientCtx.Client.Block(api.ctx, &tx.Height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -854,7 +895,7 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin
cumulativeGasUsed := uint64(tx.TxResult.GasUsed) cumulativeGasUsed := uint64(tx.TxResult.GasUsed)
if tx.Index != 0 { if tx.Index != 0 {
cumulativeGasUsed += rpctypes.GetBlockCumulativeGas(api.clientCtx.Codec, block.Block, int(tx.Index)) cumulativeGasUsed += rpctypes.GetBlockCumulativeGas(api.clientCtx, block.Block, int(tx.Index))
} }
// Set status codes based on tx result // Set status codes based on tx result
@ -867,13 +908,13 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin
txData := tx.TxResult.GetData() txData := tx.TxResult.GetData()
data, err := evmtypes.DecodeResultData(txData) data, err := evmtypes.DecodeTxResponse(txData)
if err != nil { if err != nil {
status = 0 // transaction failed status = 0 // transaction failed
} }
if len(data.Logs) == 0 { if len(data.TxLogs.Logs) == 0 {
data.Logs = []*ethtypes.Log{} data.TxLogs.Logs = []*evmtypes.Log{}
} }
receipt := map[string]interface{}{ receipt := map[string]interface{}{
@ -881,7 +922,7 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin
"status": status, "status": status,
"cumulativeGasUsed": hexutil.Uint64(cumulativeGasUsed), "cumulativeGasUsed": hexutil.Uint64(cumulativeGasUsed),
"logsBloom": data.Bloom, "logsBloom": data.Bloom,
"logs": data.Logs, "logs": data.TxLogs.EthLogs(),
// Implementation fields: These fields are added by geth when processing a transaction. // Implementation fields: These fields are added by geth when processing a transaction.
// They are stored in the chain database. // They are stored in the chain database.
@ -922,73 +963,70 @@ func (api *PublicEthereumAPI) GetUncleByBlockNumberAndIndex(number hexutil.Uint,
// GetProof returns an account object with proof and any storage proofs // GetProof returns an account object with proof and any storage proofs
func (api *PublicEthereumAPI) GetProof(address common.Address, storageKeys []string, block rpctypes.BlockNumber) (*rpctypes.AccountResult, error) { func (api *PublicEthereumAPI) GetProof(address common.Address, storageKeys []string, block rpctypes.BlockNumber) (*rpctypes.AccountResult, error) {
api.logger.Debug("eth_getProof", "address", address, "keys", storageKeys, "number", block) height := block.Int64()
api.logger.Debug("eth_getProof", "address", address, "keys", storageKeys, "number", height)
clientCtx := api.clientCtx.WithHeight(int64(block)) ctx := rpctypes.ContextWithHeight(height)
path := fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryAccount, address.Hex()) clientCtx := api.clientCtx.WithHeight(height)
// query eth account at block height
resBz, _, err := clientCtx.Query(path)
if err != nil {
return nil, err
}
var account evmtypes.QueryResAccount
clientCtx.Codec.MustUnmarshalJSON(resBz, &account)
// query storage proofs
storageProofs := make([]rpctypes.StorageResult, len(storageKeys)) storageProofs := make([]rpctypes.StorageResult, len(storageKeys))
opts := client.ABCIQueryOptions{Height: int64(block), Prove: true} for i, key := range storageKeys {
for i, k := range storageKeys { hexKey := common.HexToHash(key)
// Get value for key valueBz, proof, err := api.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes()))
vPath := fmt.Sprintf("custom/%s/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryStorage, address, k)
vRes, err := api.clientCtx.Client.ABCIQueryWithOptions(vPath, nil, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var value evmtypes.QueryResStorage
clientCtx.Codec.MustUnmarshalJSON(vRes.Response.GetValue(), &value)
// check for proof // check for proof
proof := vRes.Response.GetProof() var proofStr string
proofStr := new(merkle.Proof).String()
if proof != nil { if proof != nil {
proofStr = proof.String() proofStr = proof.String()
} }
storageProofs[i] = rpctypes.StorageResult{ storageProofs[i] = rpctypes.StorageResult{
Key: k, Key: key,
Value: (*hexutil.Big)(common.BytesToHash(value.Value).Big()), Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
Proof: []string{proofStr}, Proof: []string{proofStr},
} }
} }
req := abci.RequestQuery{ // query EVM account
Path: fmt.Sprintf("store/%s/key", auth.StoreKey), req := &evmtypes.QueryAccountRequest{
Data: auth.AddressStoreKey(sdk.AccAddress(address.Bytes())), Address: address.String(),
Height: int64(block),
Prove: true,
} }
res, err := clientCtx.QueryABCI(req) res, err := api.queryClient.Account(ctx, req)
if err != nil {
return nil, err
}
// query account proofs
accountKey := authtypes.AddressStoreKey(sdk.AccAddress(address.Bytes()))
_, proof, err := api.queryClient.GetProof(clientCtx, authtypes.StoreKey, accountKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// check for proof // check for proof
accountProof := res.GetProof() var accProofStr string
accProofStr := new(merkle.Proof).String() if proof != nil {
if accountProof != nil { accProofStr = proof.String()
accProofStr = accountProof.String() }
balance := big.NewInt(0)
err = balance.UnmarshalText([]byte(res.Balance))
if err != nil {
return nil, err
} }
return &rpctypes.AccountResult{ return &rpctypes.AccountResult{
Address: address, Address: address,
AccountProof: []string{accProofStr}, AccountProof: []string{accProofStr},
Balance: (*hexutil.Big)(utils.MustUnmarshalBigInt(account.Balance)), Balance: (*hexutil.Big)(balance),
CodeHash: common.BytesToHash(account.CodeHash), CodeHash: common.BytesToHash(res.CodeHash),
Nonce: hexutil.Uint64(account.Nonce), Nonce: hexutil.Uint64(res.Nonce),
StorageHash: common.Hash{}, // Ethermint doesn't have a storage hash StorageHash: common.Hash{}, // NOTE: Ethermint doesn't have a storage hash. TODO: implement?
StorageProof: storageProofs, StorageProof: storageProofs,
}, nil }, nil
} }
@ -1025,7 +1063,7 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty
} }
// Sets input to either Input or Data, if both are set and not equal error above returns // Sets input to either Input or Data, if both are set and not equal error above returns
var input []byte var input hexutil.Bytes
if args.Input != nil { if args.Input != nil {
input = *args.Input input = *args.Input
} else if args.Data != nil { } else if args.Data != nil {
@ -1044,7 +1082,7 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty
Gas: args.Gas, Gas: args.Gas,
GasPrice: args.GasPrice, GasPrice: args.GasPrice,
Value: args.Value, Value: args.Value,
Data: args.Data, Data: &input,
} }
gl, err := api.EstimateGas(callArgs) gl, err := api.EstimateGas(callArgs)
if err != nil { if err != nil {
@ -1056,29 +1094,29 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty
} }
msg := evmtypes.NewMsgEthereumTx(nonce, args.To, amount, gasLimit, gasPrice, input) msg := evmtypes.NewMsgEthereumTx(nonce, args.To, amount, gasLimit, gasPrice, input)
return &msg, nil return msg, nil
} }
// pendingMsgs constructs an array of sdk.Msg. This method will check pending transactions and convert // pendingMsgs constructs an array of sdk.Msg. This method will check pending transactions and convert
// those transactions into ethermint messages. // those transactions into ethereum messages. Alonside with the msgs it returns the total fees for all the
func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { // pending txs.
func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, *big.Int, error) {
// nolint: prealloc // nolint: prealloc
var msgs []sdk.Msg var msgs []sdk.Msg
feeAmount := big.NewInt(0)
pendingTxs, err := api.PendingTransactions() pendingTxs, err := api.PendingTransactions()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
for _, pendingTx := range pendingTxs { for _, pendingTx := range pendingTxs {
// NOTE: we have to construct the EVM transaction instead of just casting from the tendermint // NOTE: we have to construct the EVM transaction instead of just casting from the tendermint
// transactions because PendingTransactions only checks for MsgEthereumTx messages. // transactions because PendingTransactions only checks for MsgEthereumTx messages.
pendingTo := sdk.AccAddress(pendingTx.To.Bytes())
pendingFrom := sdk.AccAddress(pendingTx.From.Bytes())
pendingGas, err := hexutil.DecodeUint64(pendingTx.Gas.String()) pendingGas, err := hexutil.DecodeUint64(pendingTx.Gas.String())
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
pendingValue := pendingTx.Value.ToInt() pendingValue := pendingTx.Value.ToInt()
@ -1090,35 +1128,38 @@ func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) {
pendingData := pendingTx.Input pendingData := pendingTx.Input
nonce, _ := api.accountNonce(api.clientCtx, pendingTx.From, true) nonce, _ := api.accountNonce(api.clientCtx, pendingTx.From, true)
msg := evmtypes.NewMsgEthermint(nonce, &pendingTo, sdk.NewIntFromBigInt(pendingValue), pendingGas, msg := evmtypes.NewMsgEthereumTx(
sdk.NewIntFromBigInt(pendingGasPrice), pendingData, pendingFrom) 0,
pendingTx.To,
pendingValue,
pendingGas,
pendingGasPrice,
pendingData,
)
feeAmount = new(big.Int).Add(feeAmount, msg.Fee())
msgs = append(msgs, msg) msgs = append(msgs, msg)
} }
return msgs, nil return msgs, feeAmount, nil
} }
// accountNonce returns looks up the transaction nonce count for a given address. If the pending boolean // accountNonce returns looks up the transaction nonce count for a given address. If the pending boolean
// is set to true, it will add to the counter all the uncommitted EVM transactions sent from the address. // is set to true, it will add to the counter all the uncommitted EVM transactions sent from the address.
// NOTE: The function returns no error if the account doesn't exist. // NOTE: The function returns no error if the account doesn't exist.
func (api *PublicEthereumAPI) accountNonce( func (api *PublicEthereumAPI) accountNonce(
clientCtx clientcontext.CLIContext, address common.Address, pending bool, clientCtx client.Context, address common.Address, pending bool,
) (uint64, error) { ) (uint64, error) {
// Get nonce (sequence) from sender account // Get nonce (sequence) from sender account
from := sdk.AccAddress(address.Bytes()) from := sdk.AccAddress(address.Bytes())
// use a the given client context in case its wrapped with a custom height // use a the given client context in case its wrapped with a custom height
accRet := authtypes.NewAccountRetriever(clientCtx) account, err := clientCtx.AccountRetriever.GetAccount(clientCtx, from)
if err != nil || account == nil {
if err := accRet.EnsureExists(from); err != nil {
// account doesn't exist yet, return 0 // account doesn't exist yet, return 0
return 0, nil return 0, nil
} }
_, nonce, err := accRet.GetAccountNumberSequence(from) nonce := account.GetSequence()
if err != nil {
return 0, err
}
if !pending { if !pending {
return nonce, nil return nonce, nil
@ -1131,15 +1172,17 @@ func (api *PublicEthereumAPI) accountNonce(
return 0, err return 0, err
} }
if len(pendingTxs) == 0 {
return nonce, nil
}
// add the uncommitted txs to the nonce counter // add the uncommitted txs to the nonce counter
if len(pendingTxs) != 0 { for i := range pendingTxs {
for i := range pendingTxs { if pendingTxs[i] == nil {
if pendingTxs[i] == nil { continue
continue }
} if pendingTxs[i].From == address {
if pendingTxs[i].From == address { nonce++
nonce++
}
} }
} }

View File

@ -6,6 +6,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/gogo/protobuf/proto"
coretypes "github.com/tendermint/tendermint/rpc/core/types" coretypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
@ -14,7 +16,7 @@ import (
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
clientcontext "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
@ -48,7 +50,7 @@ type filter struct {
// PublicFilterAPI offers support to create and manage filters. This will allow external clients to retrieve various // PublicFilterAPI offers support to create and manage filters. This will allow external clients to retrieve various
// information related to the Ethereum protocol such as blocks, transactions and logs. // information related to the Ethereum protocol such as blocks, transactions and logs.
type PublicFilterAPI struct { type PublicFilterAPI struct {
clientCtx clientcontext.CLIContext clientCtx client.Context
backend Backend backend Backend
events *EventSystem events *EventSystem
filtersMu sync.Mutex filtersMu sync.Mutex
@ -56,13 +58,7 @@ type PublicFilterAPI struct {
} }
// NewAPI returns a new PublicFilterAPI instance. // NewAPI returns a new PublicFilterAPI instance.
func NewAPI(clientCtx clientcontext.CLIContext, backend Backend) *PublicFilterAPI { func NewAPI(clientCtx client.Context, backend Backend) *PublicFilterAPI {
// start the client to subscribe to Tendermint events
err := clientCtx.Client.Start()
if err != nil {
panic(err)
}
api := &PublicFilterAPI{ api := &PublicFilterAPI{
clientCtx: clientCtx, clientCtx: clientCtx,
backend: backend, backend: backend,
@ -122,7 +118,8 @@ func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID {
select { select {
case ev := <-txsCh: case ev := <-txsCh:
data, _ := ev.Data.(tmtypes.EventDataTx) data, _ := ev.Data.(tmtypes.EventDataTx)
txHash := common.BytesToHash(data.Tx.Hash())
txHash := common.BytesToHash(tmtypes.Tx(data.Tx).Hash())
api.filtersMu.Lock() api.filtersMu.Lock()
if f, found := api.filters[pendingTxSub.ID()]; found { if f, found := api.filters[pendingTxSub.ID()]; found {
@ -167,7 +164,7 @@ func (api *PublicFilterAPI) NewPendingTransactions(ctx context.Context) (*rpc.Su
select { select {
case ev := <-txsCh: case ev := <-txsCh:
data, _ := ev.Data.(tmtypes.EventDataTx) data, _ := ev.Data.(tmtypes.EventDataTx)
txHash := common.BytesToHash(data.Tx.Hash()) txHash := common.BytesToHash(tmtypes.Tx(data.Tx).Hash())
// To keep the original behaviour, send a single tx hash in one notification. // To keep the original behaviour, send a single tx hash in one notification.
// TODO(rjl493456442) Send a batch of tx hashes in one notification // TODO(rjl493456442) Send a batch of tx hashes in one notification
@ -297,10 +294,9 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri
select { select {
case event := <-logsCh: case event := <-logsCh:
// filter only events from EVM module txs // filter only events from EVM module txs
_, isMsgEthermint := event.Events[evmtypes.TypeMsgEthermint]
_, isMsgEthereumTx := event.Events[evmtypes.TypeMsgEthereumTx] _, isMsgEthereumTx := event.Events[evmtypes.TypeMsgEthereumTx]
if !(isMsgEthermint || isMsgEthereumTx) { if !isMsgEthereumTx {
// ignore transaction as it's not from the evm module // ignore transaction as it's not from the evm module
return return
} }
@ -313,12 +309,13 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri
return return
} }
resultData, err := evmtypes.DecodeResultData(dataTx.TxResult.Result.Data) var txResponse evmtypes.MsgEthereumTxResponse
err := proto.Unmarshal(dataTx.TxResult.Result.Data, &txResponse)
if err != nil { if err != nil {
return return
} }
logs := FilterLogs(resultData.Logs, crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics) logs := FilterLogs(txResponse.TxLogs.EthLogs(), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics)
for _, log := range logs { for _, log := range logs {
err = notifier.Notify(rpcSub.ID, log) err = notifier.Notify(rpcSub.ID, log)
@ -381,13 +378,12 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID,
return return
} }
var resultData evmtypes.ResultData txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
resultData, err = evmtypes.DecodeResultData(dataTx.TxResult.Result.Data)
if err != nil { if err != nil {
return return
} }
logs := FilterLogs(resultData.Logs, criteria.FromBlock, criteria.ToBlock, criteria.Addresses, criteria.Topics) logs := FilterLogs(txResponse.TxLogs.EthLogs(), criteria.FromBlock, criteria.ToBlock, criteria.Addresses, criteria.Topics)
api.filtersMu.Lock() api.filtersMu.Lock()
if f, found := api.filters[filterID]; found { if f, found := api.filters[filterID]; found {

View File

@ -253,16 +253,16 @@ type filterIndex map[filters.Type]map[rpc.ID]*Subscription
func (es *EventSystem) handleLogs(ev coretypes.ResultEvent) { func (es *EventSystem) handleLogs(ev coretypes.ResultEvent) {
data, _ := ev.Data.(tmtypes.EventDataTx) data, _ := ev.Data.(tmtypes.EventDataTx)
resultData, err := evmtypes.DecodeResultData(data.TxResult.Result.Data) txResponse, err := evmtypes.DecodeTxResponse(data.TxResult.Result.Data)
if err != nil { if err != nil {
return return
} }
if len(resultData.Logs) == 0 { if len(txResponse.TxLogs.Logs) == 0 {
return return
} }
for _, f := range es.index[filters.LogsSubscription] { for _, f := range es.index[filters.LogsSubscription] {
matchedLogs := FilterLogs(resultData.Logs, f.logsCrit.FromBlock, f.logsCrit.ToBlock, f.logsCrit.Addresses, f.logsCrit.Topics) matchedLogs := FilterLogs(txResponse.TxLogs.EthLogs(), f.logsCrit.FromBlock, f.logsCrit.ToBlock, f.logsCrit.Addresses, f.logsCrit.Topics)
if len(matchedLogs) > 0 { if len(matchedLogs) > 0 {
f.logs <- matchedLogs f.logs <- matchedLogs
} }
@ -272,7 +272,7 @@ func (es *EventSystem) handleLogs(ev coretypes.ResultEvent) {
func (es *EventSystem) handleTxsEvent(ev coretypes.ResultEvent) { func (es *EventSystem) handleTxsEvent(ev coretypes.ResultEvent) {
data, _ := ev.Data.(tmtypes.EventDataTx) data, _ := ev.Data.(tmtypes.EventDataTx)
for _, f := range es.index[filters.PendingTransactionsSubscription] { for _, f := range es.index[filters.PendingTransactionsSubscription] {
f.hashes <- []common.Hash{common.BytesToHash(data.Tx.Hash())} f.hashes <- []common.Hash{common.BytesToHash(tmtypes.Tx(data.Tx).Hash())}
} }
} }

View File

@ -8,6 +8,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
coretypes "github.com/tendermint/tendermint/rpc/core/types" coretypes "github.com/tendermint/tendermint/rpc/core/types"
) )

View File

@ -3,7 +3,8 @@ package net
import ( import (
"fmt" "fmt"
"github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
ethermint "github.com/cosmos/ethermint/types" ethermint "github.com/cosmos/ethermint/types"
) )
@ -13,7 +14,7 @@ type PublicNetAPI struct {
} }
// NewAPI creates an instance of the public Net Web3 API. // NewAPI creates an instance of the public Net Web3 API.
func NewAPI(clientCtx context.CLIContext) *PublicNetAPI { func NewAPI(clientCtx client.Context) *PublicNetAPI {
// parse the chainID from a integer string // parse the chainID from a integer string
chainIDEpoch, err := ethermint.ParseChainID(clientCtx.ChainID) chainIDEpoch, err := ethermint.ParseChainID(clientCtx.ChainID)
if err != nil { if err != nil {

View File

@ -7,10 +7,12 @@ import (
"os" "os"
"time" "time"
"github.com/cosmos/ethermint/crypto/hd"
ethermint "github.com/cosmos/ethermint/types"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/crypto/keys" sdkcrypto "github.com/cosmos/cosmos-sdk/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -18,7 +20,6 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" "github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/crypto/hd"
"github.com/cosmos/ethermint/rpc/namespaces/eth" "github.com/cosmos/ethermint/rpc/namespaces/eth"
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
) )
@ -27,7 +28,7 @@ import (
type PrivateAccountAPI struct { type PrivateAccountAPI struct {
ethAPI *eth.PublicEthereumAPI ethAPI *eth.PublicEthereumAPI
logger log.Logger logger log.Logger
keyInfos []keys.Info // all keys, both locked and unlocked. unlocked keys are stored in ethAPI.keys keyInfos []keyring.Info // all keys, both locked and unlocked. unlocked keys are stored in ethAPI.keys
} }
// NewAPI creates an instance of the public Personal Eth API. // NewAPI creates an instance of the public Personal Eth API.
@ -42,7 +43,7 @@ func NewAPI(ethAPI *eth.PublicEthereumAPI) *PrivateAccountAPI {
return api return api
} }
api.keyInfos, err = api.ethAPI.ClientCtx().Keybase.List() api.keyInfos, err = api.ethAPI.ClientCtx().Keyring.List()
if err != nil { if err != nil {
return api return api
} }
@ -61,27 +62,27 @@ func (api *PrivateAccountAPI) ImportRawKey(privkey, password string) (common.Add
return common.Address{}, err return common.Address{}, err
} }
privKey := ethsecp256k1.PrivKey(crypto.FromECDSA(priv)) privKey := &ethsecp256k1.PrivKey{Key: crypto.FromECDSA(priv)}
armor := mintkey.EncryptArmorPrivKey(privKey, password, ethsecp256k1.KeyType) armor := sdkcrypto.EncryptArmorPrivKey(privKey, password, ethsecp256k1.KeyType)
// ignore error as we only care about the length of the list // ignore error as we only care about the length of the list
list, _ := api.ethAPI.ClientCtx().Keybase.List() list, _ := api.ethAPI.ClientCtx().Keyring.List()
privKeyName := fmt.Sprintf("personal_%d", len(list)) privKeyName := fmt.Sprintf("personal_%d", len(list))
if err := api.ethAPI.ClientCtx().Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { if err := api.ethAPI.ClientCtx().Keyring.ImportPrivKey(privKeyName, armor, password); err != nil {
return common.Address{}, err return common.Address{}, err
} }
addr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) addr := common.BytesToAddress(privKey.PubKey().Address().Bytes())
info, err := api.ethAPI.ClientCtx().Keybase.Get(privKeyName) info, err := api.ethAPI.ClientCtx().Keyring.Key(privKeyName)
if err != nil { if err != nil {
return common.Address{}, err return common.Address{}, err
} }
// append key and info to be able to lock and list the account // append key and info to be able to lock and list the account
//api.ethAPI.keys = append(api.ethAPI.keys, privKey) // api.ethAPI.keys = append(api.ethAPI.keys, privKey)
api.keyInfos = append(api.keyInfos, info) api.keyInfos = append(api.keyInfos, info)
api.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) api.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String())
@ -116,7 +117,7 @@ func (api *PrivateAccountAPI) LockAccount(address common.Address) bool {
copy(tmp[i:], keys[i+1:]) copy(tmp[i:], keys[i+1:])
api.ethAPI.SetKeys(tmp) api.ethAPI.SetKeys(tmp)
api.logger.Debug("account unlocked", "address", address.String()) api.logger.Debug("account locked", "address", address.String())
return true return true
} }
@ -128,16 +129,33 @@ func (api *PrivateAccountAPI) NewAccount(password string) (common.Address, error
api.logger.Debug("personal_newAccount") api.logger.Debug("personal_newAccount")
name := "key_" + time.Now().UTC().Format(time.RFC3339) name := "key_" + time.Now().UTC().Format(time.RFC3339)
info, _, err := api.ethAPI.ClientCtx().Keybase.CreateMnemonic(name, keys.English, password, hd.EthSecp256k1) info, _, err := api.ethAPI.ClientCtx().Keyring.NewMnemonic(name, keyring.English, ethermint.BIP44HDPath, hd.EthSecp256k1)
if err != nil { if err != nil {
return common.Address{}, err return common.Address{}, err
} }
// TODO: rpc_test_fix: if we use NewMnemonic, it will create an account automatically, and
// the new account encrypted with default empty string in cosmos-SDK,
// if we create mnemonic then create new account, we basically generated two accounts
// nolint
//name = "key_" + time.Now().UTC().Format(time.RFC3339)
//info, err := api.ethAPI.ClientCtx().Keyring.NewAccount(name, mnemonic, password, ethermint.BIP44HDPath, hd.EthSecp256k1)
//if err != nil {
// return common.Address{}, err
//}
//
//// encrypt the key info with given password
//armor, err := api.ethAPI.ClientCtx().Keyring.ExportPrivKeyArmor(info.GetName(), password)
//if err != nil {
// return common.Address{}, err
//}
api.keyInfos = append(api.keyInfos, info) api.keyInfos = append(api.keyInfos, info)
addr := common.BytesToAddress(info.GetPubKey().Address().Bytes()) addr := common.BytesToAddress(info.GetPubKey().Address().Bytes())
api.logger.Info("Your new key was generated", "address", addr.String()) api.logger.Info("Your new key was generated", "address", addr.String())
api.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermintd/"+name) api.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermint/"+name)
api.logger.Info("Please remember your password!") api.logger.Info("Please remember your password!")
return addr, nil return addr, nil
} }
@ -150,7 +168,7 @@ func (api *PrivateAccountAPI) UnlockAccount(_ context.Context, addr common.Addre
api.logger.Debug("personal_unlockAccount", "address", addr.String()) api.logger.Debug("personal_unlockAccount", "address", addr.String())
// TODO: use duration // TODO: use duration
var keyInfo keys.Info var keyInfo keyring.Info
for _, info := range api.keyInfos { for _, info := range api.keyInfos {
addressBytes := info.GetPubKey().Address().Bytes() addressBytes := info.GetPubKey().Address().Bytes()
@ -164,17 +182,34 @@ func (api *PrivateAccountAPI) UnlockAccount(_ context.Context, addr common.Addre
return false, fmt.Errorf("cannot find key with given address %s", addr.String()) return false, fmt.Errorf("cannot find key with given address %s", addr.String())
} }
privKey, err := api.ethAPI.ClientCtx().Keybase.ExportPrivateKeyObject(keyInfo.GetName(), password) // exporting private key only works on local keys
if keyInfo.GetType() != keyring.TypeLocal {
return false, fmt.Errorf("key type must be %s, got %s", keyring.TypeLedger.String(), keyInfo.GetType().String())
}
// TODO: rpc_test_fix: password is used for encrypt and then decrypt, what's the point of locking the account ?
armor, err := api.ethAPI.ClientCtx().Keyring.ExportPrivKeyArmor(keyInfo.GetName(), password)
if err != nil { if err != nil {
return false, err return false, err
} }
ethermintPrivKey, ok := privKey.(ethsecp256k1.PrivKey) privKey, algo, err := sdkcrypto.UnarmorDecryptPrivKey(armor, password)
if err != nil {
return false, err
}
// TODO: rpc_test_fix: we need to support both ethsecp256k1 and secp256k1, however, cosmos-SDK only support secp256k1 when init with keys add CLI
// so that the very first account has key type as secp256k1, thus, we need to support both key types here
if algo != ethsecp256k1.KeyType {
return false, fmt.Errorf("invalid key algorithm, got %s, expected %s", algo, ethsecp256k1.KeyType)
}
ethermintPrivKey, ok := privKey.(*ethsecp256k1.PrivKey)
if !ok { if !ok {
return false, fmt.Errorf("invalid private key type %T, expected %T", privKey, &ethsecp256k1.PrivKey{}) return false, fmt.Errorf("invalid private key type %T, expected %T", privKey, &ethsecp256k1.PrivKey{})
} }
api.ethAPI.SetKeys(append(api.ethAPI.GetKeys(), ethermintPrivKey)) api.ethAPI.SetKeys(append(api.ethAPI.GetKeys(), *ethermintPrivKey))
api.logger.Debug("account unlocked", "address", addr.String()) api.logger.Debug("account unlocked", "address", addr.String())
return true, nil return true, nil
} }
@ -198,6 +233,7 @@ func (api *PrivateAccountAPI) SendTransaction(_ context.Context, args rpctypes.S
func (api *PrivateAccountAPI) Sign(_ context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) { func (api *PrivateAccountAPI) Sign(_ context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) {
api.logger.Debug("personal_sign", "data", data, "address", addr.String()) api.logger.Debug("personal_sign", "data", data, "address", addr.String())
// TODO: rpc_test_fix: because the default account is secp256k1, it can not be unlocked and put into api.ethAPI array
key, ok := rpctypes.GetKeyByAddress(api.ethAPI.GetKeys(), addr) key, ok := rpctypes.GetKeyByAddress(api.ethAPI.GetKeys(), addr)
if !ok { if !ok {
return nil, fmt.Errorf("cannot find key with address %s", addr.String()) return nil, fmt.Errorf("cannot find key with address %s", addr.String())

View File

@ -1,11 +1,16 @@
package types package types
import ( import (
"context"
"fmt" "fmt"
"math" "math"
"math/big" "math/big"
"strings" "strings"
"google.golang.org/grpc/metadata"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
) )
@ -28,6 +33,16 @@ func NewBlockNumber(n *big.Int) BlockNumber {
return BlockNumber(n.Int64()) return BlockNumber(n.Int64())
} }
// ContextWithHeight wraps a context with the a gRPC block height header. If the provided height is
// 0 or -1, it will return an empty context and the gRPC query will use the latest block height for querying.
func ContextWithHeight(height int64) context.Context {
if height == LatestBlockNumber.Int64() || height == PendingBlockNumber.Int64() {
return context.Background()
}
return metadata.AppendToOutgoingContext(context.Background(), grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", height))
}
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports: // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
// - "latest", "earliest" or "pending" as string arguments // - "latest", "earliest" or "pending" as string arguments
// - the block number // - the block number

61
rpc/types/query_client.go Normal file
View File

@ -0,0 +1,61 @@
package types
import (
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/proto/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/types/tx"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
)
// QueryClient defines a gRPC Client used for:
// - Transaction simulation
// - EVM module queries
type QueryClient struct {
tx.ServiceClient
evmtypes.QueryClient
}
// NewQueryClient creates a new gRPC query client
func NewQueryClient(clientCtx client.Context) *QueryClient { // nolint: interfacer
return &QueryClient{
ServiceClient: tx.NewServiceClient(clientCtx),
QueryClient: evmtypes.NewQueryClient(clientCtx),
}
}
// GetProof performs an ABCI query with the given key and returns a merkle proof. The desired
// tendermint height to perform the query should be set in the client context. The query will be
// performed at one below this height (at the IAVL version) in order to obtain the correct merkle
// proof. Proof queries at height less than or equal to 2 are not supported.
// Issue: https://github.com/cosmos/cosmos-sdk/issues/6567
func (QueryClient) GetProof(clientCtx client.Context, storeKey string, key []byte) ([]byte, *crypto.ProofOps, error) {
height := clientCtx.Height
// ABCI queries at height less than or equal to 2 are not supported.
// Base app does not support queries for height less than or equal to 1.
// Therefore, a query at height 2 would be equivalent to a query at height 3
if height <= 2 {
return nil, nil, fmt.Errorf("proof queries at height <= 2 are not supported")
}
// Use the IAVL height if a valid tendermint height is passed in.
height--
abciReq := abci.RequestQuery{
Path: fmt.Sprintf("store/%s/key", storeKey),
Data: key,
Height: height,
Prove: true,
}
abciRes, err := clientCtx.QueryABCI(abciReq)
if err != nil {
return nil, nil, err
}
return abciRes.Value, abciRes.ProofOps, nil
}

View File

@ -9,10 +9,12 @@ import (
tmbytes "github.com/tendermint/tendermint/libs/bytes" tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
clientcontext "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/client/tx"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/ethermint/crypto/ethsecp256k1" "github.com/cosmos/ethermint/crypto/ethsecp256k1"
evmtypes "github.com/cosmos/ethermint/x/evm/types" evmtypes "github.com/cosmos/ethermint/x/evm/types"
@ -23,17 +25,17 @@ import (
) )
// RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes. // RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes.
func RawTxToEthTx(clientCtx clientcontext.CLIContext, bz []byte) (*evmtypes.MsgEthereumTx, error) { func RawTxToEthTx(clientCtx client.Context, bz []byte) (*evmtypes.MsgEthereumTx, error) {
tx, err := evmtypes.TxDecoder(clientCtx.Codec)(bz) tx, err := clientCtx.TxConfig.TxDecoder()(bz)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
} }
ethTx, ok := tx.(evmtypes.MsgEthereumTx) ethTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return nil, fmt.Errorf("invalid transaction type %T, expected %T", tx, evmtypes.MsgEthereumTx{}) return nil, fmt.Errorf("invalid transaction type %T, expected %T", tx, evmtypes.MsgEthereumTx{})
} }
return &ethTx, nil return ethTx, nil
} }
// NewTransaction returns a transaction that will serialize to the RPC // NewTransaction returns a transaction that will serialize to the RPC
@ -69,7 +71,7 @@ func NewTransaction(tx *evmtypes.MsgEthereumTx, txHash, blockHash common.Hash, b
} }
// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum blockfrom a given Tendermint block. // EthBlockFromTendermint returns a JSON-RPC compatible Ethereum blockfrom a given Tendermint block.
func EthBlockFromTendermint(clientCtx clientcontext.CLIContext, block *tmtypes.Block) (map[string]interface{}, error) { func EthBlockFromTendermint(clientCtx client.Context, queryClient *QueryClient, block *tmtypes.Block) (map[string]interface{}, error) {
gasLimit, err := BlockMaxGasFromConsensusParams(context.Background(), clientCtx) gasLimit, err := BlockMaxGasFromConsensusParams(context.Background(), clientCtx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -80,15 +82,15 @@ func EthBlockFromTendermint(clientCtx clientcontext.CLIContext, block *tmtypes.B
return nil, err return nil, err
} }
res, _, err := clientCtx.Query(fmt.Sprintf("custom/%s/%s/%d", evmtypes.ModuleName, evmtypes.QueryBloom, block.Height)) req := &evmtypes.QueryBlockBloomRequest{}
// use height 0 for querying the latest block height
res, err := queryClient.BlockBloom(ContextWithHeight(0), req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var bloomRes evmtypes.QueryBloomFilter bloom := ethtypes.BytesToBloom(res.Bloom)
clientCtx.Codec.MustUnmarshalJSON(res, &bloomRes)
bloom := bloomRes.Bloom
return FormatBlock(block.Header, block.Size(), block.Hash(), gasLimit, gasUsed, transactions, bloom), nil return FormatBlock(block.Header, block.Size(), block.Hash(), gasLimit, gasUsed, transactions, bloom), nil
} }
@ -114,7 +116,7 @@ func EthHeaderFromTendermint(header tmtypes.Header) *ethtypes.Header {
// EthTransactionsFromTendermint returns a slice of ethereum transaction hashes and the total gas usage from a set of // EthTransactionsFromTendermint returns a slice of ethereum transaction hashes and the total gas usage from a set of
// tendermint block transactions. // tendermint block transactions.
func EthTransactionsFromTendermint(clientCtx clientcontext.CLIContext, txs []tmtypes.Tx) ([]common.Hash, *big.Int, error) { func EthTransactionsFromTendermint(clientCtx client.Context, txs []tmtypes.Tx) ([]common.Hash, *big.Int, error) {
transactionHashes := []common.Hash{} transactionHashes := []common.Hash{}
gasUsed := big.NewInt(0) gasUsed := big.NewInt(0)
@ -133,8 +135,8 @@ func EthTransactionsFromTendermint(clientCtx clientcontext.CLIContext, txs []tmt
} }
// BlockMaxGasFromConsensusParams returns the gas limit for the latest block from the chain consensus params. // BlockMaxGasFromConsensusParams returns the gas limit for the latest block from the chain consensus params.
func BlockMaxGasFromConsensusParams(_ context.Context, clientCtx clientcontext.CLIContext) (int64, error) { func BlockMaxGasFromConsensusParams(ctx context.Context, clientCtx client.Context) (int64, error) {
resConsParams, err := clientCtx.Client.ConsensusParams(nil) resConsParams, err := clientCtx.Client.ConsensusParams(ctx, nil)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -194,12 +196,58 @@ func GetKeyByAddress(keys []ethsecp256k1.PrivKey, address common.Address) (key *
return nil, false return nil, false
} }
// BuildEthereumTx builds and signs a Cosmos transaction from a MsgEthereumTx and returns the tx
func BuildEthereumTx(
clientCtx client.Context,
msgs []sdk.Msg,
accNumber, seq, gasLimit uint64,
fees sdk.Coins,
privKey cryptotypes.PrivKey,
) ([]byte, error) {
signMode := clientCtx.TxConfig.SignModeHandler().DefaultMode()
signerData := authsigning.SignerData{
ChainID: clientCtx.ChainID,
AccountNumber: accNumber,
Sequence: seq,
}
// Create a TxBuilder
txBuilder := clientCtx.TxConfig.NewTxBuilder()
if err := txBuilder.SetMsgs(msgs...); err != nil {
return nil, err
}
txBuilder.SetFeeAmount(fees)
txBuilder.SetGasLimit(gasLimit)
// sign with the private key
sigV2, err := tx.SignWithPrivKey(
signMode, signerData,
txBuilder, privKey, clientCtx.TxConfig, seq,
)
if err != nil {
return nil, err
}
if err := txBuilder.SetSignatures(sigV2); err != nil {
return nil, err
}
txBytes, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
if err != nil {
return nil, err
}
return txBytes, nil
}
// GetBlockCumulativeGas returns the cumulative gas used on a block up to a given // GetBlockCumulativeGas returns the cumulative gas used on a block up to a given
// transaction index. The returned gas used includes the gas from both the SDK and // transaction index. The returned gas used includes the gas from both the SDK and
// EVM module transactions. // EVM module transactions.
func GetBlockCumulativeGas(cdc *codec.Codec, block *tmtypes.Block, idx int) uint64 { func GetBlockCumulativeGas(clientCtx client.Context, block *tmtypes.Block, idx int) uint64 {
var gasUsed uint64 var gasUsed uint64
txDecoder := evmtypes.TxDecoder(cdc) txDecoder := clientCtx.TxConfig.TxDecoder()
for i := 0; i < idx && i < len(block.Txs); i++ { for i := 0; i < idx && i < len(block.Txs); i++ {
txi, err := txDecoder(block.Txs[i]) txi, err := txDecoder(block.Txs[i])
@ -208,9 +256,9 @@ func GetBlockCumulativeGas(cdc *codec.Codec, block *tmtypes.Block, idx int) uint
} }
switch tx := txi.(type) { switch tx := txi.(type) {
case authtypes.StdTx: case *evmtypes.MsgEthereumTx:
gasUsed += tx.GetGas() gasUsed += tx.GetGas()
case evmtypes.MsgEthereumTx: case sdk.FeeTx:
gasUsed += tx.GetGas() gasUsed += tx.GetGas()
} }
} }

View File

@ -15,7 +15,7 @@ import (
"github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
context "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
rpcfilters "github.com/cosmos/ethermint/rpc/namespaces/eth/filters" rpcfilters "github.com/cosmos/ethermint/rpc/namespaces/eth/filters"
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
@ -24,7 +24,7 @@ import (
// PubSubAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec // PubSubAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec
type PubSubAPI struct { type PubSubAPI struct {
clientCtx context.CLIContext clientCtx client.Context
events *rpcfilters.EventSystem events *rpcfilters.EventSystem
filtersMu sync.Mutex filtersMu sync.Mutex
filters map[rpc.ID]*wsSubscription filters map[rpc.ID]*wsSubscription
@ -32,7 +32,7 @@ type PubSubAPI struct {
} }
// NewAPI creates an instance of the ethereum PubSub API. // NewAPI creates an instance of the ethereum PubSub API.
func NewAPI(clientCtx context.CLIContext) *PubSubAPI { func NewAPI(clientCtx client.Context) *PubSubAPI {
return &PubSubAPI{ return &PubSubAPI{
clientCtx: clientCtx, clientCtx: clientCtx,
events: rpcfilters.NewEventSystem(clientCtx.Client), events: rpcfilters.NewEventSystem(clientCtx.Client),
@ -79,6 +79,19 @@ func (api *PubSubAPI) unsubscribe(id rpc.ID) bool {
return true return true
} }
// unsubscribeAll unsubscribes all the current subscriptions
func (api *PubSubAPI) unsubscribeAll() bool { // nolint: unused
api.filtersMu.Lock()
defer api.filtersMu.Unlock()
for id, filter := range api.filters {
close(filter.unsubscribed)
delete(api.filters, id)
}
return true
}
func (api *PubSubAPI) subscribeNewHeads(conn *websocket.Conn) (rpc.ID, error) { func (api *PubSubAPI) subscribeNewHeads(conn *websocket.Conn) (rpc.ID, error) {
sub, _, err := api.events.SubscribeNewHeads() sub, _, err := api.events.SubscribeNewHeads()
if err != nil { if err != nil {
@ -209,13 +222,13 @@ func (api *PubSubAPI) subscribeLogs(conn *websocket.Conn, extra interface{}) (rp
return return
} }
var resultData evmtypes.ResultData var resultData evmtypes.MsgEthereumTxResponse
resultData, err = evmtypes.DecodeResultData(dataTx.TxResult.Result.Data) resultData, err = evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
if err != nil { if err != nil {
return return
} }
logs := rpcfilters.FilterLogs(resultData.Logs, crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics) logs := rpcfilters.FilterLogs(resultData.TxLogs.EthLogs(), crit.FromBlock, crit.ToBlock, crit.Addresses, crit.Topics)
api.filtersMu.Lock() api.filtersMu.Lock()
if f, found := api.filters[sub.ID()]; found { if f, found := api.filters[sub.ID()]; found {
@ -271,7 +284,7 @@ func (api *PubSubAPI) subscribePendingTransactions(conn *websocket.Conn) (rpc.ID
select { select {
case ev := <-txsCh: case ev := <-txsCh:
data, _ := ev.Data.(tmtypes.EventDataTx) data, _ := ev.Data.(tmtypes.EventDataTx)
txHash := common.BytesToHash(data.Tx.Hash()) txHash := common.BytesToHash(tmtypes.Tx(data.Tx).Hash())
api.filtersMu.Lock() api.filtersMu.Lock()
if f, found := api.filters[sub.ID()]; found { if f, found := api.filters[sub.ID()]; found {

View File

@ -12,48 +12,32 @@ import (
"os" "os"
"strings" "strings"
"github.com/gorilla/mux"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
context "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/types/rest"
) )
// Server defines a server that handles Ethereum websockets. // Server defines a server that handles Ethereum websockets.
type Server struct { type Server struct {
rpcAddr string // listen address of rest-server Address string
wsAddr string // listen address of ws server
api *PubSubAPI api *PubSubAPI
logger log.Logger logger log.Logger
} }
// NewServer creates a new websocket server instance. // NewServer creates a new websocket server instance.
func NewServer(clientCtx context.CLIContext, wsAddr string) *Server { func NewServer(clientCtx client.Context) *Server {
return &Server{ return &Server{
rpcAddr: viper.GetString("laddr"), Address: "",
wsAddr: wsAddr,
api: NewAPI(clientCtx), api: NewAPI(clientCtx),
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "websocket-server"), logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "websocket-server"),
} }
} }
// Start runs the websocket server
func (s *Server) Start() {
ws := mux.NewRouter()
ws.Handle("/", s)
go func() {
err := http.ListenAndServe(fmt.Sprintf(":%s", s.wsAddr), ws)
if err != nil {
s.logger.Error("http error:", err)
}
}()
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var upgrader = websocket.Upgrader{ var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { CheckOrigin: func(r *http.Request) bool {
@ -63,7 +47,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
wsConn, err := upgrader.Upgrade(w, r, nil) wsConn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
s.logger.Error("websocket upgrade failed; error:", err) err := fmt.Errorf("websocket upgrade failed: %w", err)
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return return
} }
@ -163,14 +148,14 @@ func (s *Server) readLoop(wsConn *websocket.Conn) {
// tcpGetAndSendResponse connects to the rest-server over tcp, posts a JSON-RPC request, and sends the response // tcpGetAndSendResponse connects to the rest-server over tcp, posts a JSON-RPC request, and sends the response
// to the client over websockets // to the client over websockets
func (s *Server) tcpGetAndSendResponse(conn *websocket.Conn, mb []byte) error { func (s *Server) tcpGetAndSendResponse(conn *websocket.Conn, mb []byte) error {
addr := strings.Split(s.rpcAddr, "tcp://") addr := strings.Split(s.Address, "tcp://")
if len(addr) != 2 { if len(addr) != 2 {
return fmt.Errorf("invalid laddr %s", s.rpcAddr) return fmt.Errorf("invalid laddr %s", s.Address)
} }
tcpConn, err := net.Dial("tcp", addr[1]) tcpConn, err := net.Dial("tcp", addr[1])
if err != nil { if err != nil {
return fmt.Errorf("cannot connect to %s; %s", s.rpcAddr, err) return fmt.Errorf("cannot connect to %s; %s", s.Address, err)
} }
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -179,7 +164,7 @@ func (s *Server) tcpGetAndSendResponse(conn *websocket.Conn, mb []byte) error {
return fmt.Errorf("failed to write message; %s", err) return fmt.Errorf("failed to write message; %s", err)
} }
req, err := http.NewRequest("POST", s.rpcAddr, buf) req, err := http.NewRequest("POST", s.Address, buf)
if err != nil { if err != nil {
return fmt.Errorf("failed to request; %s", err) return fmt.Errorf("failed to request; %s", err)
} }

View File

@ -1,69 +1,63 @@
#!/bin/bash #!/bin/bash
KEY="mykey" KEY="mykey"
TESTKEY="test"
CHAINID="ethermint-100" CHAINID="ethermint-100"
MONIKER="localtestnet" MONIKER="localtestnet"
# stop and remove existing daemon and client data and process(es) # stop and remove existing daemon and client data and process(es)
rm -rf $PWD/.ethermint* rm -rf ~/.ethermint*
pkill -f "ethermint*" pkill -f "ethermint*"
make build-ethermint make build-ethermint
$PWD/build/ethermintcli config keyring-backend test # if $KEY exists it should be override
"$PWD"/build/ethermintd keys add $KEY --keyring-backend test --algo "eth_secp256k1"
# Set up config for CLI
$PWD/build/ethermintcli config chain-id $CHAINID
$PWD/build/ethermintcli config output json
$PWD/build/ethermintcli config indent true
$PWD/build/ethermintcli config trust-node true
# if $KEY exists it should be deleted
$PWD/build/ethermintcli keys add $KEY
# Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer) # Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
$PWD/build/ethermintd init $MONIKER --chain-id $CHAINID "$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID
# Change parameter token denominations to aphoton # Change parameter token denominations to aphoton
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="stake"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="aphoton"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="aphoton"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aphoton"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json cat $HOME/.ethermint/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aphoton"' > $HOME/.ethermint/config/tmp_genesis.json && mv $HOME/.ethermint/config/tmp_genesis.json $HOME/.ethermint/config/genesis.json
# Allocate genesis accounts (cosmos formatted addresses) # Allocate genesis accounts (cosmos formatted addresses)
$PWD/build/ethermintd add-genesis-account "$("$PWD"/build/ethermintcli keys show "$KEY$i" -a)" 100000000000000000000aphoton "$PWD"/build/ethermintd add-genesis-account "$("$PWD"/build/ethermintd keys show "$KEY" -a --keyring-backend test)" 100000000000000000000aphoton,10000000000000000000stake --keyring-backend test
# Sign genesis transaction # Sign genesis transaction
$PWD/build/ethermintd gentx --name $KEY --amount=1000000000000000000aphoton --keyring-backend test "$PWD"/build/ethermintd gentx $KEY 10000000000000000000stake --amount=100000000000000000000aphoton --keyring-backend test --chain-id $CHAINID
# Collect genesis tx # Collect genesis tx
$PWD/build/ethermintd collect-gentxs "$PWD"/build/ethermintd collect-gentxs
# Run this to ensure everything worked and that the genesis file is setup correctly # Run this to ensure everything worked and that the genesis file is setup correctly
$PWD/build/ethermintd validate-genesis "$PWD"/build/ethermintd validate-genesis
# Start the node (remove the --pruning=nothing flag if historical queries are not needed) in background and log to file # Start the node (remove the --pruning=nothing flag if historical queries are not needed) in background and log to file
$PWD/build/ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace > ethermintd.log & "$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe --rpc-api "web3, eth, personal, net" --keyring-backend test > ethermintd.log 2>&1 &
sleep 1 # Give ethermintd node enough time to launch
sleep 5
# Start the rest server with unlocked key in background and log to file solcjs --abi "$PWD"/tests-solidity/suites/basic/contracts/Counter.sol --bin -o "$PWD"/tests-solidity/suites/basic/counter
$PWD/build/ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key $KEY --chain-id $CHAINID --trace --rpc-api="web3,eth,net,personal" > ethermintcli.log & mv "$PWD"/tests-solidity/suites/basic/counter/*.abi "$PWD"/tests-solidity/suites/basic/counter/counter_sol.abi 2> /dev/null
mv "$PWD"/tests-solidity/suites/basic/counter/*.bin "$PWD"/tests-solidity/suites/basic/counter/counter_sol.bin 2> /dev/null
solcjs --abi $PWD/tests-solidity/suites/basic/contracts/Counter.sol --bin -o $PWD/tests-solidity/suites/basic/counter # Query for the account
mv $PWD/tests-solidity/suites/basic/counter/*.abi $PWD/tests-solidity/suites/basic/counter/counter_sol.abi 2> /dev/null ACCT=$(curl --fail --silent -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | grep -o '\0x[^"]*')
mv $PWD/tests-solidity/suites/basic/counter/*.bin $PWD/tests-solidity/suites/basic/counter/counter_sol.bin 2> /dev/null echo "$ACCT"
ACCT=$(curl --fail --silent -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' -H "Content-Type: application/json" http://localhost:8545 | grep -o '\0x[^"]*' | head -1 2>&1)
echo $ACCT
# Start testcases
curl -X POST --data '{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["'$ACCT'", ""],"id":1}' -H "Content-Type: application/json" http://localhost:8545 curl -X POST --data '{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["'$ACCT'", ""],"id":1}' -H "Content-Type: application/json" http://localhost:8545
PRIVKEY="$("$PWD"/build/ethermintcli keys unsafe-export-eth-key $KEY)" #PRIVKEY="$("$PWD"/build/ethermintd keys export $KEY)"
echo $PRIVKEY
## need to get the private key from the account in order to check this functionality. ## need to get the private key from the account in order to check this functionality.
cd tests-solidity/suites/basic/ && go get && sleep 5 && go run main.go $ACCT cd tests-solidity/suites/basic/ && go get && go run main.go $ACCT
# After tests
# kill test ethermintd
echo "going to shutdown ethermintd in 3 seconds..."
sleep 3
pkill -f "ethermint*"

View File

@ -9,6 +9,9 @@ QTD=1
SLEEP_TIMEOUT=5 SLEEP_TIMEOUT=5
TEST_QTD=1 TEST_QTD=1
## remove test data dir after
REMOVE_DATA_DIR=false
#PORT AND RPC_PORT 3 initial digits, to be concat with a suffix later when node is initialized #PORT AND RPC_PORT 3 initial digits, to be concat with a suffix later when node is initialized
RPC_PORT="854" RPC_PORT="854"
IP_ADDR="0.0.0.0" IP_ADDR="0.0.0.0"
@ -29,10 +32,11 @@ usage() {
echo "-q <number> -- Quantity of nodes to run. eg: 3" echo "-q <number> -- Quantity of nodes to run. eg: 3"
echo "-z <number> -- Quantity of nodes to run tests against eg: 3" echo "-z <number> -- Quantity of nodes to run tests against eg: 3"
echo "-s <number> -- Sleep between operations in secs. eg: 5" echo "-s <number> -- Sleep between operations in secs. eg: 5"
echo "-r <string> -- Remove test dir after, eg: true, default is false"
exit 1 exit 1
} }
while getopts "h?t:q:z:s:m:" args; do while getopts "h?t:q:z:s:m:r:" args; do
case $args in case $args in
h|\?) h|\?)
usage; usage;
@ -42,6 +46,7 @@ while getopts "h?t:q:z:s:m:" args; do
z ) TEST_QTD=${OPTARG};; z ) TEST_QTD=${OPTARG};;
s ) SLEEP_TIMEOUT=${OPTARG};; s ) SLEEP_TIMEOUT=${OPTARG};;
m ) MODE=${OPTARG};; m ) MODE=${OPTARG};;
r ) REMOVE_DATA_DIR=${OPTARG};;
esac esac
done done
@ -54,13 +59,6 @@ if [[ ! "$DATA_DIR" ]]; then
exit 1 exit 1
fi fi
DATA_CLI_DIR=$(mktemp -d -t ethermint-cli-datadir.XXXXX)
if [[ ! "$DATA_CLI_DIR" ]]; then
echo "Could not create $DATA_CLI_DIR"
exit 1
fi
# Compile ethermint # Compile ethermint
echo "compiling ethermint" echo "compiling ethermint"
make build-ethermint make build-ethermint
@ -68,34 +66,30 @@ make build-ethermint
# PID array declaration # PID array declaration
arr=() arr=()
# PID arraycli declaration
arrcli=()
init_func() { init_func() {
echo "create and add new keys" "$PWD"/build/ethermintd keys add $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --no-backup --algo "eth_secp256k1"
"$PWD"/build/ethermintcli config keyring-backend test --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli keys add $KEY"$i" --home "$DATA_CLI_DIR$i" --no-backup --chain-id $CHAINID
echo "init Ethermint with moniker=$MONIKER and chain-id=$CHAINID"
"$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID --home "$DATA_DIR$i" "$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID --home "$DATA_DIR$i"
echo "init ethermintcli with chain-id=$CHAINID and config it trust-node true"
"$PWD"/build/ethermintcli config chain-id $CHAINID --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli config output json --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli config indent true --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintcli config trust-node true --home "$DATA_CLI_DIR$i"
echo "prepare genesis: Allocate genesis accounts"
"$PWD"/build/ethermintd add-genesis-account \ "$PWD"/build/ethermintd add-genesis-account \
"$("$PWD"/build/ethermintcli keys show "$KEY$i" -a --home "$DATA_CLI_DIR$i" )" 1000000000000000000aphoton,1000000000000000000stake \ "$("$PWD"/build/ethermintd keys show "$KEY$i" --keyring-backend test -a --home "$DATA_DIR$i")" 1000000000000000000aphoton,1000000000000000000stake \
--home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i" --keyring-backend test --home "$DATA_DIR$i"
echo "prepare genesis: Sign genesis transaction" "$PWD"/build/ethermintd gentx "$KEY$i" 1000000000000000000stake --amount=1000000000000000000aphoton --chain-id $CHAINID --keyring-backend test --home "$DATA_DIR$i"
"$PWD"/build/ethermintd gentx --name $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i"
echo "prepare genesis: Collect genesis tx"
"$PWD"/build/ethermintd collect-gentxs --home "$DATA_DIR$i" "$PWD"/build/ethermintd collect-gentxs --home "$DATA_DIR$i"
echo "prepare genesis: Run validate-genesis to ensure everything worked and that the genesis file is setup correctly"
"$PWD"/build/ethermintd validate-genesis --home "$DATA_DIR$i" "$PWD"/build/ethermintd validate-genesis --home "$DATA_DIR$i"
if [[ $MODE == "pending" ]]; then if [[ $MODE == "pending" ]]; then
ls $DATA_DIR$i ls $DATA_DIR$i
# sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $DATA_DIR$i/config/config.toml if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "2s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_prevote = "1s"/timeout_prevote = "120s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "2s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "2s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $DATA_DIR$i/config/config.toml
sed -i '' 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $DATA_DIR$i/config/config.toml
else
sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $DATA_DIR$i/config/config.toml
sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $DATA_DIR$i/config/config.toml sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $DATA_DIR$i/config/config.toml
sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "2s"/g' $DATA_DIR$i/config/config.toml sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "2s"/g' $DATA_DIR$i/config/config.toml
sed -i 's/timeout_prevote = "1s"/timeout_prevote = "120s"/g' $DATA_DIR$i/config/config.toml sed -i 's/timeout_prevote = "1s"/timeout_prevote = "120s"/g' $DATA_DIR$i/config/config.toml
@ -103,33 +97,29 @@ init_func() {
sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $DATA_DIR$i/config/config.toml sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $DATA_DIR$i/config/config.toml
sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "2s"/g' $DATA_DIR$i/config/config.toml sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "2s"/g' $DATA_DIR$i/config/config.toml
sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $DATA_DIR$i/config/config.toml sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $DATA_DIR$i/config/config.toml
sed -i 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $DATA_DIR$i/config/config.toml
fi
fi fi
} }
start_func() { start_func() {
echo "starting ethermint node $i in background ..." echo "starting ethermint node $i in background ..."
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" \ "$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe \
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \ --p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
--home "$DATA_DIR$i" \ --json-rpc.address http://$IP_ADDR:$RPC_PORT"$i" \
--keyring-backend test --home "$DATA_DIR$i" \
--rpc-api "web3, eth, personal, net" \
>"$DATA_DIR"/node"$i".log 2>&1 & disown >"$DATA_DIR"/node"$i".log 2>&1 & disown
ETHERMINT_PID=$! ETHERMINT_PID=$!
echo "started ethermint node, pid=$ETHERMINT_PID" echo "started ethermint node, pid=$ETHERMINT_PID"
# add PID to array # add PID to array
arr+=("$ETHERMINT_PID") arr+=("$ETHERMINT_PID")
}
start_cli_func() { if [[ $MODE == "pending" ]]; then
echo "starting ethermint node $i in background ..." echo "waiting for the first block..."
"$PWD"/build/ethermintcli rest-server --unlock-key $KEY"$i" --chain-id $CHAINID --trace --rpc-api="web3,eth,net,personal" \ sleep 300
--laddr "tcp://localhost:$RPC_PORT$i" --node tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \ fi
--home "$DATA_CLI_DIR$i" --read-timeout 30 --write-timeout 30 \
>"$DATA_CLI_DIR"/cli"$i".log 2>&1 & disown
ETHERMINT_CLI_PID=$!
echo "started ethermintcli node, pid=$ETHERMINT_CLI_PID"
# add PID to array
arrcli+=("$ETHERMINT_CLI_PID")
} }
# Run node with static blockchain database # Run node with static blockchain database
@ -138,7 +128,6 @@ for i in $(seq 1 "$QTD"); do
init_func "$i" init_func "$i"
start_func "$i" start_func "$i"
sleep 1 sleep 1
start_cli_func "$i"
echo "sleeping $SLEEP_TIMEOUT seconds for startup" echo "sleeping $SLEEP_TIMEOUT seconds for startup"
sleep "$SLEEP_TIMEOUT" sleep "$SLEEP_TIMEOUT"
echo "done sleeping" echo "done sleeping"
@ -150,37 +139,37 @@ echo "done sleeping"
set +e set +e
if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then
time_out=300s
if [[ $TEST == "pending" ]]; then
time_out=60m0s
fi
for i in $(seq 1 "$TEST_QTD"); do for i in $(seq 1 "$TEST_QTD"); do
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i" HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
echo "going to test ethermint node $HOST_RPC ..." echo "going to test ethermint node $HOST_RPC ..."
if [[ $MODE == "pending" ]]; then MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=$time_out -v -short
sleep 150
MODE=$MODE HOST=$HOST_RPC go test -v ./tests/tests-pending/rpc_pending_test.go
else
MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short
fi
RPC_FAIL=$? RPC_FAIL=$?
done done
fi fi
stop_func() { stop_func() {
ETHERMINT_PID=$i ETHERMINT_PID=$i
echo "shutting down node, pid=$ETHERMINT_PID ..." echo "shutting down node, pid=$ETHERMINT_PID ..."
# Shutdown ethermint node # Shutdown ethermint node
kill -9 "$ETHERMINT_PID" kill -9 "$ETHERMINT_PID"
wait "$ETHERMINT_PID" wait "$ETHERMINT_PID"
if [ $REMOVE_DATA_DIR == "true" ]
then
rm -rf $DATA_DIR*
fi
} }
for i in "${arrcli[@]}"; do
stop_func "$i"
done
for i in "${arr[@]}"; do for i in "${arr[@]}"; do
stop_func "$i" stop_func "$i"
done done

155
scripts/proto-tools-installer.sh Executable file
View File

@ -0,0 +1,155 @@
#!/bin/bash
set -ue
DESTDIR=${DESTDIR:-}
PREFIX=${PREFIX:-/usr/local}
UNAME_S="$(uname -s 2>/dev/null)"
UNAME_M="$(uname -m 2>/dev/null)"
BUF_VERSION=0.11.0
PROTOC_VERSION=3.13.0
PROTOC_GRPC_GATEWAY_VERSION=1.14.7
f_abort() {
local l_rc=$1
shift
echo $@ >&2
exit ${l_rc}
}
case "${UNAME_S}" in
Linux)
PROTOC_ZIP="protoc-${PROTOC_VERSION}-linux-x86_64.zip"
PROTOC_GRPC_GATEWAY_BIN="protoc-gen-grpc-gateway-v${PROTOC_GRPC_GATEWAY_VERSION}-linux-x86_64"
;;
Darwin)
PROTOC_ZIP="protoc-${PROTOC_VERSION}-osx-x86_64.zip"
PROTOC_GRPC_GATEWAY_BIN="protoc-gen-grpc-gateway-v${PROTOC_GRPC_GATEWAY_VERSION}-darwin-x86_64"
;;
*)
f_abort 1 "Unknown kernel name. Exiting."
esac
TEMPDIR="$(mktemp -d)"
trap "rm -rvf ${TEMPDIR}" EXIT
f_print_installing_with_padding() {
printf "Installing %30s ..." "$1" >&2
}
f_print_done() {
echo -e "\tDONE" >&2
}
f_ensure_tools() {
! which curl &>/dev/null && f_abort 2 "couldn't find curl, aborting" || true
}
f_ensure_dirs() {
mkdir -p "${DESTDIR}/${PREFIX}/bin"
mkdir -p "${DESTDIR}/${PREFIX}/include"
}
f_needs_install() {
if [ -x $1 ]; then
echo -e "\talready installed. Skipping." >&2
return 1
fi
return 0
}
f_install_protoc() {
f_print_installing_with_padding proto_c
f_needs_install "${DESTDIR}/${PREFIX}/bin/protoc" || return 0
pushd "${TEMPDIR}" >/dev/null
curl -o "${PROTOC_ZIP}" -sSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/${PROTOC_ZIP}"
unzip -q -o ${PROTOC_ZIP} -d ${DESTDIR}/${PREFIX} bin/protoc; \
unzip -q -o ${PROTOC_ZIP} -d ${DESTDIR}/${PREFIX} 'include/*'; \
rm -f ${PROTOC_ZIP}
popd >/dev/null
f_print_done
}
f_install_buf() {
f_print_installing_with_padding buf
f_needs_install "${DESTDIR}/${PREFIX}/bin/buf" || return 0
curl -sSL "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/buf-${UNAME_S}-${UNAME_M}" -o "${DESTDIR}/${PREFIX}/bin/buf"
chmod +x "${DESTDIR}/${PREFIX}/bin/buf"
f_print_done
}
f_install_protoc_gen_gocosmos() {
f_print_installing_with_padding protoc-gen-gocosmos
if ! grep "github.com/gogo/protobuf => github.com/regen-network/protobuf" go.mod &>/dev/null ; then
echo -e "\tPlease run this command from somewhere inside the ethermint folder."
return 1
fi
go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos 2>/dev/null
f_print_done
}
f_install_protoc_gen_grpc_gateway() {
f_print_installing_with_padding protoc-gen-grpc-gateway
f_needs_install "${DESTDIR}/${PREFIX}/bin/protoc-gen-grpc-gateway" || return 0
curl -o "${DESTDIR}/${PREFIX}/bin/protoc-gen-grpc-gateway" -sSL "https://github.com/grpc-ecosystem/grpc-gateway/releases/download/v${PROTOC_GRPC_GATEWAY_VERSION}/${PROTOC_GRPC_GATEWAY_BIN}"
f_print_done
}
f_install_protoc_gen_swagger() {
f_print_installing_with_padding protoc-gen-swagger
f_needs_install "${DESTDIR}/${PREFIX}/bin/protoc-gen-swagger" || return 0
if ! which npm &>/dev/null ; then
echo -e "\tNPM is not installed. Skipping."
return 0
fi
pushd "${TEMPDIR}" >/dev/null
go get github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
npm install -g swagger-combine
popd >/dev/null
f_print_done
}
f_install_clang_format() {
f_print_installing_with_padding clang-format
if which clang-format &>/dev/null ; then
echo -e "\talready installed. Skipping."
return 0
fi
case "${UNAME_S}" in
Linux)
if [ -e /etc/debian_version ]; then
echo -e "\tRun: sudo apt-get install clang-format" >&2
elif [ -e /etc/fedora-release ]; then
echo -e "\tRun: sudo dnf install clang" >&2
else
echo -e "\tRun (as root): subscription-manager repos --enable rhel-7-server-devtools-rpms ; yum install llvm-toolset-7" >&2
fi
;;
Darwin)
echo "\tRun: brew install clang-format" >&2
;;
*)
echo "\tunknown operating system. Skipping." >&2
esac
}
f_ensure_tools
f_ensure_dirs
f_install_protoc
f_install_buf
f_install_protoc_gen_gocosmos
f_install_protoc_gen_grpc_gateway
f_install_protoc_gen_swagger
f_install_clang_format

View File

@ -4,22 +4,26 @@ set -eo pipefail
protoc_gen_gocosmos() { protoc_gen_gocosmos() {
if ! grep "github.com/gogo/protobuf => github.com/regen-network/protobuf" go.mod &>/dev/null ; then if ! grep "github.com/gogo/protobuf => github.com/regen-network/protobuf" go.mod &>/dev/null ; then
echo -e "\tPlease run this command from somewhere inside the ethermint folder." echo -e "\tPlease run this command from somewhere inside the sommelier folder."
return 1 return 1
fi fi
go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos 2>/dev/null go get github.com/regen-network/cosmos-proto/protoc-gen-gocosmos 2>/dev/null
} }
protoc_gen_doc() {
go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc 2>/dev/null
}
protoc_gen_gocosmos protoc_gen_gocosmos
protoc_gen_doc
proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq)
for dir in $proto_dirs; do for dir in $proto_dirs; do
buf protoc \ buf protoc \
-I "proto" \ -I "proto" \
-I "third_party/proto" \ -I "third_party/proto" \
--gocosmos_out=plugins=interfacetype+grpc,\ --gocosmos_out=plugins=interfacetype+grpc:. \
Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \
$(find "${dir}" -maxdepth 1 -name '*.proto') $(find "${dir}" -maxdepth 1 -name '*.proto')
# command to generate gRPC gateway (*.pb.gw.go in respective modules) files # command to generate gRPC gateway (*.pb.gw.go in respective modules) files
@ -31,9 +35,14 @@ Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \
done done
# generate codec/testdata proto code # command to generate docs using protoc-gen-doc
buf protoc -I "proto" -I "third_party/proto" -I "testutil/testdata" --gocosmos_out=plugins=interfacetype+grpc,\ buf protoc \
Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. ./testutil/testdata/*.proto -I "proto" \
-I "third_party/proto" \
--doc_out=./docs/core \
--doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \
$(find "$(pwd)/proto" -maxdepth 5 -name '*.proto')
go mod tidy
# move proto files to the right places # move proto files to the right places
cp -r github.com/cosmos/ethermint/* ./ cp -r github.com/cosmos/ethermint/* ./

View File

@ -3,13 +3,18 @@
export GOPATH=~/go export GOPATH=~/go
export PATH=$PATH:$GOPATH/bin export PATH=$PATH:$GOPATH/bin
go build -o ./build/ethermintd ./cmd/ethermintd go build -o ./build/ethermintd ./cmd/ethermintd
go build -o ./build/ethermintcli ./cmd/ethermintcli
mkdir $GOPATH/bin mkdir $GOPATH/bin
cp ./build/ethermintd $GOPATH/bin cp ./build/ethermintd $GOPATH/bin
cp ./build/ethermintcli $GOPATH/bin
localKeyAddr=0x7cb61d4117ae31a12e393a1cfa3bac666481d02e
user1Addr=0xc6fe5d33615a1c52c08018c47e8bc53646a0e101
user2Addr=0x963ebdf2e1f8db8707d05fc75bfeffba1b5bac17
CHAINID="ethermint-1337" CHAINID="ethermint-1337"
# build ethermint binary
make install
cd tests-solidity cd tests-solidity
if command -v yarn &> /dev/null; then if command -v yarn &> /dev/null; then
@ -22,11 +27,22 @@ else
fi fi
chmod +x ./init-test-node.sh chmod +x ./init-test-node.sh
./init-test-node.sh > ethermintd.log & nohup ./init-test-node.sh > ethermintd.log 2>&1 &
sleep 5
ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id $CHAINID --trace --wsport 8546 --rpc-api="web3,eth,net,personal" > ethermintcli.log &
# give ethermintd node enough time to launch
echo "sleeping ..."
sleep 10
# show existing accounts
echo "account list: "
curl -X POST --data '{"jsonrpc":"2.0","method":"personal_listAccounts","params":[],"id":1}' -H "Content-Type: application/json" http://localhost:8545
# unlock localKey address
curl -X POST --data '{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["'$localKeyAddr'", ""],"id":1}' -H "Content-Type: application/json" http://localhost:8545
# tests start
cd suites/initializable cd suites/initializable
yarn contract-migrate
yarn test-ethermint yarn test-ethermint
ok=$? ok=$?
@ -35,7 +51,6 @@ if (( $? != 0 )); then
echo "initializable test failed: exit code $?" echo "initializable test failed: exit code $?"
fi fi
killall ethermintcli
killall ethermintd killall ethermintd
echo "Script exited with code $ok" echo "Script exited with code $ok"
@ -43,10 +58,7 @@ exit $ok
# initializable-buidler fails on CI, re-add later # initializable-buidler fails on CI, re-add later
./../../init-test-node.sh > ethermintd.log & ./../../init-test-node.sh > ethermintd.log
sleep 5
ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id $CHAINID --trace --wsport 8546 --rpc-api="web3,eth,net,personal" > ethermintcli.log &
cd ../initializable-buidler cd ../initializable-buidler
yarn test-ethermint yarn test-ethermint
@ -56,7 +68,6 @@ if (( $? != 0 )); then
echo "initializable-buidler test failed: exit code $?" echo "initializable-buidler test failed: exit code $?"
fi fi
killall ethermintcli
killall ethermintd killall ethermintd
echo "Script exited with code $ok" echo "Script exited with code $ok"

View File

@ -1,5 +1,176 @@
#!/bin/sh #!/bin/bash
ethermintd --home /ethermint/node$ID/ethermintd/ start > ethermintd.log &
sleep 5 # "stable" mode tests assume data is static
ethermintcli rest-server --laddr "tcp://localhost:8545" --chain-id "ethermint-7305661614933169792" --trace --rpc-api="web3,eth,net,personal" > ethermintcli.log & # "live" mode tests assume data dynamic
tail -f /dev/null
SCRIPT=$(basename ${BASH_SOURCE[0]})
TEST=""
QTD=1
SLEEP_TIMEOUT=5
TEST_QTD=1
#PORT AND RPC_PORT 3 initial digits, to be concat with a suffix later when node is initialized
RPC_PORT="8545"
IP_ADDR="0.0.0.0"
MODE="rpc"
KEY="mykey"
CHAINID="ethermint-2"
MONIKER="mymoniker"
## default port prefixes for ethermintd
NODE_P2P_PORT="2660"
NODE_PORT="2663"
NODE_RPC_PORT="2666"
usage() {
echo "Usage: $SCRIPT"
echo "Optional command line arguments"
echo "-t <string> -- Test to run. eg: rpc"
echo "-q <number> -- Quantity of nodes to run. eg: 3"
echo "-z <number> -- Quantity of nodes to run tests against eg: 3"
echo "-s <number> -- Sleep between operations in secs. eg: 5"
exit 1
}
while getopts "h?t:q:z:s:" args; do
case $args in
h|\?)
usage;
exit;;
t ) TEST=${OPTARG};;
q ) QTD=${OPTARG};;
z ) TEST_QTD=${OPTARG};;
s ) SLEEP_TIMEOUT=${OPTARG};;
esac
done
set -euxo pipefail
DATA_DIR=$(mktemp -d -t ethermint-datadir.XXXXX)
if [[ ! "$DATA_DIR" ]]; then
echo "Could not create $DATA_DIR"
exit 1
fi
DATA_CLI_DIR=$(mktemp -d -t ethermint-cli-datadir.XXXXX)
if [[ ! "$DATA_CLI_DIR" ]]; then
echo "Could not create $DATA_CLI_DIR"
exit 1
fi
# Compile ethermint
echo "compiling ethermint"
make build-ethermint
# PID array declaration
arr=()
# PID arraycli declaration
arrcli=()
init_func() {
echo "create and add new keys"
"$PWD"/build/ethermintd config keyring-backend test --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintd keys add $KEY"$i" --home "$DATA_CLI_DIR$i" --no-backup --chain-id $CHAINID --algo "eth_secp256k1"
echo "init Ethermint with moniker=$MONIKER and chain-id=$CHAINID"
"$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID --home "$DATA_DIR$i"
echo "init ethermintd with chain-id=$CHAINID and config it trust-node true"
"$PWD"/build/ethermintd config chain-id $CHAINID --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintd config output json --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintd config indent true --home "$DATA_CLI_DIR$i"
"$PWD"/build/ethermintd config trust-node true --home "$DATA_CLI_DIR$i"
echo "prepare genesis: Allocate genesis accounts"
"$PWD"/build/ethermintd add-genesis-account \
"$("$PWD"/build/ethermintd keys show "$KEY$i" -a --home "$DATA_CLI_DIR$i" )" 1000000000000000000aphoton,1000000000000000000stake \
--home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i"
echo "prepare genesis: Sign genesis transaction"
"$PWD"/build/ethermintd gentx --name $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --home-client "$DATA_CLI_DIR$i"
echo "prepare genesis: Collect genesis tx"
"$PWD"/build/ethermintd collect-gentxs --home "$DATA_DIR$i"
echo "prepare genesis: Run validate-genesis to ensure everything worked and that the genesis file is setup correctly"
"$PWD"/build/ethermintd validate-genesis --home "$DATA_DIR$i"
}
start_func() {
echo "starting ethermint node $i in background ..."
"$PWD"/build/ethermintd start --pruning=nothing --rpc.unsafe \
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
--home "$DATA_DIR$i" \
>"$DATA_DIR"/node"$i".log 2>&1 & disown
ETHERMINT_PID=$!
echo "started ethermint node, pid=$ETHERMINT_PID"
# add PID to array
arr+=("$ETHERMINT_PID")
}
start_cli_func() {
echo "starting ethermint node $i in background ..."
"$PWD"/build/ethermintd rest-server --unlock-key $KEY"$i" --chain-id $CHAINID --trace \
--laddr "tcp://localhost:$RPC_PORT$i" --node tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
--home "$DATA_CLI_DIR$i" --read-timeout 30 --write-timeout 30 \
--rpc-api "web3, eth, personal, net" \
>"$DATA_CLI_DIR"/cli"$i".log 2>&1 & disown
ETHERMINT_CLI_PID=$!
echo "started ethermintd node, pid=$ETHERMINT_CLI_PID"
# add PID to array
arrcli+=("$ETHERMINT_CLI_PID")
}
# Run node with static blockchain database
# For loop N times
for i in $(seq 1 "$QTD"); do
init_func "$i"
start_func "$i"
sleep 1
start_cli_func "$i"
echo "sleeping $SLEEP_TIMEOUT seconds for startup"
sleep "$SLEEP_TIMEOUT"
echo "done sleeping"
done
echo "sleeping $SLEEP_TIMEOUT seconds before running tests ... "
sleep "$SLEEP_TIMEOUT"
echo "done sleeping"
set +e
if [[ -z $TEST || $TEST == "rpc" ]]; then
for i in $(seq 1 "$TEST_QTD"); do
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
echo "going to test ethermint node $HOST_RPC ..."
MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short
RPC_FAIL=$?
done
fi
stop_func() {
ETHERMINT_PID=$i
echo "shutting down node, pid=$ETHERMINT_PID ..."
# Shutdown ethermint node
kill -9 "$ETHERMINT_PID"
wait "$ETHERMINT_PID"
}
for i in "${arrcli[@]}"; do
stop_func "$i"
done
for i in "${arr[@]}"; do
stop_func "$i"
done
if [[ (-z $TEST || $TEST == "rpc") && $RPC_FAIL -ne 0 ]]; then
exit $RPC_FAIL
else
exit 0
fi

70
server/config/config.go Normal file
View File

@ -0,0 +1,70 @@
package config
import (
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/server/config"
)
const (
// DefaultJSONRPCAddress is the default address the JSON-RPC server binds to.
DefaultJSONRPCAddress = "tcp://0.0.0.0:8545"
// DefaultEthereumWebsocketAddress is the default address the Ethereum websocket server binds to.
DefaultEthereumWebsocketAddress = "tcp://0.0.0.0:8546"
)
// Config defines the server's top level configuration
type Config struct {
*config.Config
JSONRPC JSONRPCConfig `mapstructure:"json-rpc"`
EthereumWebsocket WebsocketConfig `mapstructure:"ethereum-websocket"`
}
// JSONRPCConfig defines the Ethereum API listener configuration.
type JSONRPCConfig struct {
// Enable defines if the JSON-RPC server should be enabled.
Enable bool `mapstructure:"enable"`
// Address defines the JSON-RPC server address to listen on
Address string `mapstructure:"address"`
}
// WebsocketConfig defines the Ethereum API listener configuration.
type WebsocketConfig struct {
// Enable defines if the Ethereum websocker server should be enabled.
Enable bool `mapstructure:"enable"`
// Address defines the Websocket server address to listen on
Address string `mapstructure:"address"`
}
// DefaultConfig returns server's default configuration.
func DefaultConfig() *Config {
return &Config{
Config: config.DefaultConfig(),
JSONRPC: JSONRPCConfig{
Enable: true,
Address: DefaultJSONRPCAddress,
},
EthereumWebsocket: WebsocketConfig{
Enable: true,
Address: DefaultEthereumWebsocketAddress,
},
}
}
// GetConfig returns a fully parsed Config object.
func GetConfig(v *viper.Viper) Config {
sdkConfig := config.GetConfig(v)
return Config{
Config: &sdkConfig,
JSONRPC: JSONRPCConfig{
Enable: v.GetBool("json-rpc.enable"),
Address: v.GetString("json-rpc.address"),
},
EthereumWebsocket: WebsocketConfig{
Enable: v.GetBool("ethereum-websocket.enable"),
Address: v.GetString("ethereum-websocket.address"),
},
}
}

225
server/config/toml.go Normal file
View File

@ -0,0 +1,225 @@
package config
import (
"bytes"
"text/template"
"github.com/spf13/viper"
tmos "github.com/tendermint/tendermint/libs/os"
)
const defaultConfigTemplate = `# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
###############################################################################
### Base Configuration ###
###############################################################################
# The minimum gas prices a validator is willing to accept for processing a
# transaction. A transaction's fees must meet the minimum of any denomination
# specified in this config (e.g. 0.25token1;0.0001token2).
minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}"
# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
# everything: all saved states will be deleted, storing only the current state; pruning at 10 block intervals
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
pruning = "{{ .BaseConfig.Pruning }}"
# These are applied if and only if the pruning strategy is custom.
pruning-keep-recent = "{{ .BaseConfig.PruningKeepRecent }}"
pruning-keep-every = "{{ .BaseConfig.PruningKeepEvery }}"
pruning-interval = "{{ .BaseConfig.PruningInterval }}"
# HaltHeight contains a non-zero block height at which a node will gracefully
# halt and shutdown that can be used to assist upgrades and testing.
#
# Note: Commitment of state will be attempted on the corresponding block.
halt-height = {{ .BaseConfig.HaltHeight }}
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
# a node will gracefully halt and shutdown that can be used to assist upgrades
# and testing.
#
# Note: Commitment of state will be attempted on the corresponding block.
halt-time = {{ .BaseConfig.HaltTime }}
# MinRetainBlocks defines the minimum block height offset from the current
# block being committed, such that all blocks past this offset are pruned
# from Tendermint. It is used as part of the process of determining the
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
# that no blocks should be pruned.
#
# This configuration value is only responsible for pruning Tendermint blocks.
# It has no bearing on application state pruning which is determined by the
# "pruning-*" configurations.
#
# Note: Tendermint block pruning is dependant on this parameter in conunction
# with the unbonding (safety threshold) period, state pruning and state sync
# snapshot parameters to determine the correct minimum value of
# ResponseCommit.RetainHeight.
min-retain-blocks = {{ .BaseConfig.MinRetainBlocks }}
# InterBlockCache enables inter-block caching.
inter-block-cache = {{ .BaseConfig.InterBlockCache }}
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
# which informs Tendermint what to index. If empty, all events will be indexed.
#
# Example:
# ["message.sender", "message.recipient"]
index-events = {{ .BaseConfig.IndexEvents }}
###############################################################################
### Telemetry Configuration ###
###############################################################################
[telemetry]
# Prefixed with keys to separate services.
service-name = "{{ .Telemetry.ServiceName }}"
# Enabled enables the application telemetry functionality. When enabled,
# an in-memory sink is also enabled by default. Operators may also enabled
# other sinks such as Prometheus.
enabled = {{ .Telemetry.Enabled }}
# Enable prefixing gauge values with hostname.
enable-hostname = {{ .Telemetry.EnableHostname }}
# Enable adding hostname to labels.
enable-hostname-label = {{ .Telemetry.EnableHostnameLabel }}
# Enable adding service to labels.
enable-service-label = {{ .Telemetry.EnableServiceLabel }}
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
prometheus-retention-time = {{ .Telemetry.PrometheusRetentionTime }}
# GlobalLabels defines a global set of name/value label tuples applied to all
# metrics emitted using the wrapper functions defined in telemetry package.
#
# Example:
# [["chain_id", "cosmoshub-1"]]
global-labels = [{{ range $k, $v := .Telemetry.GlobalLabels }}
["{{index $v 0 }}", "{{ index $v 1}}"],{{ end }}
]
###############################################################################
### API Configuration ###
###############################################################################
[api]
# Enable defines if the API server should be enabled.
enable = {{ .API.Enable }}
# Swagger defines if swagger documentation should automatically be registered.
swagger = {{ .API.Swagger }}
# Address defines the API server to listen on.
address = "{{ .API.Address }}"
# MaxOpenConnections defines the number of maximum open connections.
max-open-connections = {{ .API.MaxOpenConnections }}
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
rpc-read-timeout = {{ .API.RPCReadTimeout }}
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
rpc-write-timeout = {{ .API.RPCWriteTimeout }}
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
rpc-max-body-bytes = {{ .API.RPCMaxBodyBytes }}
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
enabled-unsafe-cors = {{ .API.EnableUnsafeCORS }}
###############################################################################
### gRPC Configuration ###
###############################################################################
[grpc]
# Enable defines if the gRPC server should be enabled.
enable = {{ .GRPC.Enable }}
# Address defines the gRPC server address to bind to.
address = "{{ .GRPC.Address }}"
###############################################################################
### State Sync Configuration ###
###############################################################################
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
# blocks, instead downloading and applying a snapshot of the application state at a given height.
[state-sync]
# snapshot-interval specifies the block interval at which local state sync snapshots are
# taken (0 to disable). Must be a multiple of pruning-keep-every.
snapshot-interval = {{ .StateSync.SnapshotInterval }}
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
snapshot-keep-recent = {{ .StateSync.SnapshotKeepRecent }}
###############################################################################
### JSON-RPC Configuration ###
###############################################################################
# JSON-RPC enables a JSON-RPC server that allows Ethereum clients to connect to an Ethermint node.
# For the full list of supported endpoints see https://docs.ethermint.zone/basics/json_rpc.html
[json-rpc]
# Enable defines if the JSON-RPC server should be enabled.
enable = {{ .JSONRPC.Enable }}
# Address defines the JSON-RPC server address to bind to.
address = "{{ .JSONRPC.Address }}"
###############################################################################
### Ethereum Websocket Configuration ###
###############################################################################
# Ethereum Websocket enables a PubSub server that allows Ethereum clients to subscribe to specific endpoints.
[ethereum-websocket]
# Enable defines if the Ethereum Websocket server should be enabled.
enable = {{ .EthereumWebsocket.Enable }}
# Address defines the Ethereum Websocket server address to bind to.
address = "{{ .EthereumWebsocket.Address }}"
`
var configTemplate *template.Template
func init() {
var err error
tmpl := template.New("appConfigFileTemplate")
if configTemplate, err = tmpl.Parse(defaultConfigTemplate); err != nil {
panic(err)
}
}
// ParseConfig retrieves the default environment configuration for the
// application.
func ParseConfig(v *viper.Viper) (*Config, error) {
conf := DefaultConfig()
err := v.Unmarshal(conf)
return conf, err
}
// WriteConfigFile renders config using the template and writes it to
// configFilePath.
func WriteConfigFile(configFilePath string, config *Config) {
var buffer bytes.Buffer
if err := configTemplate.Execute(&buffer, config); err != nil {
panic(err)
}
tmos.MustWriteFile(configFilePath, buffer.Bytes(), 0644)
}

29
server/flags.go Normal file
View File

@ -0,0 +1,29 @@
package server
// Tendermint full-node start flags
const (
flagWithTendermint = "with-tendermint"
flagAddress = "address"
flagTransport = "transport"
flagTraceStore = "trace-store"
flagCPUProfile = "cpu-profile"
)
// GRPC-related flags.
const (
flagGRPCEnable = "grpc.enable"
flagGRPCAddress = "grpc.address"
)
// RPCAPI-related flags.
const (
flagRPCAPI = "rpc-api"
)
// Ethereum-related flags.
const (
flagJSONRPCEnable = "json-rpc.enable"
flagJSONRPCAddress = "json-rpc.address"
flagEthereumWebsocketEnable = "ethereum-websocket.enable"
flagEthereumWebsocketAddress = "ethereum-websocket.address"
)

View File

@ -0,0 +1,90 @@
package jsonrpc
import (
"context"
"fmt"
"net"
"net/http"
"net/url"
"time"
"github.com/cosmos/ethermint/server/config"
"github.com/ethereum/go-ethereum/rpc"
)
type Service struct {
rpcServer *rpc.Server
apis []rpc.API
http *http.Server
}
// NewService creates a new JSON-RPC server instance over http with public Ethereum APIs
func NewService(apis []rpc.API) *Service {
s := &Service{
rpcServer: rpc.NewServer(),
apis: apis,
http: &http.Server{},
}
s.http.Handler = s.rpcServer
return s
}
// Name returns the JSON-RPC service name
func (Service) Name() string {
return "JSON-RPC"
}
// RegisterRoutes registers the JSON-RPC server to the application. It fails if any of the
// API names fail to register.
func (s *Service) RegisterRoutes() error {
for _, api := range s.apis {
if err := s.rpcServer.RegisterName(api.Namespace, api.Service); err != nil {
return err
}
}
return nil
}
// Start starts the JSON-RPC server on the address defined on the configuration.
func (s *Service) Start(cfg config.Config) error {
u, err := url.Parse(cfg.JSONRPC.Address)
if err != nil {
return err
}
listener, err := net.Listen("tcp", u.Host)
if err != nil {
return err
}
errCh := make(chan error)
go func() {
err = s.http.Serve(listener)
if err != nil {
errCh <- fmt.Errorf("failed to serve: %w", err)
}
}()
select {
case err := <-errCh:
return err
case <-time.After(5 * time.Second): // assume server started successfully
return nil
}
}
// Stop stops the JSON-RPC service by no longer reading new requests, waits for
// stopPendingRequestTimeout to allow pending requests to finish, then closes all codecs which will
// cancel pending requests and subscriptions.
func (s *Service) Stop() error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := s.http.Shutdown(ctx)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,57 @@
package websocket
import (
"net/http"
"net/url"
"time"
"github.com/cosmos/cosmos-sdk/client"
"github.com/gorilla/mux"
"github.com/cosmos/ethermint/rpc/websockets"
"github.com/cosmos/ethermint/server/config"
)
type Service struct {
websocketServer *websockets.Server
}
// NewService creates a new gRPC server instance with a defined listener address.
func NewService(clientCtx client.Context) *Service {
return &Service{
websocketServer: websockets.NewServer(clientCtx),
}
}
// Name returns the JSON-RPC service name
func (Service) Name() string {
return "Ethereum Websocket"
}
// Start runs the websocket server
func (s Service) Start(cfg config.Config) error {
s.websocketServer.Address = cfg.JSONRPC.Address
u, err := url.Parse(cfg.EthereumWebsocket.Address)
if err != nil {
return err
}
ws := mux.NewRouter()
ws.Handle("/", s.websocketServer)
errCh := make(chan error)
go func() {
err := http.ListenAndServe(":"+u.Port(), ws)
if err != nil {
errCh <- err
}
}()
select {
case err := <-errCh:
return err
case <-time.After(5 * time.Second): // assume server started successfully
return nil
}
}

331
server/start.go Normal file
View File

@ -0,0 +1,331 @@
package server
// DONTCOVER
import (
"fmt"
"os"
"runtime/pprof"
"strings"
"time"
"github.com/tendermint/tendermint/rpc/client/local"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdkserver "github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
sdkconfig "github.com/cosmos/cosmos-sdk/server/config"
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/tendermint/tendermint/abci/server"
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
tmos "github.com/tendermint/tendermint/libs/os"
"github.com/tendermint/tendermint/node"
"github.com/tendermint/tendermint/p2p"
pvm "github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
"github.com/cosmos/ethermint/rpc"
"github.com/cosmos/ethermint/server/config"
"github.com/cosmos/ethermint/server/services/jsonrpc"
"github.com/cosmos/ethermint/server/services/websocket"
)
// StartCmd runs the service passed in, either stand-alone or in-process with
// Tendermint.
func StartCmd(appCreator servertypes.AppCreator, defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "start",
Short: "Run the full node",
Long: `Run the full node application with Tendermint in or out of process. By
default, the application will run with Tendermint in process.
Pruning options can be provided via the '--pruning' flag or alternatively with '--pruning-keep-recent',
'pruning-keep-every', and 'pruning-interval' together.
For '--pruning' the options are as follows:
default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
everything: all saved states will be deleted, storing only the current state; pruning at 10 block intervals
custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
Node halting configurations exist in the form of two flags: '--halt-height' and '--halt-time'. During
the ABCI Commit phase, the node will check if the current block height is greater than or equal to
the halt-height or if the current block time is greater than or equal to the halt-time. If so, the
node will attempt to gracefully shutdown and the block will not be committed. In addition, the node
will not be able to commit subsequent blocks.
For profiling and benchmarking purposes, CPU profiling can be enabled via the '--cpu-profile' flag
which accepts a path for the resulting pprof file.
`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
serverCtx := sdkserver.GetServerContextFromCmd(cmd)
// Bind flags to the Context's Viper so the app construction can set
// options accordingly.
if err := serverCtx.Viper.BindPFlags(cmd.Flags()); err != nil {
return err
}
_, err := sdkserver.GetPruningOptionsFromFlags(serverCtx.Viper)
return err
},
RunE: func(cmd *cobra.Command, _ []string) error {
serverCtx := sdkserver.GetServerContextFromCmd(cmd)
clientCtx := client.GetClientContextFromCmd(cmd)
withTM, _ := cmd.Flags().GetBool(flagWithTendermint)
if !withTM {
serverCtx.Logger.Info("starting ABCI without Tendermint")
return startStandAlone(serverCtx, appCreator)
}
serverCtx.Logger.Info("starting ABCI with Tendermint")
// amino is needed here for backwards compatibility of REST routes
err := startInProcess(serverCtx, clientCtx, appCreator)
return err
},
}
cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
cmd.Flags().Bool(flagWithTendermint, true, "Run abci app embedded in-process with tendermint")
cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address")
cmd.Flags().String(flagTransport, "socket", "Transport protocol: socket, grpc")
cmd.Flags().String(flagTraceStore, "", "Enable KVStore tracing to an output file")
cmd.Flags().String(sdkserver.FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; Any fee in a tx must meet this minimum (e.g. 0.01photino;0.0001stake)")
cmd.Flags().IntSlice(sdkserver.FlagUnsafeSkipUpgrades, []int{}, "Skip a set of upgrade heights to continue the old binary")
cmd.Flags().Uint64(sdkserver.FlagHaltHeight, 0, "Block height at which to gracefully halt the chain and shutdown the node")
cmd.Flags().Uint64(sdkserver.FlagHaltTime, 0, "Minimum block time (in Unix seconds) at which to gracefully halt the chain and shutdown the node")
cmd.Flags().Bool(sdkserver.FlagInterBlockCache, true, "Enable inter-block caching")
cmd.Flags().String(flagCPUProfile, "", "Enable CPU profiling and write to the provided file")
cmd.Flags().Bool(sdkserver.FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
cmd.Flags().String(sdkserver.FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
cmd.Flags().Uint64(sdkserver.FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
cmd.Flags().Uint64(sdkserver.FlagPruningKeepEvery, 0, "Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom')")
cmd.Flags().Uint64(sdkserver.FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
cmd.Flags().Uint(sdkserver.FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
cmd.Flags().Uint64(sdkserver.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
cmd.Flags().Bool(flagGRPCEnable, true, "Define if the gRPC server should be enabled")
cmd.Flags().String(flagGRPCAddress, sdkconfig.DefaultGRPCAddress, "the gRPC server address to listen on")
cmd.Flags().Bool(flagJSONRPCEnable, true, "Define if the Ethereum JSON-RPC server should be enabled")
cmd.Flags().String(flagJSONRPCAddress, config.DefaultJSONRPCAddress, "the JSON-RPC server address to listen on")
cmd.Flags().Bool(flagEthereumWebsocketEnable, true, "Define if the Ethereum Websocket server should be enabled")
cmd.Flags().String(flagEthereumWebsocketAddress, config.DefaultEthereumWebsocketAddress, "the Ethereum websocket server address to listen on")
cmd.Flags().Uint64(sdkserver.FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval")
cmd.Flags().Uint32(sdkserver.FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
cmd.Flags().String(flagRPCAPI, "", fmt.Sprintf("Comma separated list of RPC API modules to enable: %s, %s, %s, %s", rpc.Web3Namespace, rpc.EthNamespace, rpc.PersonalNamespace, rpc.NetNamespace))
// add support for all Tendermint-specific command line options
tcmd.AddNodeFlags(cmd)
return cmd
}
func startStandAlone(ctx *sdkserver.Context, appCreator servertypes.AppCreator) error {
addr := ctx.Viper.GetString(flagAddress)
transport := ctx.Viper.GetString(flagTransport)
home := ctx.Viper.GetString(flags.FlagHome)
db, err := openDB(home)
if err != nil {
return err
}
traceWriterFile := ctx.Viper.GetString(flagTraceStore)
traceWriter, err := openTraceWriter(traceWriterFile)
if err != nil {
return err
}
app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)
svr, err := server.NewServer(addr, transport, app)
if err != nil {
return fmt.Errorf("error creating listener: %v", err)
}
svr.SetLogger(ctx.Logger.With("module", "abci-server"))
err = svr.Start()
if err != nil {
tmos.Exit(err.Error())
}
sdkserver.TrapSignal(func() {
if err = svr.Stop(); err != nil {
tmos.Exit(err.Error())
}
})
// run forever (the node will not be returned)
select {}
}
// legacyAminoCdc is used for the legacy REST API
func startInProcess(ctx *sdkserver.Context, clientCtx client.Context, appCreator servertypes.AppCreator) error {
cfg := ctx.Config
home := cfg.RootDir
var cpuProfileCleanup func()
if cpuProfile := ctx.Viper.GetString(flagCPUProfile); cpuProfile != "" {
f, err := os.Create(cpuProfile)
if err != nil {
return err
}
ctx.Logger.Info("starting CPU profiler", "profile", cpuProfile)
if err := pprof.StartCPUProfile(f); err != nil {
return err
}
cpuProfileCleanup = func() {
ctx.Logger.Info("stopping CPU profiler", "profile", cpuProfile)
pprof.StopCPUProfile()
f.Close()
}
}
traceWriterFile := ctx.Viper.GetString(flagTraceStore)
db, err := openDB(home)
if err != nil {
return err
}
traceWriter, err := openTraceWriter(traceWriterFile)
if err != nil {
return err
}
app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)
nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile())
if err != nil {
return err
}
genDocProvider := node.DefaultGenesisDocProviderFunc(cfg)
tmNode, err := node.NewNode(
cfg,
pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()),
nodeKey,
proxy.NewLocalClientCreator(app),
genDocProvider,
node.DefaultDBProvider,
node.DefaultMetricsProvider(cfg.Instrumentation),
ctx.Logger.With("module", "node"),
)
if err != nil {
return err
}
ctx.Logger.Debug("Initialization: tmNode created")
if err := tmNode.Start(); err != nil {
return err
}
ctx.Logger.Debug("Initialization: tmNode started")
// Add the tx service to the gRPC router.
app.RegisterTxService(clientCtx)
var apiSrv *api.Server
config := config.GetConfig(ctx.Viper)
genDoc, err := genDocProvider()
if err != nil {
return err
}
clientCtx = clientCtx.
WithHomeDir(home).
WithChainID(genDoc.ChainID).
WithClient(local.New(tmNode))
if config.API.Enable {
apiSrv = api.New(clientCtx, ctx.Logger.With("module", "api-server"))
app.RegisterAPIRoutes(apiSrv, config.API)
errCh := make(chan error)
go func() {
if err := apiSrv.Start(*config.Config); err != nil {
errCh <- err
}
}()
select {
case err := <-errCh:
return err
case <-time.After(5 * time.Second): // assume server started successfully
}
}
var grpcSrv *grpc.Server
if config.GRPC.Enable {
grpcSrv, err = servergrpc.StartGRPCServer(clientCtx, app, config.GRPC.Address)
if err != nil {
return err
}
}
rpcapi := ctx.Viper.GetString(flagRPCAPI)
rpcapi = strings.ReplaceAll(rpcapi, " ", "")
rpcapiArr := strings.Split(rpcapi, ",")
jsonRPCSrv := jsonrpc.NewService(rpc.GetAPIs(clientCtx, rpcapiArr))
if config.JSONRPC.Enable {
if err := jsonRPCSrv.RegisterRoutes(); err != nil {
return err
}
err = jsonRPCSrv.Start(config)
if err != nil {
return err
}
}
if config.EthereumWebsocket.Enable {
websocketSrv := websocket.NewService(clientCtx)
err = websocketSrv.Start(config)
if err != nil {
return err
}
}
defer func() {
if tmNode.IsRunning() {
_ = tmNode.Stop()
}
if cpuProfileCleanup != nil {
cpuProfileCleanup()
}
if apiSrv != nil {
_ = apiSrv.Close()
}
if grpcSrv != nil {
grpcSrv.Stop()
}
_ = jsonRPCSrv.Stop()
ctx.Logger.Info("exiting...")
}()
// Wait for SIGINT or SIGTERM signal
return sdkserver.WaitForQuitSignals()
}

199
server/util.go Normal file
View File

@ -0,0 +1,199 @@
package server
import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
tmcfg "github.com/tendermint/tendermint/config"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/client/flags"
sdkserver "github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/ethermint/server/config"
)
// InterceptConfigsPreRunHandler performs a pre-run function for the root daemon
// application command. It will create a Viper literal and a default server
// Context. The server Tendermint configuration will either be read and parsed
// or created and saved to disk, where the server Context is updated to reflect
// the Tendermint configuration. The Viper literal is used to read and parse
// the application configuration. Command handlers can fetch the server Context
// to get the Tendermint configuration or to get access to Viper.
func InterceptConfigsPreRunHandler(cmd *cobra.Command) error {
serverCtx := sdkserver.NewDefaultContext()
// Get the executable name and configure the viper instance so that environmental
// variables are checked based off that name. The underscore character is used
// as a separator
executableName, err := os.Executable()
if err != nil {
return err
}
basename := path.Base(executableName)
// Configure the viper instance
if err := serverCtx.Viper.BindPFlags(cmd.Flags()); err != nil {
return err
}
if err := serverCtx.Viper.BindPFlags(cmd.PersistentFlags()); err != nil {
return err
}
serverCtx.Viper.SetEnvPrefix(basename)
serverCtx.Viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
serverCtx.Viper.AutomaticEnv()
// intercept configuration files, using both Viper instances separately
config, err := interceptConfigs(serverCtx.Viper)
if err != nil {
return err
}
// return value is a tendermint configuration object
serverCtx.Config = config
var logWriter io.Writer
if strings.ToLower(serverCtx.Viper.GetString(flags.FlagLogFormat)) == tmcfg.LogFormatPlain {
logWriter = zerolog.ConsoleWriter{Out: os.Stderr}
} else {
logWriter = os.Stderr
}
logLvlStr := serverCtx.Viper.GetString(flags.FlagLogLevel)
logLvl, err := zerolog.ParseLevel(logLvlStr)
if err != nil {
return fmt.Errorf("failed to parse log level (%s): %w", logLvlStr, err)
}
serverCtx.Logger = sdkserver.ZeroLogWrapper{
Logger: zerolog.New(logWriter).Level(logLvl).With().Timestamp().Logger(),
}
return sdkserver.SetCmdServerContext(cmd, serverCtx)
}
// interceptConfigs parses and updates a Tendermint configuration file or
// creates a new one and saves it. It also parses and saves the application
// configuration file. The Tendermint configuration file is parsed given a root
// Viper object, whereas the application is parsed with the private package-aware
// viperCfg object.
func interceptConfigs(rootViper *viper.Viper) (*tmcfg.Config, error) {
rootDir := rootViper.GetString(flags.FlagHome)
configPath := filepath.Join(rootDir, "config")
configFile := filepath.Join(configPath, "config.toml")
conf := tmcfg.DefaultConfig()
switch _, err := os.Stat(configFile); {
case os.IsNotExist(err):
tmcfg.EnsureRoot(rootDir)
if err = conf.ValidateBasic(); err != nil {
return nil, fmt.Errorf("error in config file: %v", err)
}
conf.RPC.PprofListenAddress = "localhost:6060"
conf.P2P.RecvRate = 5120000
conf.P2P.SendRate = 5120000
conf.Consensus.TimeoutCommit = 5 * time.Second
tmcfg.WriteConfigFile(configFile, conf)
case err != nil:
return nil, err
default:
rootViper.SetConfigType("toml")
rootViper.SetConfigName("config")
rootViper.AddConfigPath(configPath)
if err := rootViper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("failed to read in app.toml: %w", err)
}
}
// Read into the configuration whatever data the viper instance has for it
// This may come from the configuration file above but also any of the other sources
// viper uses
if err := rootViper.Unmarshal(conf); err != nil {
return nil, err
}
conf.SetRoot(rootDir)
appConfigFilePath := filepath.Join(configPath, "app.toml")
if _, err := os.Stat(appConfigFilePath); os.IsNotExist(err) {
appConf, err := config.ParseConfig(rootViper)
if err != nil {
return nil, fmt.Errorf("failed to parse app.toml: %w", err)
}
config.WriteConfigFile(appConfigFilePath, appConf)
}
rootViper.SetConfigType("toml")
rootViper.SetConfigName("app")
rootViper.AddConfigPath(configPath)
if err := rootViper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("failed to read in app.toml: %w", err)
}
return conf, nil
}
// AddCommands adds the server commands
func AddCommands(
rootCmd *cobra.Command, defaultNodeHome string,
appCreator servertypes.AppCreator, appExport servertypes.AppExporter, addStartFlags servertypes.ModuleInitFlags,
) {
tendermintCmd := &cobra.Command{
Use: "tendermint",
Short: "Tendermint subcommands",
}
tendermintCmd.AddCommand(
sdkserver.ShowNodeIDCmd(),
sdkserver.ShowValidatorCmd(),
sdkserver.ShowAddressCmd(),
sdkserver.VersionCmd(),
)
startCmd := StartCmd(appCreator, defaultNodeHome)
addStartFlags(startCmd)
rootCmd.AddCommand(
startCmd,
sdkserver.UnsafeResetAllCmd(),
flags.LineBreak,
tendermintCmd,
sdkserver.ExportCmd(appExport, defaultNodeHome),
flags.LineBreak,
version.NewVersionCommand(),
)
}
func openDB(rootDir string) (dbm.DB, error) {
dataDir := filepath.Join(rootDir, "data")
return sdk.NewLevelDB("application", dataDir)
}
func openTraceWriter(traceWriterFile string) (w io.Writer, err error) {
if traceWriterFile == "" {
return
}
return os.OpenFile(
traceWriterFile,
os.O_WRONLY|os.O_APPEND|os.O_CREATE,
0666,
)
}

View File

@ -10,7 +10,7 @@ Increasingly difficult tests are provided:
### Quick start ### Quick start
**Prerequisite**: in the repo's root, run `make install` to install the `ethermintd` and `ethermintcli` binaries. When done, come back to this directory. **Prerequisite**: in the repo's root, run `make install` to install the `ethermintd` and `ethermintd` binaries. When done, come back to this directory.
**Prerequisite**: install the individual solidity packages. They're set up as individual reops in a yarn monorepo workspace. Install them all via `yarn install`. **Prerequisite**: install the individual solidity packages. They're set up as individual reops in a yarn monorepo workspace. Install them all via `yarn install`.
@ -22,10 +22,10 @@ In the first, run `ethermintd`:
./init-test-node.sh ./init-test-node.sh
``` ```
In the second, run `ethermintcli` as mentioned in the script's output: In the second, run `ethermintd` as mentioned in the script's output:
```sh ```sh
ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id "ethermint-1337" --trace --wsport 8546 ethermintd rest-server --laddr "tcp://localhost:8545" --unlock-key localkey,user1,user2 --chain-id "ethermint-1337" --trace --wsport 8546
``` ```
You will now have three ethereum accounts unlocked in the test node: You will now have three ethereum accounts unlocked in the test node:
@ -36,7 +36,7 @@ You will now have three ethereum accounts unlocked in the test node:
From here, in your other available terminal, go into any of the tests and run `yarn test-ethermint`. You should see `ethermintd` accepting transactions and producing blocks. You should be able to query for any transaction via: From here, in your other available terminal, go into any of the tests and run `yarn test-ethermint`. You should see `ethermintd` accepting transactions and producing blocks. You should be able to query for any transaction via:
- `ethermintcli query tx <cosmos-sdk tx>` - `ethermintd query tx <cosmos-sdk tx>`
- `curl localhost:8545 -H "Content-Type:application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["<ethereum tx>"],"id":1}'` - `curl localhost:8545 -H "Content-Type:application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["<ethereum tx>"],"id":1}'`
And obviously more, via the Ethereum JSON-RPC API). And obviously more, via the Ethereum JSON-RPC API).
@ -56,7 +56,7 @@ The [`init-test-node.sh`](./init-test-node.sh) script sets up ethermint with the
Each with roughly 100 ETH available (1e18 photon). Each with roughly 100 ETH available (1e18 photon).
Running `ethermintcli list keys` should output: Running `ethermintd list keys` should output:
```json ```json
[ [

View File

@ -3,41 +3,35 @@
CHAINID="ethermint-1337" CHAINID="ethermint-1337"
MONIKER="localtestnet" MONIKER="localtestnet"
# localKey address 0x7cb61d4117ae31a12e393a1cfa3bac666481d02e
VAL_KEY="localkey" VAL_KEY="localkey"
VAL_MNEMONIC="gesture inject test cycle original hollow east ridge hen combine junk child bacon zero hope comfort vacuum milk pitch cage oppose unhappy lunar seat" VAL_MNEMONIC="gesture inject test cycle original hollow east ridge hen combine junk child bacon zero hope comfort vacuum milk pitch cage oppose unhappy lunar seat"
# user1 address 0xc6fe5d33615a1c52c08018c47e8bc53646a0e101
USER1_KEY="user1" USER1_KEY="user1"
USER1_MNEMONIC="copper push brief egg scan entry inform record adjust fossil boss egg comic alien upon aspect dry avoid interest fury window hint race symptom" USER1_MNEMONIC="copper push brief egg scan entry inform record adjust fossil boss egg comic alien upon aspect dry avoid interest fury window hint race symptom"
# user2 address 0x963ebdf2e1f8db8707d05fc75bfeffba1b5bac17
USER2_KEY="user2" USER2_KEY="user2"
USER2_MNEMONIC="maximum display century economy unlock van census kite error heart snow filter midnight usage egg venture cash kick motor survey drastic edge muffin visual" USER2_MNEMONIC="maximum display century economy unlock van census kite error heart snow filter midnight usage egg venture cash kick motor survey drastic edge muffin visual"
# remove existing daemon and client # remove existing daemon and client
rm -rf ~/.ethermint* rm -rf ~/.ethermint*
ethermintcli config keyring-backend test
# Set up config for CLI
ethermintcli config chain-id $CHAINID
ethermintcli config output json
ethermintcli config indent true
ethermintcli config trust-node true
# Import keys from mnemonics # Import keys from mnemonics
echo $VAL_MNEMONIC | ethermintcli keys add $VAL_KEY --recover echo $VAL_MNEMONIC | ethermintd keys add $VAL_KEY --recover --keyring-backend test --algo "eth_secp256k1"
echo $USER1_MNEMONIC | ethermintcli keys add $USER1_KEY --recover echo $USER1_MNEMONIC | ethermintd keys add $USER1_KEY --recover --keyring-backend test --algo "eth_secp256k1"
echo $USER2_MNEMONIC | ethermintcli keys add $USER2_KEY --recover echo $USER2_MNEMONIC | ethermintd keys add $USER2_KEY --recover --keyring-backend test --algo "eth_secp256k1"
# Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
ethermintd init $MONIKER --chain-id $CHAINID ethermintd init $MONIKER --chain-id $CHAINID
# Allocate genesis accounts (cosmos formatted addresses) # Allocate genesis accounts (cosmos formatted addresses)
ethermintd add-genesis-account $(ethermintcli keys show $VAL_KEY -a) 1000000000000000000000aphoton,10000000000000000stake ethermintd add-genesis-account "$(ethermintd keys show $VAL_KEY -a --keyring-backend test)" 1000000000000000000000aphoton,1000000000000000000stake --keyring-backend test
ethermintd add-genesis-account $(ethermintcli keys show $USER1_KEY -a) 1000000000000000000000aphoton,10000000000000000stake ethermintd add-genesis-account "$(ethermintd keys show $USER1_KEY -a --keyring-backend test)" 1000000000000000000000aphoton,1000000000000000000stake --keyring-backend test
ethermintd add-genesis-account $(ethermintcli keys show $USER2_KEY -a) 1000000000000000000000aphoton,10000000000000000stake ethermintd add-genesis-account "$(ethermintd keys show $USER2_KEY -a --keyring-backend test)" 1000000000000000000000aphoton,1000000000000000000stake --keyring-backend test
# Sign genesis transaction # Sign genesis transaction
ethermintd gentx --name $VAL_KEY --keyring-backend test ethermintd gentx $VAL_KEY 1000000000000000000stake --amount=1000000000000000000000aphoton --chain-id $CHAINID --keyring-backend test
# Collect genesis tx # Collect genesis tx
ethermintd collect-gentxs ethermintd collect-gentxs
@ -45,9 +39,5 @@ ethermintd collect-gentxs
# Run this to ensure everything worked and that the genesis file is setup correctly # Run this to ensure everything worked and that the genesis file is setup correctly
ethermintd validate-genesis ethermintd validate-genesis
# Command to run the rest server in a different terminal/window
echo -e '\nrun the following command in a different terminal/window to run the REST server and JSON-RPC:'
echo -e "ethermintcli rest-server --laddr \"tcp://localhost:8545\" --wsport 8546 --unlock-key $VAL_KEY,$USER1_KEY,$USER2_KEY --chain-id $CHAINID --trace\n"
# Start the node (remove the --pruning=nothing flag if historical queries are not needed) # Start the node (remove the --pruning=nothing flag if historical queries are not needed)
ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace ethermintd start --pruning=nothing --rpc.unsafe --rpc-api "web3, eth, personal, net" --keyring-backend test --trace --log_level "info"

View File

@ -4,13 +4,16 @@
"author": "Aragon Association <contact@aragon.org>", "author": "Aragon Association <contact@aragon.org>",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"scripts": { "scripts": {
"contract-compile": "yarn truffle compile",
"contract-migrate": "yarn truffle migrate --network ethermint",
"test-ganache": "yarn truffle test", "test-ganache": "yarn truffle test",
"test-ethermint": "yarn truffle test --network ethermint" "test-ethermint": "yarn truffle test --network ethermint"
}, },
"devDependencies": { "devDependencies": {
"@aragon/contract-helpers-test": "^0.1.0", "@aragon/contract-helpers-test": "^0.1.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"truffle": "^5.1.42", "truffle": "^5.2.5",
"web3": "^1.2.11" "web3": "^1.3.4",
"sleep": "^6.3.0"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -34,8 +34,11 @@ func TestPersonal_NewAccount(t *testing.T) {
} }
func TestPersonal_Sign(t *testing.T) { func TestPersonal_Sign(t *testing.T) {
rpcRes := Call(t, "personal_sign", []interface{}{hexutil.Bytes{0x88}, hexutil.Bytes(from), ""}) rpcRes := Call(t, "personal_unlockAccount", []interface{}{hexutil.Bytes(from), ""})
require.Nil(t, rpcRes.Error)
rpcRes = Call(t, "personal_sign", []interface{}{hexutil.Bytes{0x88}, hexutil.Bytes(from), ""})
require.Nil(t, rpcRes.Error)
var res hexutil.Bytes var res hexutil.Bytes
err := json.Unmarshal(rpcRes.Result, &res) err := json.Unmarshal(rpcRes.Result, &res)
require.NoError(t, err) require.NoError(t, err)

View File

@ -1,9 +1,8 @@
// This is a test utility for Ethermint's Web3 JSON-RPC services. // This is a test utility for Ethermint's Web3 JSON-RPC services.
// //
// To run these tests please first ensure you have the ethermintd running // To run these tests please first ensure you have the ethermintd running
// and have started the RPC service with `ethermintcli rest-server`.
// //
// You can configure the desired HOST and MODE as well // You can configure the desired HOST and MODE as well in integration-test-all.sh
package tests package tests
import ( import (
@ -55,6 +54,33 @@ func TestMain(m *testing.M) {
os.Exit(code) os.Exit(code)
} }
func TestEth_GetTransactionCount(t *testing.T) {
// TODO: this test passes on when run on its own, but fails when run with the other tests
if testing.Short() {
t.Skip("skipping TestEth_GetTransactionCount")
}
prev := GetNonce(t, "latest")
SendTestTransaction(t, from)
time.Sleep(20 * time.Second)
post := GetNonce(t, "latest")
require.Equal(t, prev, post-1)
}
func TestEth_GetLogs_NoLogs(t *testing.T) {
param := make([]map[string][]string, 1)
param[0] = make(map[string][]string)
param[0]["topics"] = []string{}
rpcRes := Call(t, "eth_getLogs", param)
require.NotNil(t, rpcRes)
require.Nil(t, rpcRes.Error)
var logs []*ethtypes.Log
err := json.Unmarshal(rpcRes.Result, &logs)
require.NoError(t, err)
require.Empty(t, logs) // begin, end are -1, crit.Addresses, crit.Topics are empty array, so no log should be returned(run this test before anyone else so that log will be empty)
}
func TestBlockBloom(t *testing.T) { func TestBlockBloom(t *testing.T) {
hash := DeployTestContractWithFunction(t, from) hash := DeployTestContractWithFunction(t, from)
receipt := WaitForReceipt(t, hash) receipt := WaitForReceipt(t, hash)
@ -72,20 +98,6 @@ func TestBlockBloom(t *testing.T) {
require.Equal(t, hash.String(), block["transactions"].([]interface{})[0]) require.Equal(t, hash.String(), block["transactions"].([]interface{})[0])
} }
func TestEth_GetLogs_NoLogs(t *testing.T) {
param := make([]map[string][]string, 1)
param[0] = make(map[string][]string)
param[0]["topics"] = []string{}
rpcRes := Call(t, "eth_getLogs", param)
require.NotNil(t, rpcRes)
require.Nil(t, rpcRes.Error)
var logs []*ethtypes.Log
err := json.Unmarshal(rpcRes.Result, &logs)
require.NoError(t, err)
require.NotEmpty(t, logs)
}
func TestEth_GetLogs_Topics_AB(t *testing.T) { func TestEth_GetLogs_Topics_AB(t *testing.T) {
// TODO: this test passes on when run on its own, but fails when run with the other tests // TODO: this test passes on when run on its own, but fails when run with the other tests
if testing.Short() { if testing.Short() {
@ -115,18 +127,6 @@ func TestEth_GetLogs_Topics_AB(t *testing.T) {
require.Equal(t, 1, len(logs)) require.Equal(t, 1, len(logs))
} }
func TestEth_GetTransactionCount(t *testing.T) {
// TODO: this test passes on when run on its own, but fails when run with the other tests
if testing.Short() {
t.Skip("skipping TestEth_GetTransactionCount")
}
prev := GetNonce(t, "latest")
SendTestTransaction(t, from)
post := GetNonce(t, "latest")
require.Equal(t, prev, post-1)
}
func TestEth_GetTransactionLogs(t *testing.T) { func TestEth_GetTransactionLogs(t *testing.T) {
// TODO: this test passes on when run on its own, but fails when run with the other tests // TODO: this test passes on when run on its own, but fails when run with the other tests
if testing.Short() { if testing.Short() {
@ -205,7 +205,8 @@ func TestEth_GetBalance(t *testing.T) {
func TestEth_GetStorageAt(t *testing.T) { func TestEth_GetStorageAt(t *testing.T) {
expectedRes := hexutil.Bytes{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} expectedRes := hexutil.Bytes{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
rpcRes := Call(t, "eth_getStorageAt", []string{addrA, fmt.Sprint(addrAStoreKey), zeroString}) testKey := 1 // using 0 as key here will create an ethereum empty hash which is considered as invalid hash
rpcRes := Call(t, "eth_getStorageAt", []string{addrA, fmt.Sprint(testKey), "0x3"})
var storage hexutil.Bytes var storage hexutil.Bytes
err := storage.UnmarshalJSON(rpcRes.Result) err := storage.UnmarshalJSON(rpcRes.Result)
@ -220,7 +221,8 @@ func TestEth_GetProof(t *testing.T) {
params := make([]interface{}, 3) params := make([]interface{}, 3)
params[0] = addrA params[0] = addrA
params[1] = []string{fmt.Sprint(addrAStoreKey)} params[1] = []string{fmt.Sprint(addrAStoreKey)}
params[2] = "latest" params[2] = "0x3" // queries at height <= 2 are not supported
rpcRes := Call(t, "eth_getProof", params) rpcRes := Call(t, "eth_getProof", params)
require.NotNil(t, rpcRes) require.NotNil(t, rpcRes)
@ -255,7 +257,10 @@ func TestEth_SendTransaction_Transfer(t *testing.T) {
param[0]["gasLimit"] = "0x5208" param[0]["gasLimit"] = "0x5208"
param[0]["gasPrice"] = "0x55ae82600" param[0]["gasPrice"] = "0x55ae82600"
rpcRes := Call(t, "eth_sendTransaction", param) rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, rpcRes.Error)
rpcRes = Call(t, "eth_sendTransaction", param)
var hash hexutil.Bytes var hash hexutil.Bytes
err := json.Unmarshal(rpcRes.Result, &hash) err := json.Unmarshal(rpcRes.Result, &hash)
@ -272,7 +277,10 @@ func TestEth_SendTransaction_ContractDeploy(t *testing.T) {
param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["from"] = "0x" + fmt.Sprintf("%x", from)
param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029"
rpcRes := Call(t, "eth_sendTransaction", param) rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, rpcRes.Error)
rpcRes = Call(t, "eth_sendTransaction", param)
var hash hexutil.Bytes var hash hexutil.Bytes
err := json.Unmarshal(rpcRes.Result, &hash) err := json.Unmarshal(rpcRes.Result, &hash)
@ -369,12 +377,15 @@ func TestEth_GetTransactionReceipt(t *testing.T) {
} }
func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) {
rpcRes := Call(t, "personal_unlockAccount", []interface{}{hexutil.Bytes(from), ""})
require.Nil(t, rpcRes.Error)
hash, _ := DeployTestContract(t, from) hash, _ := DeployTestContract(t, from)
time.Sleep(time.Second * 5) time.Sleep(time.Second * 5)
param := []string{hash.String()} param := []string{hash.String()}
rpcRes := Call(t, "eth_getTransactionReceipt", param) rpcRes = Call(t, "eth_getTransactionReceipt", param)
receipt := make(map[string]interface{}) receipt := make(map[string]interface{})
err := json.Unmarshal(rpcRes.Result, &receipt) err := json.Unmarshal(rpcRes.Result, &receipt)
@ -410,11 +421,7 @@ func TestEth_GetFilterChanges_NoTopics(t *testing.T) {
// get filter changes // get filter changes
changesRes := Call(t, "eth_getFilterChanges", []string{ID}) changesRes := Call(t, "eth_getFilterChanges", []string{ID})
require.Equal(t, 2, len(changesRes.Result))
var logs []*ethtypes.Log
err = json.Unmarshal(changesRes.Result, &logs)
require.NoError(t, err)
require.Equal(t, 1, len(logs))
} }
func TestEth_GetFilterChanges_Addresses(t *testing.T) { func TestEth_GetFilterChanges_Addresses(t *testing.T) {
@ -458,12 +465,7 @@ func TestEth_GetFilterChanges_Topics_AB(t *testing.T) {
// get filter changes // get filter changes
changesRes := Call(t, "eth_getFilterChanges", []string{ID}) changesRes := Call(t, "eth_getFilterChanges", []string{ID})
require.Equal(t, 2, len(changesRes.Result))
var logs []*ethtypes.Log
err = json.Unmarshal(changesRes.Result, &logs)
require.NoError(t, err)
require.Equal(t, 1, len(logs))
} }
func TestEth_GetFilterChanges_Topics_XB(t *testing.T) { func TestEth_GetFilterChanges_Topics_XB(t *testing.T) {
@ -488,12 +490,7 @@ func TestEth_GetFilterChanges_Topics_XB(t *testing.T) {
// get filter changes // get filter changes
changesRes := Call(t, "eth_getFilterChanges", []string{ID}) changesRes := Call(t, "eth_getFilterChanges", []string{ID})
require.Equal(t, 2, len(changesRes.Result))
var logs []*ethtypes.Log
err = json.Unmarshal(changesRes.Result, &logs)
require.NoError(t, err)
require.Equal(t, 1, len(logs))
} }
func TestEth_GetFilterChanges_Topics_XXC(t *testing.T) { func TestEth_GetFilterChanges_Topics_XXC(t *testing.T) {
@ -532,7 +529,11 @@ func TestEth_EstimateGas(t *testing.T) {
param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["from"] = "0x" + fmt.Sprintf("%x", from)
param[0]["to"] = "0x1122334455667788990011223344556677889900" param[0]["to"] = "0x1122334455667788990011223344556677889900"
param[0]["value"] = "0x1" param[0]["value"] = "0x1"
rpcRes := Call(t, "eth_estimateGas", param)
rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.NotNil(t, rpcRes)
rpcRes = Call(t, "eth_estimateGas", param)
require.NotNil(t, rpcRes) require.NotNil(t, rpcRes)
require.NotEmpty(t, rpcRes.Result) require.NotEmpty(t, rpcRes.Result)
@ -540,7 +541,7 @@ func TestEth_EstimateGas(t *testing.T) {
err := json.Unmarshal(rpcRes.Result, &gas) err := json.Unmarshal(rpcRes.Result, &gas)
require.NoError(t, err, string(rpcRes.Result)) require.NoError(t, err, string(rpcRes.Result))
require.Equal(t, "0xf560", gas) require.Equal(t, "0xfab9", gas)
} }
func TestEth_EstimateGas_ContractDeployment(t *testing.T) { func TestEth_EstimateGas_ContractDeployment(t *testing.T) {
@ -558,6 +559,9 @@ func TestEth_EstimateGas_ContractDeployment(t *testing.T) {
param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["from"] = "0x" + fmt.Sprintf("%x", from)
param[0]["data"] = bytecode param[0]["data"] = bytecode
rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.NotNil(t, rpcRes)
rpcRes = Call(t, "eth_estimateGas", param) rpcRes = Call(t, "eth_estimateGas", param)
require.NotNil(t, rpcRes) require.NotNil(t, rpcRes)
require.NotEmpty(t, rpcRes.Result) require.NotEmpty(t, rpcRes.Result)
@ -566,7 +570,7 @@ func TestEth_EstimateGas_ContractDeployment(t *testing.T) {
err := json.Unmarshal(rpcRes.Result, &gas) err := json.Unmarshal(rpcRes.Result, &gas)
require.NoError(t, err, string(rpcRes.Result)) require.NoError(t, err, string(rpcRes.Result))
require.Equal(t, "0x1a738", gas.String()) require.Equal(t, "0x1ab8d", gas.String())
} }
func TestEth_GetBlockByNumber(t *testing.T) { func TestEth_GetBlockByNumber(t *testing.T) {

View File

@ -1,9 +1,8 @@
// This is a test utility for Ethermint's Web3 JSON-RPC services. // This is a test utility for Ethermint's Web3 JSON-RPC services.
// //
// To run these tests please first ensure you have the ethermintd running // To run these tests please first ensure you have the ethermintd running
// and have started the RPC service with `ethermintcli rest-server`.
// //
// You can configure the desired HOST and MODE as well // You can configure the desired HOST and MODE as well in integration-test-all.sh
package pending package pending
import ( import (
@ -13,10 +12,9 @@ import (
"os" "os"
"testing" "testing"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require"
rpctypes "github.com/cosmos/ethermint/rpc/types" rpctypes "github.com/cosmos/ethermint/rpc/types"
util "github.com/cosmos/ethermint/tests" util "github.com/cosmos/ethermint/tests"
@ -92,6 +90,9 @@ func TestEth_Pending_GetBalance(t *testing.T) {
param[0]["gasLimit"] = "0x5208" param[0]["gasLimit"] = "0x5208"
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
rpcRes = util.Call(t, "eth_sendTransaction", param) rpcRes = util.Call(t, "eth_sendTransaction", param)
require.Nil(t, rpcRes.Error) require.Nil(t, rpcRes.Error)
@ -118,6 +119,7 @@ func TestEth_Pending_GetTransactionCount(t *testing.T) {
currentNonce := util.GetNonce(t, "latest") currentNonce := util.GetNonce(t, "latest")
t.Logf("Current nonce is %d", currentNonce) t.Logf("Current nonce is %d", currentNonce)
require.Equal(t, prePendingNonce, currentNonce)
param := make([]map[string]string, 1) param := make([]map[string]string, 1)
param[0] = make(map[string]string) param[0] = make(map[string]string)
@ -127,17 +129,20 @@ func TestEth_Pending_GetTransactionCount(t *testing.T) {
param[0]["gasLimit"] = "0x5208" param[0]["gasLimit"] = "0x5208"
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
txRes := util.Call(t, "eth_sendTransaction", param) txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
txRes = util.Call(t, "eth_sendTransaction", param)
require.Nil(t, txRes.Error) require.Nil(t, txRes.Error)
pendingNonce := util.GetNonce(t, "pending") pendingNonce := util.GetNonce(t, "pending")
latestNonce := util.GetNonce(t, "latest") latestNonce := util.GetNonce(t, "latest")
t.Logf("Latest nonce is %d", latestNonce)
require.Equal(t, currentNonce, latestNonce)
t.Logf("Pending nonce is %d", pendingNonce)
require.NotEqual(t, latestNonce, pendingNonce)
require.Greater(t, uint64(pendingNonce), uint64(latestNonce)) t.Logf("Latest nonce is %d", latestNonce)
require.Equal(t, currentNonce+1, latestNonce)
t.Logf("Pending nonce is %d", pendingNonce)
require.Equal(t, latestNonce, pendingNonce)
require.Equal(t, uint64(prePendingNonce)+uint64(1), uint64(pendingNonce)) require.Equal(t, uint64(prePendingNonce)+uint64(1), uint64(pendingNonce))
} }
@ -154,6 +159,8 @@ func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
t.Logf("Pre tx latest nonce is %d", preTxLatestTxCount) t.Logf("Pre tx latest nonce is %d", preTxLatestTxCount)
require.Equal(t, preTxPendingTxCount, preTxLatestTxCount)
param := make([]map[string]string, 1) param := make([]map[string]string, 1)
param[0] = make(map[string]string) param[0] = make(map[string]string)
param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["from"] = "0x" + fmt.Sprintf("%x", from)
@ -162,7 +169,10 @@ func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) {
param[0]["gasLimit"] = "0x5208" param[0]["gasLimit"] = "0x5208"
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
txRes := util.Call(t, "eth_sendTransaction", param) txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
txRes = util.Call(t, "eth_sendTransaction", param)
require.Nil(t, txRes.Error) require.Nil(t, txRes.Error)
rpcRes = util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) rpcRes = util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"})
@ -177,8 +187,10 @@ func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
t.Logf("Post tx latest nonce is %d", postTxLatestTxCount) t.Logf("Post tx latest nonce is %d", postTxLatestTxCount)
require.Equal(t, uint64(preTxPendingTxCount)+uint64(1), uint64(postTxPendingTxCount)) require.Equal(t, postTxPendingTxCount, postTxLatestTxCount)
require.NotEqual(t, uint64(postTxPendingTxCount)-uint64(preTxPendingTxCount), uint64(postTxLatestTxCount)-uint64(preTxLatestTxCount))
require.Equal(t, uint64(preTxPendingTxCount), uint64(postTxPendingTxCount))
require.Equal(t, uint64(postTxPendingTxCount)-uint64(preTxPendingTxCount), uint64(postTxLatestTxCount)-uint64(preTxLatestTxCount))
} }
func TestEth_Pending_GetBlockByNumber(t *testing.T) { func TestEth_Pending_GetBlockByNumber(t *testing.T) {
@ -202,7 +214,9 @@ func TestEth_Pending_GetBlockByNumber(t *testing.T) {
param[0]["gasLimit"] = "0x5208" param[0]["gasLimit"] = "0x5208"
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
txRes := util.Call(t, "eth_sendTransaction", param) txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
txRes = util.Call(t, "eth_sendTransaction", param)
require.Nil(t, txRes.Error) require.Nil(t, txRes.Error)
rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"pending", true})
@ -210,7 +224,7 @@ func TestEth_Pending_GetBlockByNumber(t *testing.T) {
err = json.Unmarshal(rpcRes.Result, &postTxPendingBlock) err = json.Unmarshal(rpcRes.Result, &postTxPendingBlock)
require.NoError(t, err) require.NoError(t, err)
postTxPendingTxs := len(postTxPendingBlock["transactions"].([]interface{})) postTxPendingTxs := len(postTxPendingBlock["transactions"].([]interface{}))
require.Greater(t, postTxPendingTxs, preTxPendingTxs) require.Equal(t, postTxPendingTxs, preTxPendingTxs)
rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"latest", true})
var postTxLatestBlock map[string]interface{} var postTxLatestBlock map[string]interface{}
@ -219,7 +233,7 @@ func TestEth_Pending_GetBlockByNumber(t *testing.T) {
postTxLatestTxs := len(postTxLatestBlock["transactions"].([]interface{})) postTxLatestTxs := len(postTxLatestBlock["transactions"].([]interface{}))
require.Equal(t, preTxLatestTxs, postTxLatestTxs) require.Equal(t, preTxLatestTxs, postTxLatestTxs)
require.Greater(t, postTxPendingTxs, preTxPendingTxs) require.Equal(t, postTxPendingTxs, preTxPendingTxs)
} }
func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) {
@ -239,26 +253,33 @@ func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) {
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
param[0]["data"] = data param[0]["data"] = data
txRes := util.Call(t, "eth_sendTransaction", param) txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
txRes = util.Call(t, "eth_sendTransaction", param)
require.Nil(t, txRes.Error) require.Nil(t, txRes.Error)
rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x" + fmt.Sprintf("%X", pendingTxCount)}) // test will be blocked here until tx gets confirmed
var pendingBlockTx map[string]interface{} var txHash common.Hash
err = json.Unmarshal(rpcRes.Result, &pendingBlockTx) err = json.Unmarshal(txRes.Result, &txHash)
require.NoError(t, err)
rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x" + fmt.Sprintf("%X", pendingTxCount)})
var latestBlockTx map[string]interface{}
err = json.Unmarshal(rpcRes.Result, &latestBlockTx)
require.NoError(t, err) require.NoError(t, err)
// verify the pending tx has all the correct fields from the tx sent. // verify the pending tx has all the correct fields from the tx sent.
require.NotEmpty(t, pendingBlockTx["hash"]) require.NotEmpty(t, latestBlockTx["hash"])
require.Equal(t, pendingBlockTx["value"], "0xa") require.Equal(t, latestBlockTx["value"], "0xa")
require.Equal(t, data, pendingBlockTx["input"]) require.Equal(t, data, latestBlockTx["input"])
rpcRes = util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x" + fmt.Sprintf("%X", pendingTxCount)}) rpcRes = util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x" + fmt.Sprintf("%X", pendingTxCount)})
var latestBlock map[string]interface{} var pendingBlock map[string]interface{}
err = json.Unmarshal(rpcRes.Result, &latestBlock) err = json.Unmarshal(rpcRes.Result, &pendingBlock)
require.NoError(t, err) require.NoError(t, err)
// verify the pending trasnaction does not exist in the latest block info. // verify the transaction does not exist in the pending block info.
require.Empty(t, latestBlock) require.Empty(t, pendingBlock)
} }
func TestEth_Pending_GetTransactionByHash(t *testing.T) { func TestEth_Pending_GetTransactionByHash(t *testing.T) {
@ -272,7 +293,10 @@ func TestEth_Pending_GetTransactionByHash(t *testing.T) {
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
param[0]["data"] = data param[0]["data"] = data
txRes := util.Call(t, "eth_sendTransaction", param) txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
txRes = util.Call(t, "eth_sendTransaction", param)
var txHash common.Hash var txHash common.Hash
err := txHash.UnmarshalJSON(txRes.Result) err := txHash.UnmarshalJSON(txRes.Result)
require.NoError(t, err) require.NoError(t, err)
@ -299,6 +323,9 @@ func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) {
param[0]["gasLimit"] = "0x5208" param[0]["gasLimit"] = "0x5208"
param[0]["gasPrice"] = "0x1" param[0]["gasPrice"] = "0x1"
txRes := util.Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, txRes.Error)
// first transaction // first transaction
txRes1 := util.Call(t, "eth_sendTransaction", param) txRes1 := util.Call(t, "eth_sendTransaction", param)
require.Nil(t, txRes1.Error) require.Nil(t, txRes1.Error)

View File

@ -141,7 +141,12 @@ func SendTestTransaction(t *testing.T, addr []byte) hexutil.Bytes {
param[0]["from"] = "0x" + fmt.Sprintf("%x", addr) param[0]["from"] = "0x" + fmt.Sprintf("%x", addr)
param[0]["to"] = "0x1122334455667788990011223344556677889900" param[0]["to"] = "0x1122334455667788990011223344556677889900"
param[0]["value"] = "0x1" param[0]["value"] = "0x1"
rpcRes := Call(t, "eth_sendTransaction", param)
rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, rpcRes.Error)
rpcRes = Call(t, "eth_sendTransaction", param)
require.Nil(t, rpcRes.Error)
var hash hexutil.Bytes var hash hexutil.Bytes
err := json.Unmarshal(rpcRes.Result, &hash) err := json.Unmarshal(rpcRes.Result, &hash)
@ -157,7 +162,11 @@ func DeployTestContract(t *testing.T, addr []byte) (hexutil.Bytes, map[string]in
param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029"
param[0]["gas"] = "0x200000" param[0]["gas"] = "0x200000"
rpcRes := Call(t, "eth_sendTransaction", param) rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, rpcRes.Error)
rpcRes = Call(t, "eth_sendTransaction", param)
require.Nil(t, rpcRes.Error)
var hash hexutil.Bytes var hash hexutil.Bytes
err := json.Unmarshal(rpcRes.Result, &hash) err := json.Unmarshal(rpcRes.Result, &hash)
@ -197,7 +206,10 @@ func DeployTestContractWithFunction(t *testing.T, addr []byte) hexutil.Bytes {
param[0]["data"] = bytecode param[0]["data"] = bytecode
param[0]["gas"] = "0x200000" param[0]["gas"] = "0x200000"
rpcRes := Call(t, "eth_sendTransaction", param) rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.Nil(t, rpcRes.Error)
rpcRes = Call(t, "eth_sendTransaction", param)
var hash hexutil.Bytes var hash hexutil.Bytes
err := json.Unmarshal(rpcRes.Result, &hash) err := json.Unmarshal(rpcRes.Result, &hash)

View File

@ -0,0 +1,62 @@
syntax = "proto3";
package cosmos.auth.v1beta1;
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types";
// BaseAccount defines a base account type. It contains all the necessary fields
// for basic account functionality. Any custom account type should extend this
// type for additional functionality (e.g. vesting).
message BaseAccount {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
option (gogoproto.equal) = false;
option (cosmos_proto.implements_interface) = "AccountI";
string address = 1;
google.protobuf.Any pub_key = 2 [
(gogoproto.jsontag) = "public_key,omitempty",
(gogoproto.moretags) = "yaml:\"public_key\""
];
uint64 account_number = 3
[ (gogoproto.moretags) = "yaml:\"account_number\"" ];
uint64 sequence = 4;
}
// ModuleAccount defines an account for modules that holds coins on a pool.
message ModuleAccount {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
option (cosmos_proto.implements_interface) = "ModuleAccountI";
BaseAccount base_account = 1 [
(gogoproto.embed) = true,
(gogoproto.moretags) = "yaml:\"base_account\""
];
string name = 2;
repeated string permissions = 3;
}
// Params defines the parameters for the auth module.
message Params {
option (gogoproto.equal) = true;
option (gogoproto.goproto_stringer) = false;
uint64 max_memo_characters = 1
[ (gogoproto.moretags) = "yaml:\"max_memo_characters\"" ];
uint64 tx_sig_limit = 2 [ (gogoproto.moretags) = "yaml:\"tx_sig_limit\"" ];
uint64 tx_size_cost_per_byte = 3
[ (gogoproto.moretags) = "yaml:\"tx_size_cost_per_byte\"" ];
uint64 sig_verify_cost_ed25519 = 4 [
(gogoproto.customname) = "SigVerifyCostED25519",
(gogoproto.moretags) = "yaml:\"sig_verify_cost_ed25519\""
];
uint64 sig_verify_cost_secp256k1 = 5 [
(gogoproto.customname) = "SigVerifyCostSecp256k1",
(gogoproto.moretags) = "yaml:\"sig_verify_cost_secp256k1\""
];
}

View File

@ -0,0 +1,17 @@
syntax = "proto3";
package cosmos.auth.v1beta1;
import "google/protobuf/any.proto";
import "gogoproto/gogo.proto";
import "cosmos/auth/v1beta1/auth.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types";
// GenesisState defines the auth module's genesis state.
message GenesisState {
// params defines all the paramaters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
// accounts are the accounts present at genesis.
repeated google.protobuf.Any accounts = 2;
}

View File

@ -0,0 +1,48 @@
syntax = "proto3";
package cosmos.auth.v1beta1;
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "google/api/annotations.proto";
import "cosmos/auth/v1beta1/auth.proto";
import "cosmos_proto/cosmos.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types";
// Query defines the gRPC querier service.
service Query {
// Account returns account details based on address.
rpc Account(QueryAccountRequest) returns (QueryAccountResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/accounts/{address}";
}
// Params queries all parameters.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/params";
}
}
// QueryAccountRequest is the request type for the Query/Account RPC method.
message QueryAccountRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// address defines the address to query for.
string address = 1;
}
// QueryAccountResponse is the response type for the Query/Account RPC method.
message QueryAccountResponse {
// account defines the account of the corresponding address.
google.protobuf.Any account = 1
[ (cosmos_proto.accepts_interface) = "AccountI" ];
}
// QueryParamsRequest is the request type for the Query/Params RPC method.
message QueryParamsRequest {}
// QueryParamsResponse is the response type for the Query/Params RPC method.
message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
}

View File

@ -0,0 +1,94 @@
syntax = "proto3";
package cosmos.bank.v1beta1;
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";
import "cosmos/base/v1beta1/coin.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types";
// Params defines the parameters for the bank module.
message Params {
option (gogoproto.goproto_stringer) = false;
repeated SendEnabled send_enabled = 1
[ (gogoproto.moretags) = "yaml:\"send_enabled,omitempty\"" ];
bool default_send_enabled = 2
[ (gogoproto.moretags) = "yaml:\"default_send_enabled,omitempty\"" ];
}
// SendEnabled maps coin denom to a send_enabled status (whether a denom is
// sendable).
message SendEnabled {
option (gogoproto.equal) = true;
option (gogoproto.goproto_stringer) = false;
string denom = 1;
bool enabled = 2;
}
// Input models transaction input.
message Input {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
// Output models transaction outputs.
message Output {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
// Supply represents a struct that passively keeps track of the total supply
// amounts in the network.
message Supply {
option (gogoproto.equal) = true;
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
option (cosmos_proto.implements_interface) =
"*github.com/cosmos/cosmos-sdk/x/bank/exported.SupplyI";
repeated cosmos.base.v1beta1.Coin total = 1 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
// DenomUnit represents a struct that describes a given
// denomination unit of the basic token.
message DenomUnit {
// denom represents the string name of the given denom unit (e.g uatom).
string denom = 1;
// exponent represents power of 10 exponent that one must
// raise the base_denom to in order to equal the given DenomUnit's denom
// 1 denom = 1^exponent base_denom
// (e.g. with a base_denom of uatom, one can create a DenomUnit of 'atom' with
// exponent = 6, thus: 1 atom = 10^6 uatom).
uint32 exponent = 2;
// aliases is a list of string aliases for the given denom
repeated string aliases = 3;
}
// Metadata represents a struct that describes
// a basic token.
message Metadata {
string description = 1;
// denom_units represents the list of DenomUnit's for a given coin
repeated DenomUnit denom_units = 2;
// base represents the base denom (should be the DenomUnit with exponent = 0).
string base = 3;
// display indicates the suggested denom that should be
// displayed in clients.
string display = 4;
}

View File

@ -0,0 +1,45 @@
syntax = "proto3";
package cosmos.bank.v1beta1;
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/bank/v1beta1/bank.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types";
// GenesisState defines the bank module's genesis state.
message GenesisState {
// params defines all the paramaters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
// balances is an array containing the balances of all the accounts.
repeated Balance balances = 2 [ (gogoproto.nullable) = false ];
// supply represents the total supply.
repeated cosmos.base.v1beta1.Coin supply = 3 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.nullable) = false
];
// denom_metadata defines the metadata of the differents coins.
repeated Metadata denom_metadata = 4 [
(gogoproto.moretags) = "yaml:\"denom_metadata\"",
(gogoproto.nullable) = false
];
}
// Balance defines an account address and balance pair used in the bank module's
// genesis state.
message Balance {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// address is the address of the balance holder.
string address = 1;
// coins defines the different coins this balance holds.
repeated cosmos.base.v1beta1.Coin coins = 2 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins",
(gogoproto.nullable) = false
];
}

View File

@ -0,0 +1,116 @@
syntax = "proto3";
package cosmos.bank.v1beta1;
import "cosmos/base/query/v1beta1/pagination.proto";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/bank/v1beta1/bank.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types";
// Query defines the gRPC querier service.
service Query {
// Balance queries the balance of a single coin for a single account.
rpc Balance(QueryBalanceRequest) returns (QueryBalanceResponse) {
option (google.api.http).get =
"/cosmos/bank/v1beta1/balances/{address}/{denom}";
}
// AllBalances queries the balance of all coins for a single account.
rpc AllBalances(QueryAllBalancesRequest) returns (QueryAllBalancesResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/balances/{address}";
}
// TotalSupply queries the total supply of all coins.
rpc TotalSupply(QueryTotalSupplyRequest) returns (QueryTotalSupplyResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/supply";
}
// SupplyOf queries the supply of a single coin.
rpc SupplyOf(QuerySupplyOfRequest) returns (QuerySupplyOfResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/supply/{denom}";
}
// Params queries the parameters of x/bank module.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (google.api.http).get = "/cosmos/bank/v1beta1/params";
}
}
// QueryBalanceRequest is the request type for the Query/Balance RPC method.
message QueryBalanceRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// address is the address to query balances for.
string address = 1;
// denom is the coin denom to query balances for.
string denom = 2;
}
// QueryBalanceResponse is the response type for the Query/Balance RPC method.
message QueryBalanceResponse {
// balance is the balance of the coin.
cosmos.base.v1beta1.Coin balance = 1;
}
// QueryBalanceRequest is the request type for the Query/AllBalances RPC method.
message QueryAllBalancesRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// address is the address to query balances for.
string address = 1;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}
// QueryAllBalancesResponse is the response type for the Query/AllBalances RPC
// method.
message QueryAllBalancesResponse {
// balances is the balances of all the coins.
repeated cosmos.base.v1beta1.Coin balances = 1 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC
// method.
message QueryTotalSupplyRequest {}
// QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC
// method
message QueryTotalSupplyResponse {
// supply is the supply of the coins
repeated cosmos.base.v1beta1.Coin supply = 1 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
// QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method.
message QuerySupplyOfRequest {
// denom is the coin denom to query balances for.
string denom = 1;
}
// QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method.
message QuerySupplyOfResponse {
// amount is the supply of the coin.
cosmos.base.v1beta1.Coin amount = 1 [ (gogoproto.nullable) = false ];
}
// QueryParamsRequest defines the request type for querying x/bank parameters.
message QueryParamsRequest {}
// QueryParamsResponse defines the response type for querying x/bank parameters.
message QueryParamsResponse {
Params params = 1 [ (gogoproto.nullable) = false ];
}

View File

@ -0,0 +1,29 @@
syntax = "proto3";
package cosmos.bank.v1beta1;
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/bank/v1beta1/bank.proto";
option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types";
// MsgSend represents a message to send coins from one account to another.
message MsgSend {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
string from_address = 1 [ (gogoproto.moretags) = "yaml:\"from_address\"" ];
string to_address = 2 [ (gogoproto.moretags) = "yaml:\"to_address\"" ];
repeated cosmos.base.v1beta1.Coin amount = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];
}
// MsgMultiSend represents an arbitrary multi-in, multi-out send message.
message MsgMultiSend {
option (gogoproto.equal) = false;
repeated Input inputs = 1 [ (gogoproto.nullable) = false ];
repeated Output outputs = 2 [ (gogoproto.nullable) = false ];
}

View File

@ -0,0 +1,153 @@
syntax = "proto3";
package cosmos.base.abci.v1beta1;
import "gogoproto/gogo.proto";
import "tendermint/abci/types.proto";
import "google/protobuf/any.proto";
option go_package = "github.com/cosmos/cosmos-sdk/types";
option (gogoproto.goproto_stringer_all) = false;
// TxResponse defines a structure containing relevant tx data and metadata. The
// tags are stringified and the log is JSON decoded.
message TxResponse {
option (gogoproto.goproto_getters) = false;
// The block height
int64 height = 1;
// The transaction hash.
string txhash = 2 [ (gogoproto.customname) = "TxHash" ];
// Namespace for the Code
string codespace = 3;
// Response code.
uint32 code = 4;
// Result bytes, if any.
string data = 5;
// The output of the application's logger (raw string). May be
// non-deterministic.
string raw_log = 6;
// The output of the application's logger (typed). May be non-deterministic.
repeated ABCIMessageLog logs = 7 [
(gogoproto.castrepeated) = "ABCIMessageLogs",
(gogoproto.nullable) = false
];
// Additional information. May be non-deterministic.
string info = 8;
// Amount of gas requested for transaction.
int64 gas_wanted = 9;
// Amount of gas consumed by transaction.
int64 gas_used = 10;
// The request transaction bytes.
google.protobuf.Any tx = 11;
// Time of the previous block. For heights > 1, it's the weighted median of
// the timestamps of the valid votes in the block.LastCommit. For height == 1,
// it's genesis time.
string timestamp = 12;
}
// ABCIMessageLog defines a structure containing an indexed tx ABCI message log.
message ABCIMessageLog {
option (gogoproto.stringer) = true;
uint32 msg_index = 1;
string log = 2;
// Events contains a slice of Event objects that were emitted during some
// execution.
repeated StringEvent events = 3 [
(gogoproto.castrepeated) = "StringEvents",
(gogoproto.nullable) = false
];
}
// StringEvent defines en Event object wrapper where all the attributes
// contain key/value pairs that are strings instead of raw bytes.
message StringEvent {
option (gogoproto.stringer) = true;
string type = 1;
repeated Attribute attributes = 2 [ (gogoproto.nullable) = false ];
}
// Attribute defines an attribute wrapper where the key and value are
// strings instead of raw bytes.
message Attribute {
string key = 1;
string value = 2;
}
// GasInfo defines tx execution gas context.
message GasInfo {
// GasWanted is the maximum units of work we allow this tx to perform.
uint64 gas_wanted = 1 [ (gogoproto.moretags) = "yaml:\"gas_wanted\"" ];
// GasUsed is the amount of gas actually consumed.
uint64 gas_used = 2 [ (gogoproto.moretags) = "yaml:\"gas_used\"" ];
}
// Result is the union of ResponseFormat and ResponseCheckTx.
message Result {
option (gogoproto.goproto_getters) = false;
// Data is any data returned from message or handler execution. It MUST be
// length prefixed in order to separate data from multiple message executions.
bytes data = 1;
// Log contains the log information from message or handler execution.
string log = 2;
// Events contains a slice of Event objects that were emitted during message
// or handler execution.
repeated tendermint.abci.Event events = 3 [ (gogoproto.nullable) = false ];
}
// SimulationResponse defines the response generated when a transaction is
// successfully simulated.
message SimulationResponse {
GasInfo gas_info = 1
[ (gogoproto.embed) = true, (gogoproto.nullable) = false ];
Result result = 2;
}
// MsgData defines the data returned in a Result object during message
// execution.
message MsgData {
option (gogoproto.stringer) = true;
string msg_type = 1;
bytes data = 2;
}
// TxMsgData defines a list of MsgData. A transaction will have a MsgData object
// for each message.
message TxMsgData {
option (gogoproto.stringer) = true;
repeated MsgData data = 1;
}
// SearchTxsResult defines a structure for querying txs pageable
message SearchTxsResult {
option (gogoproto.stringer) = true;
// Count of all txs
uint64 total_count = 1 [
(gogoproto.moretags) = "yaml:\"total_count\"",
(gogoproto.jsontag) = "total_count"
];
// Count of txs in current page
uint64 count = 2;
// Index of current page, start from 1
uint64 page_number = 3 [
(gogoproto.moretags) = "yaml:\"page_number\"",
(gogoproto.jsontag) = "page_number"
];
// Count of total pages
uint64 page_total = 4 [
(gogoproto.moretags) = "yaml:\"page_total\"",
(gogoproto.jsontag) = "page_total"
];
// Max count txs per page
uint64 limit = 5;
// List of txs in current page
repeated TxResponse txs = 6;
}

View File

@ -0,0 +1,15 @@
syntax = "proto3";
package cosmos.base.kv.v1beta1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/types/kv";
// Pairs defines a repeated slice of Pair objects.
message Pairs { repeated Pair pairs = 1 [ (gogoproto.nullable) = false ]; }
// Pair defines a key/value bytes tuple.
message Pair {
bytes key = 1;
bytes value = 2;
}

View File

@ -0,0 +1,50 @@
syntax = "proto3";
package cosmos.base.query.v1beta1;
option go_package = "github.com/cosmos/cosmos-sdk/types/query";
// PageRequest is to be embedded in gRPC request messages for efficient
// pagination. Ex:
//
// message SomeRequest {
// Foo some_parameter = 1;
// PageRequest pagination = 2;
// }
message PageRequest {
// key is a value returned in PageResponse.next_key to begin
// querying the next page most efficiently. Only one of offset or key
// should be set.
bytes key = 1;
// offset is a numeric offset that can be used when key is unavailable.
// It is less efficient than using key. Only one of offset or key should
// be set.
uint64 offset = 2;
// limit is the total number of results to be returned in the result page.
// If left empty it will default to a value to be set by each app.
uint64 limit = 3;
// count_total is set to true to indicate that the result set should include
// a count of the total number of items available for pagination in UIs.
// count_total is only respected when offset is used. It is ignored when key
// is set.
bool count_total = 4;
}
// PageResponse is to be embedded in gRPC response messages where the
// corresponding request message has used PageRequest.
//
// message SomeResponse {
// repeated Bar results = 1;
// PageResponse page = 2;
// }
message PageResponse {
// next_key is the key to be passed to PageRequest.key to
// query the next page most efficiently
bytes next_key = 1;
// total is total number of results available if PageRequest.count_total
// was set, its value is undefined otherwise
uint64 total = 2;
}

View File

@ -0,0 +1,46 @@
syntax = "proto3";
package cosmos.base.reflection.v1beta1;
import "google/api/annotations.proto";
option go_package = "github.com/cosmos/cosmos-sdk/client/grpc/reflection";
// ReflectionService defines a service for interface reflection.
service ReflectionService {
// ListAllInterfaces lists all the interfaces registered in the interface
// registry.
rpc ListAllInterfaces(ListAllInterfacesRequest)
returns (ListAllInterfacesResponse) {
option (google.api.http).get = "/cosmos/base/reflection/v1beta1/interfaces";
};
// ListImplementations list all the concrete types that implement a given
// interface.
rpc ListImplementations(ListImplementationsRequest)
returns (ListImplementationsResponse) {
option (google.api.http).get = "/cosmos/base/reflection/v1beta1/interfaces/"
"{interface_name}/implementations";
};
}
// ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC.
message ListAllInterfacesRequest {}
// ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC.
message ListAllInterfacesResponse {
// interface_names is an array of all the registered interfaces.
repeated string interface_names = 1;
}
// ListImplementationsRequest is the request type of the ListImplementations
// RPC.
message ListImplementationsRequest {
// interface_name defines the interface to query the implementations for.
string interface_name = 1;
}
// ListImplementationsResponse is the response type of the ListImplementations
// RPC.
message ListImplementationsResponse {
repeated string implementation_message_names = 1;
}

View File

@ -0,0 +1,33 @@
syntax = "proto3";
package cosmos.base.simulate.v1beta1;
import "google/api/annotations.proto";
import "cosmos/base/abci/v1beta1/abci.proto";
import "cosmos/tx/v1beta1/tx.proto";
option go_package = "github.com/cosmos/cosmos-sdk/client/grpc/simulate";
// SimulateService defines a gRPC service for simulating transactions.
// It may also support querying and broadcasting in the future.
service SimulateService {
// Simulate simulates executing a transaction for estimating gas usage.
rpc Simulate(SimulateRequest) returns (SimulateResponse) {
option (google.api.http).post = "/cosmos/base/simulate/v1beta1/simulate";
}
}
// SimulateRequest is the request type for the SimulateServiceService.Simulate
// RPC method.
message SimulateRequest {
// tx is the transaction to simulate.
cosmos.tx.v1beta1.Tx tx = 1;
}
// SimulateResponse is the response type for the
// SimulateServiceService.SimulateRPC method.
message SimulateResponse {
// gas_info is the information about gas used in the simulation.
cosmos.base.abci.v1beta1.GasInfo gas_info = 1;
// result is the result of the simulation.
cosmos.base.abci.v1beta1.Result result = 2;
}

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package cosmos.base.snapshots.v1beta1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/snapshots/types";
// Snapshot contains Tendermint state sync snapshot info.
message Snapshot {
uint64 height = 1;
uint32 format = 2;
uint32 chunks = 3;
bytes hash = 4;
Metadata metadata = 5 [ (gogoproto.nullable) = false ];
}
// Metadata contains SDK-specific snapshot metadata.
message Metadata {
repeated bytes chunk_hashes = 1; // SHA-256 chunk hashes
}

View File

@ -0,0 +1,29 @@
syntax = "proto3";
package cosmos.base.store.v1beta1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/store/types";
// CommitInfo defines commit information used by the multi-store when committing
// a version/height.
message CommitInfo {
int64 version = 1;
repeated StoreInfo store_infos = 2 [ (gogoproto.nullable) = false ];
}
// StoreInfo defines store-specific commit information. It contains a reference
// between a store name and the commit ID.
message StoreInfo {
string name = 1;
CommitID commit_id = 2 [ (gogoproto.nullable) = false ];
}
// CommitID defines the committment information when a specific store is
// committed.
message CommitID {
option (gogoproto.goproto_stringer) = false;
int64 version = 1;
bytes hash = 2;
}

View File

@ -0,0 +1,26 @@
syntax = "proto3";
package cosmos.base.store.v1beta1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/store/types";
// SnapshotItem is an item contained in a rootmulti.Store snapshot.
message SnapshotItem {
// item is the specific type of snapshot item.
oneof item {
SnapshotStoreItem store = 1;
SnapshotIAVLItem iavl = 2 [ (gogoproto.customname) = "IAVL" ];
}
}
// SnapshotStoreItem contains metadata about a snapshotted store.
message SnapshotStoreItem { string name = 1; }
// SnapshotIAVLItem is an exported IAVL node.
message SnapshotIAVLItem {
bytes key = 1;
bytes value = 2;
int64 version = 3;
int32 height = 4;
}

View File

@ -0,0 +1,44 @@
syntax = "proto3";
package cosmos.base.v1beta1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/types";
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = false;
// Coin defines a token with a denomination and an amount.
//
// NOTE: The amount field is an Int which implements the custom method
// signatures required by gogoproto.
message Coin {
option (gogoproto.equal) = true;
string denom = 1;
string amount = 2
[ (gogoproto.customtype) = "Int", (gogoproto.nullable) = false ];
}
// DecCoin defines a token with a denomination and a decimal amount.
//
// NOTE: The amount field is an Dec which implements the custom method
// signatures required by gogoproto.
message DecCoin {
option (gogoproto.equal) = true;
string denom = 1;
string amount = 2
[ (gogoproto.customtype) = "Dec", (gogoproto.nullable) = false ];
}
// IntProto defines a Protobuf wrapper around an Int object.
message IntProto {
string int = 1
[ (gogoproto.customtype) = "Int", (gogoproto.nullable) = false ];
}
// DecProto defines a Protobuf wrapper around a Dec object.
message DecProto {
string dec = 1
[ (gogoproto.customtype) = "Dec", (gogoproto.nullable) = false ];
}

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package cosmos.crypto.ed25519;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519";
// PubKey defines a ed25519 public key
// Key is the compressed form of the pubkey. The first byte depends is a 0x02
// byte if the y-coordinate is the lexicographically largest of the two
// associated with the x-coordinate. Otherwise the first byte is a 0x03. This
// prefix is followed with the x-coordinate.
message PubKey {
option (gogoproto.goproto_stringer) = false;
bytes key = 1;
}
// PrivKey defines a ed25519 private key.
message PrivKey { bytes key = 1; }

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package cosmos.crypto.multisig;
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/multisig";
// LegacyAminoPubKey specifies a public key type
// which nests multiple public keys and a threshold,
// it uses legacy amino address rules.
message LegacyAminoPubKey {
option (gogoproto.goproto_getters) = false;
uint32 threshold = 1 [ (gogoproto.moretags) = "yaml:\"threshold\"" ];
repeated google.protobuf.Any public_keys = 2 [
(gogoproto.customname) = "PubKeys",
(gogoproto.moretags) = "yaml:\"pubkeys\""
];
}

Some files were not shown because too many files have changed in this diff Show More