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
UseTab: Never
...

View File

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

View File

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

1
.gitignore vendored
View File

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

View File

@ -71,6 +71,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
### 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.
### 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
### API Breaking
@ -227,6 +230,11 @@ corresponding Ethereum API namespace:
### 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.
* (`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:

View File

@ -25,7 +25,6 @@ WORKDIR /root
# 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/ethermintcli /usr/bin/ethermintcli
# Run ethermintd by default
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')
DOCKER_TAG = unstable
DOCKER_IMAGE = cosmos/ethermint
ETHERMINT_DAEMON_BINARY = ethermintd
ETHERMINT_CLI_BINARY = ethermintcli
DOCKER_BUF := docker run -v $(shell pwd):/workspace --workdir /workspace bufbuild/buf
ETHERMINT_BINARY = ethermintd
ETHERMINT_DIR = ethermint
GO_MOD=GO111MODULE=on
BUILDDIR ?= $(CURDIR)/build
SIMAPP = ./app
@ -34,7 +35,7 @@ ifeq ($(OS),Windows_NT)
DETECTED_OS := windows
else
UNAME_S = $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
ifeq ($(UNAME_S),Darwin)
DETECTED_OS := mac
else
DETECTED_OS := linux
@ -106,8 +107,7 @@ build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags))
# process linker flags
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.ClientName=$(ETHERMINT_CLI_BINARY) \
-X github.com/cosmos/cosmos-sdk/version.AppName=$(ETHERMINT_BINARY) \
-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.BuildTags=$(build_tags_comma_sep)"
@ -129,17 +129,14 @@ all: tools verify install
build: go.sum
ifeq ($(OS), Windows_NT)
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_DAEMON_BINARY).exe ./cmd/$(ETHERMINT_DAEMON_BINARY)
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_CLI_BINARY).exe ./cmd/$(ETHERMINT_CLI_BINARY)
go build $(BUILD_FLAGS) -o build/$(ETHERMINT_BINARY).exe ./cmd/$(ETHERMINT_BINARY)
else
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_DAEMON_BINARY) ./cmd/$(ETHERMINT_DAEMON_BINARY)
go build -mod=readonly $(BUILD_FLAGS) -o build/$(ETHERMINT_CLI_BINARY) ./cmd/$(ETHERMINT_CLI_BINARY)
go build $(BUILD_FLAGS) -o build/$(ETHERMINT_BINARY) ./cmd/$(ETHERMINT_BINARY)
endif
build-ethermint: go.sum
mkdir -p $(BUILDDIR)
go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR) ./cmd/$(ETHERMINT_DAEMON_BINARY)
go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR) ./cmd/$(ETHERMINT_CLI_BINARY)
go build $(BUILD_FLAGS) -o $(BUILDDIR) ./cmd/$(ETHERMINT_BINARY)
build-ethermint-linux: go.sum
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
install:
${GO_MOD} go install $(BUILD_FLAGS) ./cmd/$(ETHERMINT_DAEMON_BINARY)
${GO_MOD} go install $(BUILD_FLAGS) ./cmd/$(ETHERMINT_CLI_BINARY)
${GO_MOD} go install $(BUILD_FLAGS) ./cmd/$(ETHERMINT_BINARY)
clean:
@rm -rf ./build ./vendor
@ -165,8 +161,7 @@ docker-build:
docker create --name ethermint -t -i cosmos/ethermint:latest ethermint
# move the binaries to the ./build directory
mkdir -p ./build/
docker cp ethermint:/usr/bin/ethermintd ./build/ ; \
docker cp ethermint:/usr/bin/ethermintcli ./build/
docker cp ethermint:/usr/bin/ethermintd ./build/
docker-localnet:
docker build -f ./networks/local/ethermintnode/Dockerfile . -t ethermintd/node
@ -186,40 +181,47 @@ RUNSIM = $(TOOLS_DESTDIR)/runsim
runsim: $(RUNSIM)
$(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:
ifeq (, $(shell which stringer))
@echo "Installing stringer..."
@go install golang.org/x/tools/cmd/stringer
@go get golang.org/x/tools/cmd/stringer
else
@echo "stringer already installed; skipping..."
endif
ifeq (, $(shell which 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
@echo "go-bindata already installed; skipping..."
endif
ifeq (, $(shell which gencodec))
@echo "Installing gencodec..."
@go install github.com/fjl/gencodec
@go get github.com/fjl/gencodec
else
@echo "gencodec already installed; skipping..."
endif
ifeq (, $(shell which 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
@echo "protoc-gen-go already installed; skipping..."
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))
@echo "Installing solcjs..."
@apt-get install -f -y protobuf-compiler
@npm install -g solc@0.5.11
else
@echo "solcjs already installed; skipping..."
@ -234,7 +236,7 @@ else
endif
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
# rebuilding when this Makefile target is hit twice
# in a row.
@ -250,7 +252,7 @@ docs-tools-stamp: docs-tools
# in a row.
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 ###
@ -270,10 +272,10 @@ test-import:
rm -rf importer/tmp
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:
./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:
@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:
@echo "Running custom genesis simulation..."
@echo "By default, ${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json will be used."
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json \
@echo "By default, ${HOME}/.$(ETHERMINT_DIR)/config/genesis.json will be used."
@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
test-sim-import-export: runsim
@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
@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
@echo "Running multi-seed custom genesis simulation..."
@echo "By default, ${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json will be used."
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail -Genesis=${HOME}/.$(ETHERMINT_DAEMON_BINARY)/config/genesis.json 400 5 TestFullAppSimulation
@echo "By default, ${HOME}/.$(ETHERMINT_DIR)/config/genesis.json will be used."
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail -Genesis=${HOME}/.$(ETHERMINT_DIR)/config/genesis.json 400 5 TestFullAppSimulation
test-sim-multi-seed-long: runsim
@echo "Running multi-seed application simulation. This may take awhile!"
@ -359,13 +361,19 @@ proto-format:
proto-swagger-gen:
@./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:
@$(DOCKER_BUF) check lint --error-format=json
proto-check-breaking:
@$(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
COSMOS_SDK_URL = https://raw.githubusercontent.com/cosmos/cosmos-sdk/master
COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master
@ -437,13 +445,13 @@ ifeq ($(OS),Windows_NT)
mkdir build &
@$(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
else
mkdir -p ./build/
@$(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
endif

View File

@ -1,23 +1,22 @@
package ante
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"
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"
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/types"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
)
func init() {
ethsecp256k1.RegisterCodec(types.ModuleCdc)
}
const (
// TODO: Use this cost per byte through parameter or overriding NewConsumeGasForTxSizeDecorator
// which currently defaults at 10, if intended
@ -25,43 +24,61 @@ const (
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
// Ethereum or SDK transaction to an internal ante handler for performing
// transaction-level processing (e.g. fee payment, signature verification) before
// 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(
ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) {
var anteHandler sdk.AnteHandler
switch tx.(type) {
case auth.StdTx:
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:
case *evmtypes.MsgEthereumTx:
anteHandler = sdk.ChainAnteDecorators(
NewEthSetupContextDecorator(), // outermost AnteDecorator. EthSetUpContext must be called first
authante.NewRejectExtensionOptionsDecorator(),
NewEthMempoolFeeDecorator(evmKeeper),
authante.NewValidateBasicDecorator(),
NewEthSigVerificationDecorator(),
NewAccountVerificationDecorator(ak, evmKeeper),
NewAccountVerificationDecorator(ak, bankKeeper, evmKeeper),
NewNonceVerificationDecorator(ak),
NewEthGasConsumeDecorator(ak, sk, evmKeeper),
NewEthGasConsumeDecorator(ak, bankKeeper, evmKeeper),
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:
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
// module on the SDK. It doesn't allow ed25519 nor multisig thresholds.
func sigGasConsumer(
meter sdk.GasMeter, _ []byte, pubkey tmcrypto.PubKey, _ types.Params,
var _ = DefaultSigVerificationGasConsumer
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
// 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 {
switch pubkey.(type) {
case ethsecp256k1.PubKey:
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: secp256k1")
pubkey := sig.PubKey
switch pubkey := pubkey.(type) {
case *ed25519.PubKey:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")
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
default:
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"
abci "github.com/tendermint/tendermint/abci/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/app"
@ -42,12 +42,14 @@ func (suite *AnteTestSuite) TestValidEthTx() {
addr2, _ := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
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.SetCoins(newTestCoins())
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
to := ethcmn.BytesToAddress(addr2.Bytes())
@ -60,32 +62,35 @@ func (suite *AnteTestSuite) TestValidEthTx() {
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)
addr1, priv1 := newTestAddrKey()
addr2, priv2 := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
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.SetCoins(newTestCoins())
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
fee := newTestStdFee()
msg1 := newTestMsg(addr1, addr2)
msgs := []sdk.Msg{msg1}
privKeys := []tmcrypto.PrivKey{priv1, priv2}
privKeys := []cryptotypes.PrivKey{priv1, priv2}
accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()}
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() {
@ -96,12 +101,14 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
addr3, priv3 := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
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.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc2)
err = suite.app.BankKeeper.SetBalances(suite.ctx, acc2.GetAddress(), newTestCoins())
suite.Require().NoError(err)
fee := newTestStdFee()
msg1 := newTestMsg(addr1, addr2)
@ -109,7 +116,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
// require validation failure with no signers
msgs := []sdk.Msg{msg1}
privKeys := []tmcrypto.PrivKey{}
privKeys := []cryptotypes.PrivKey{}
accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()}
@ -119,7 +126,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
// require validation failure with invalid number of signers
msgs = []sdk.Msg{msg1}
privKeys = []tmcrypto.PrivKey{priv1}
privKeys = []cryptotypes.PrivKey{priv1}
accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence()}
@ -130,7 +137,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
msg2 := newTestMsg(addr1, addr3)
msgs = []sdk.Msg{msg1, msg2}
privKeys = []tmcrypto.PrivKey{priv1, priv2, priv3}
privKeys = []cryptotypes.PrivKey{priv1, priv2, priv3}
accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber(), 0}
accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence(), 0}
@ -144,13 +151,14 @@ func (suite *AnteTestSuite) TestSDKInvalidAcc() {
addr1, priv1 := newTestAddrKey()
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc1.SetCoins(newTestCoins())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc1)
err := suite.app.BankKeeper.SetBalances(suite.ctx, acc1.GetAddress(), newTestCoins())
suite.Require().NoError(err)
fee := newTestStdFee()
msg1 := newTestMsg(addr1)
msgs := []sdk.Msg{msg1}
privKeys := []tmcrypto.PrivKey{priv1}
privKeys := []cryptotypes.PrivKey{priv1}
// require validation failure with invalid account number
accNums := []uint64{1}
@ -194,8 +202,9 @@ func (suite *AnteTestSuite) TestEthInvalidNonce() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
err := acc.SetSequence(10)
suite.Require().NoError(err)
_ = acc.SetCoins(newTestCoins())
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
to := ethcmn.BytesToAddress(addr2.Bytes())
@ -235,8 +244,9 @@ func (suite *AnteTestSuite) TestEthInvalidIntrinsicGas() {
addr2, _ := newTestAddrKey()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc.SetCoins(newTestCoins())
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
to := ethcmn.BytesToAddress(addr2.Bytes())
@ -253,17 +263,18 @@ func (suite *AnteTestSuite) TestEthInvalidIntrinsicGas() {
func (suite *AnteTestSuite) TestEthInvalidMempoolFees() {
// setup app with checkTx = 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.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))))
addr1, priv1 := newTestAddrKey()
addr2, _ := newTestAddrKey()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc.SetCoins(newTestCoins())
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
to := ethcmn.BytesToAddress(addr2.Bytes())
@ -283,8 +294,9 @@ func (suite *AnteTestSuite) TestEthInvalidChainID() {
addr2, _ := newTestAddrKey()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr1)
_ = acc.SetCoins(newTestCoins())
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
to := ethcmn.BytesToAddress(addr2.Bytes())

View File

@ -6,9 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/types"
ethermint "github.com/cosmos/ethermint/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)
}
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx)
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
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
// 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()
minFees := minGasPrices.AmountOf(evmDenom).MulInt64(int64(msgEthTx.Data.GasLimit))
@ -134,7 +132,7 @@ func NewEthSigVerificationDecorator() EthSigVerificationDecorator {
// 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) {
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx)
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
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
type AccountVerificationDecorator struct {
ak auth.AccountKeeper
evmKeeper EVMKeeper
ak AccountKeeper
bankKeeper BankKeeper
evmKeeper EVMKeeper
}
// NewAccountVerificationDecorator creates a new AccountVerificationDecorator
func NewAccountVerificationDecorator(ak auth.AccountKeeper, ek EVMKeeper) AccountVerificationDecorator {
func NewAccountVerificationDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKeeper) AccountVerificationDecorator {
return AccountVerificationDecorator{
ak: ak,
evmKeeper: ek,
ak: ak,
bankKeeper: bankKeeper,
evmKeeper: ek,
}
}
@ -177,13 +177,13 @@ func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
return next(ctx, tx, simulate)
}
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx)
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
}
// sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.From()
address := msgEthTx.GetFrom()
if address.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
// validate sender has enough funds to pay for gas cost
balance := acc.GetCoins().AmountOf(evmDenom)
if balance.BigInt().Cmp(msgEthTx.Cost()) < 0 {
balance := avd.bankKeeper.GetBalance(ctx, address, evmDenom)
if balance.Amount.BigInt().Cmp(msgEthTx.Cost()) < 0 {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"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
// the sender account sequence.
type NonceVerificationDecorator struct {
ak auth.AccountKeeper
ak AccountKeeper
}
// NewNonceVerificationDecorator creates a new NonceVerificationDecorator
func NewNonceVerificationDecorator(ak auth.AccountKeeper) NonceVerificationDecorator {
func NewNonceVerificationDecorator(ak AccountKeeper) NonceVerificationDecorator {
return NonceVerificationDecorator{
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
// current nonce).
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 {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
}
// sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.From()
address := msgEthTx.GetFrom()
if address.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
// gas consumption.
type EthGasConsumeDecorator struct {
ak auth.AccountKeeper
sk types.SupplyKeeper
evmKeeper EVMKeeper
ak AccountKeeper
bankKeeper BankKeeper
evmKeeper EVMKeeper
}
// 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{
ak: ak,
sk: sk,
evmKeeper: ek,
ak: ak,
bankKeeper: bankKeeper,
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
// supplied with the transaction.
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 {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
}
// sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.From()
address := msgEthTx.GetFrom()
if address.Empty() {
panic("sender address cannot be empty")
}
// fetch sender account from signature
senderAcc, err := auth.GetSignerAcc(ctx, egcd.ak, address)
senderAcc, err := authante.GetSignerAcc(ctx, egcd.ak, address)
if err != nil {
return ctx, err
}
@ -336,14 +336,14 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
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 {
return ctx, err
}
}
// 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)
}
@ -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.
type IncrementSenderSequenceDecorator struct {
ak auth.AccountKeeper
ak AccountKeeper
}
// NewIncrementSenderSequenceDecorator creates a new IncrementSenderSequenceDecorator.
func NewIncrementSenderSequenceDecorator(ak auth.AccountKeeper) IncrementSenderSequenceDecorator {
func NewIncrementSenderSequenceDecorator(ak AccountKeeper) IncrementSenderSequenceDecorator {
return IncrementSenderSequenceDecorator{
ak: ak,
}
@ -370,7 +370,7 @@ func (issd IncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.
gasMeter := ctx.GasMeter()
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
msgEthTx, ok := tx.(evmtypes.MsgEthereumTx)
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
ctx = ctx.WithGasMeter(gasMeter)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)

View File

@ -1,14 +1,16 @@
package ante_test
import (
"fmt"
"testing"
"time"
"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"
"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"
ante "github.com/cosmos/ethermint/app/ante"
@ -16,50 +18,56 @@ import (
ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
abci "github.com/tendermint/tendermint/abci/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
type AnteTestSuite struct {
suite.Suite
ctx sdk.Context
app *app.EthermintApp
anteHandler sdk.AnteHandler
ctx sdk.Context
app *app.EthermintApp
encodingConfig params.EncodingConfig
anteHandler sdk.AnteHandler
}
func (suite *AnteTestSuite) SetupTest() {
checkTx := false
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.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) {
suite.Run(t, new(AnteTestSuite))
}
func newTestMsg(addrs ...sdk.AccAddress) *sdk.TestMsg {
return sdk.NewTestMsg(addrs...)
func newTestMsg(addrs ...sdk.AccAddress) *testdata.TestMsg {
return testdata.NewTestMsg(addrs...)
}
func newTestCoins() sdk.Coins {
return sdk.NewCoins(ethermint.NewPhotonCoinInt64(500000000))
}
func newTestStdFee() auth.StdFee {
return auth.NewStdFee(220000, sdk.NewCoins(ethermint.NewPhotonCoinInt64(150)))
func newTestStdFee() legacytx.StdFee {
return legacytx.NewStdFee(220000, sdk.NewCoins(ethermint.NewPhotonCoinInt64(150)))
}
// GenerateAddress generates an Ethereum address.
func newTestAddrKey() (sdk.AccAddress, tmcrypto.PrivKey) {
func newTestAddrKey() (sdk.AccAddress, cryptotypes.PrivKey) {
privkey, _ := ethsecp256k1.GenerateKey()
addr := ethcrypto.PubkeyToAddress(privkey.ToECDSA().PublicKey)
@ -67,38 +75,35 @@ func newTestAddrKey() (sdk.AccAddress, tmcrypto.PrivKey) {
}
func newTestSDKTx(
ctx sdk.Context, msgs []sdk.Msg, privs []tmcrypto.PrivKey,
accNums []uint64, seqs []uint64, fee auth.StdFee,
ctx sdk.Context, msgs []sdk.Msg, privs []cryptotypes.PrivKey,
accNums []uint64, seqs []uint64, fee legacytx.StdFee,
) sdk.Tx {
sigs := make([]auth.StdSignature, len(privs))
sigs := make([]legacytx.StdSignature, len(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)
if err != nil {
panic(err)
}
sigs[i] = auth.StdSignature{
sigs[i] = legacytx.StdSignature{
PubKey: priv.PubKey(),
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())
if err != nil {
return nil, err
}
privkey, ok := priv.(ethsecp256k1.PrivKey)
if !ok {
return nil, fmt.Errorf("invalid private key type: %T", priv)
}
privkey := &ethsecp256k1.PrivKey{Key: priv.Bytes()}
if err := msg.Sign(chainIDEpoch, privkey.ToECDSA()); err != nil {
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 (
"io"
"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/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"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
"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"
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"
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"
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"
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"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"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"
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"
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"
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/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"
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"
ethermintcodec "github.com/cosmos/ethermint/codec"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
dbm "github.com/tendermint/tm-db"
evmrest "github.com/cosmos/ethermint/x/evm/client/rest"
evmkeeper "github.com/cosmos/ethermint/x/evm/keeper"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
)
func init() {
@ -42,93 +99,113 @@ func init() {
config := sdk.GetConfig()
ethermint.SetBech32Prefixes(config)
ethermint.SetBip44CoinType(config)
userHomeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
DefaultNodeHome = filepath.Join(userHomeDir, ".ethermint")
}
const appName = "Ethermint"
var (
// DefaultCLIHome sets the default home directories for the application CLI
DefaultCLIHome = os.ExpandEnv("$HOME/.ethermintcli")
// DefaultNodeHome sets the folder where the applcation data and configuration will be stored
DefaultNodeHome = os.ExpandEnv("$HOME/.ethermintd")
// DefaultNodeHome default home directories for the application daemon
DefaultNodeHome string
// ModuleBasics defines the module BasicManager is in charge of setting up basic,
// non-dependant module elements, such as codec registration
// and genesis verification.
ModuleBasics = module.NewBasicManager(
auth.AppModuleBasic{},
supply.AppModuleBasic{},
genutil.AppModuleBasic{},
bank.AppModuleBasic{},
capability.AppModuleBasic{},
staking.AppModuleBasic{},
mint.AppModuleBasic{},
distr.AppModuleBasic{},
gov.NewAppModuleBasic(
paramsclient.ProposalHandler, distr.ProposalHandler, upgradeclient.ProposalHandler,
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
),
params.AppModuleBasic{},
crisis.AppModuleBasic{},
slashing.AppModuleBasic{},
evidence.AppModuleBasic{},
ibc.AppModuleBasic{},
upgrade.AppModuleBasic{},
evidence.AppModuleBasic{},
transfer.AppModuleBasic{},
vesting.AppModuleBasic{},
evm.AppModuleBasic{},
)
// module account permissions
maccPerms = map[string][]string{
auth.FeeCollectorName: nil,
distr.ModuleName: nil,
mint.ModuleName: {supply.Minter},
staking.BondedPoolName: {supply.Burner, supply.Staking},
staking.NotBondedPoolName: {supply.Burner, supply.Staking},
gov.ModuleName: {supply.Burner},
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
}
// module accounts that are allowed to receive tokens
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
// that may process transactions through Ethereum's EVM running atop of
// Tendermint consensus.
type EthermintApp struct {
*bam.BaseApp
cdc *codec.Codec
*baseapp.BaseApp
cdc *codec.LegacyAmino
appCodec codec.Marshaler
interfaceRegistry types.InterfaceRegistry
invCheckPeriod uint
// keys to access the substores
keys map[string]*sdk.KVStoreKey
tkeys map[string]*sdk.TransientStoreKey
// subspaces
subspaces map[string]params.Subspace
keys map[string]*sdk.KVStoreKey
tkeys map[string]*sdk.TransientStoreKey
memKeys map[string]*sdk.MemoryStoreKey
// keepers
AccountKeeper auth.AccountKeeper
BankKeeper bank.Keeper
SupplyKeeper supply.Keeper
StakingKeeper staking.Keeper
SlashingKeeper slashing.Keeper
MintKeeper mint.Keeper
DistrKeeper distr.Keeper
GovKeeper gov.Keeper
CrisisKeeper crisis.Keeper
UpgradeKeeper upgrade.Keeper
ParamsKeeper params.Keeper
EvidenceKeeper evidence.Keeper
EvmKeeper *evm.Keeper
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
CapabilityKeeper *capabilitykeeper.Keeper
StakingKeeper stakingkeeper.Keeper
SlashingKeeper slashingkeeper.Keeper
MintKeeper mintkeeper.Keeper
DistrKeeper distrkeeper.Keeper
GovKeeper govkeeper.Keeper
CrisisKeeper crisiskeeper.Keeper
UpgradeKeeper upgradekeeper.Keeper
ParamsKeeper paramskeeper.Keeper
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
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
mm *module.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.
@ -138,181 +215,267 @@ func NewEthermintApp(
traceStore io.Writer,
loadLatest bool,
skipUpgradeHeights map[int64]bool,
homePath string,
invCheckPeriod uint,
baseAppOptions ...func(*bam.BaseApp),
encodingConfig simappparams.EncodingConfig,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *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
bApp := bam.NewBaseApp(appName, logger, db, evm.TxDecoder(cdc), baseAppOptions...)
bApp := baseapp.NewBaseApp(
appName,
logger,
db,
encodingConfig.TxConfig.TxDecoder(),
baseAppOptions...,
)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetAppVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
keys := sdk.NewKVStoreKeys(
bam.MainStoreKey, auth.StoreKey, staking.StoreKey,
supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey,
gov.StoreKey, params.StoreKey, upgrade.StoreKey, evidence.StoreKey,
evm.StoreKey,
// SDK keys
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.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{
BaseApp: bApp,
cdc: cdc,
invCheckPeriod: invCheckPeriod,
keys: keys,
tkeys: tkeys,
subspaces: make(map[string]params.Subspace),
BaseApp: bApp,
cdc: cdc,
appCodec: appCodec,
interfaceRegistry: interfaceRegistry,
invCheckPeriod: invCheckPeriod,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
// init params keeper and subspaces
app.ParamsKeeper = params.NewKeeper(cdc, keys[params.StoreKey], tkeys[params.TStoreKey])
app.subspaces[auth.ModuleName] = app.ParamsKeeper.Subspace(auth.DefaultParamspace)
app.subspaces[bank.ModuleName] = app.ParamsKeeper.Subspace(bank.DefaultParamspace)
app.subspaces[staking.ModuleName] = app.ParamsKeeper.Subspace(staking.DefaultParamspace)
app.subspaces[mint.ModuleName] = app.ParamsKeeper.Subspace(mint.DefaultParamspace)
app.subspaces[distr.ModuleName] = app.ParamsKeeper.Subspace(distr.DefaultParamspace)
app.subspaces[slashing.ModuleName] = app.ParamsKeeper.Subspace(slashing.DefaultParamspace)
app.subspaces[gov.ModuleName] = app.ParamsKeeper.Subspace(gov.DefaultParamspace).WithKeyTable(gov.ParamKeyTable())
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)
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
// set the BaseApp's parameter store
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()))
// add capability keeper and ScopeToModule for ibc module
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName)
// use custom Ethermint account for contracts
app.AccountKeeper = auth.NewAccountKeeper(
cdc, keys[auth.StoreKey], app.subspaces[auth.ModuleName], ethermint.ProtoAccount,
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
)
app.BankKeeper = bank.NewBaseKeeper(
app.AccountKeeper, app.subspaces[bank.ModuleName], app.BlacklistedAccAddrs(),
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
)
app.SupplyKeeper = supply.NewKeeper(
cdc, keys[supply.StoreKey], app.AccountKeeper, app.BankKeeper, maccPerms,
stakingKeeper := stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
)
stakingKeeper := staking.NewKeeper(
cdc, keys[staking.StoreKey], app.SupplyKeeper, app.subspaces[staking.ModuleName],
app.MintKeeper = mintkeeper.NewKeeper(
appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
)
app.MintKeeper = mint.NewKeeper(
cdc, keys[mint.StoreKey], app.subspaces[mint.ModuleName], &stakingKeeper,
app.SupplyKeeper, auth.FeeCollectorName,
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
)
app.DistrKeeper = distr.NewKeeper(
cdc, keys[distr.StoreKey], app.subspaces[distr.ModuleName], &stakingKeeper,
app.SupplyKeeper, auth.FeeCollectorName, app.ModuleAccountAddrs(),
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
)
app.SlashingKeeper = slashing.NewKeeper(
cdc, keys[slashing.StoreKey], &stakingKeeper, app.subspaces[slashing.ModuleName],
)
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.CrisisKeeper = crisiskeeper.NewKeeper(
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
)
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath)
// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
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
// must be passed by reference here.
app.mm = module.NewManager(
genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx),
auth.NewAppModule(app.AccountKeeper),
bank.NewAppModule(app.BankKeeper, app.AccountKeeper),
crisis.NewAppModule(&app.CrisisKeeper),
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper),
gov.NewAppModule(app.GovKeeper, app.AccountKeeper, app.SupplyKeeper),
mint.NewAppModule(app.MintKeeper),
slashing.NewAppModule(app.SlashingKeeper, app.AccountKeeper, app.StakingKeeper),
distr.NewAppModule(app.DistrKeeper, app.AccountKeeper, app.SupplyKeeper, app.StakingKeeper),
staking.NewAppModule(app.StakingKeeper, app.AccountKeeper, app.SupplyKeeper),
// SDK app modules
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
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),
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
// there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant.
// NOTE: upgrade module must go first to handle software upgrades.
// NOTE: staking module is required if HistoricalEntries param > 0.
app.mm.SetOrderBeginBlockers(
evm.ModuleName, mint.ModuleName, distr.ModuleName, slashing.ModuleName,
evidence.ModuleName,
upgradetypes.ModuleName,
evmtypes.ModuleName,
minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName,
)
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
// 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(
auth.ModuleName, distr.ModuleName, staking.ModuleName, bank.ModuleName,
slashing.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName,
evm.ModuleName, crisis.ModuleName, genutil.ModuleName, evidence.ModuleName,
// SDK modules
capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.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.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
//
// NOTE: this is not required apps that don't use the simulator for fuzz testing
// transactions
app.sm = module.NewSimulationManager(
auth.NewAppModule(app.AccountKeeper),
bank.NewAppModule(app.BankKeeper, app.AccountKeeper),
supply.NewAppModule(app.SupplyKeeper, app.AccountKeeper),
gov.NewAppModule(app.GovKeeper, app.AccountKeeper, app.SupplyKeeper),
mint.NewAppModule(app.MintKeeper),
staking.NewAppModule(app.StakingKeeper, app.AccountKeeper, app.SupplyKeeper),
distr.NewAppModule(app.DistrKeeper, app.AccountKeeper, app.SupplyKeeper, app.StakingKeeper),
slashing.NewAppModule(app.SlashingKeeper, app.AccountKeeper, app.StakingKeeper),
params.NewAppModule(), // NOTE: only used for simulation to generate randomized param change proposals
)
// app.sm = module.NewSimulationManager(
// auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
// bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
// capability.NewAppModule(appCodec, *app.CapabilityKeeper),
// gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
// mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
// staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
// distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
// slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
// params.NewAppModule(app.ParamsKeeper),
// evidence.NewAppModule(app.EvidenceKeeper),
// ibc.NewAppModule(app.IBCKeeper),
// transferModule,
//)
app.sm.RegisterStoreDecoders()
// app.sm.RegisterStoreDecoders()
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)
// initialize BaseApp
app.SetInitChainer(app.InitChainer)
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)
if loadLatest {
err := app.LoadLatestVersion(app.keys[bam.MainStoreKey])
if err != nil {
if err := app.LoadLatestVersion(); err != nil {
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
}
@ -332,38 +495,57 @@ func (app *EthermintApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) a
// InitChainer updates at chain initialization
func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
var genesisState simapp.GenesisState
app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState)
return app.mm.InitGenesis(ctx, genesisState)
if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
panic(err)
}
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
}
// LoadHeight loads state at a particular height
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.
func (app *EthermintApp) ModuleAccountAddrs() map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range maccPerms {
modAccAddrs[supply.NewModuleAddress(acc).String()] = true
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
return modAccAddrs
}
// BlacklistedAccAddrs returns all the app's module account addresses black listed for receiving tokens.
func (app *EthermintApp) BlacklistedAccAddrs() map[string]bool {
blacklistedAddrs := make(map[string]bool)
// BlockedAddrs returns all the app's module account addresses that are not
// allowed to receive external tokens.
func (app *EthermintApp) BlockedAddrs() map[string]bool {
blockedAddrs := make(map[string]bool)
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
func (app *EthermintApp) SimulationManager() *module.SimulationManager {
return app.sm
// LegacyAmino returns EthermintApp's amino 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) 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.
@ -373,12 +555,57 @@ func (app *EthermintApp) GetKey(storeKey string) *sdk.KVStoreKey {
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
// for modules to register their own custom testing types.
func (app *EthermintApp) Codec() *codec.Codec {
return app.cdc
// NOTE: This is solely to be used for testing purposes.
func (app *EthermintApp) GetTKey(storeKey string) *sdk.TransientStoreKey {
return app.tkeys[storeKey]
}
// 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
@ -390,3 +617,25 @@ func GetMaccPerms() map[string][]string {
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
import (
"encoding/json"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/simapp"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/codec"
)
func TestEthermintAppExport(t *testing.T) {
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()
stateBytes, err := codec.MarshalJSONIndent(app.cdc, genesisState)
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)
// Initialize the chain
@ -31,7 +32,7 @@ func TestEthermintAppExport(t *testing.T) {
app.Commit()
// 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)
_, _, err = app2.ExportAppStateAndValidators(false, []string{})
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, MakeEncodingConfig(), simapp.EmptyAppOptions{})
_, err = app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}

View File

@ -2,70 +2,81 @@ package app
import (
"encoding/json"
"log"
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp"
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/exported"
ethcdc "github.com/cosmos/ethermint/codec"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
// NewDefaultGenesisState generates the default state for the application.
func NewDefaultGenesisState() simapp.GenesisState {
_ = ethcdc.MakeCodec(ModuleBasics)
return ModuleBasics.DefaultGenesis()
encCfg := MakeEncodingConfig()
return ModuleBasics.DefaultGenesis(encCfg.Marshaler)
}
// ExportAppStateAndValidators exports the state of the application for a genesis
// file.
func (app *EthermintApp) ExportAppStateAndValidators(
forZeroHeight bool, jailWhiteList []string,
) (appState json.RawMessage, validators []tmtypes.GenesisValidator, err error) {
forZeroHeight bool, jailAllowedAddrs []string,
) (servertypes.ExportedApp, error) {
// 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 {
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)
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
genState := app.mm.ExportGenesis(ctx, app.appCodec)
appState, err := json.MarshalIndent(genState, "", " ")
if err != nil {
return nil, nil, err
return servertypes.ExportedApp{}, err
}
// Write validators to staking module to be used by TM node
validators = staking.WriteValidators(ctx, app.StakingKeeper)
return appState, validators, nil
validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
if err != 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
// NOTE zero height genesis is a temporary feature which will be deprecated
// in favour of export at a block height
func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) {
applyWhiteList := false
func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) error {
applyAllowedAddrs := false
//Check if there is a whitelist
if len(jailWhiteList) > 0 {
applyWhiteList = true
// check if there is a allowed address list
if len(jailAllowedAddrs) > 0 {
applyAllowedAddrs = true
}
whiteListMap := make(map[string]bool)
allowedAddrsMap := make(map[string]bool)
for _, addr := range jailWhiteList {
for _, addr := range jailAllowedAddrs {
_, err := sdk.ValAddressFromBech32(addr)
if err != nil {
log.Fatal(err)
return err
}
whiteListMap[addr] = true
allowedAddrsMap[addr] = true
}
/* 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. */
// 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())
return false
})
@ -82,7 +93,16 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
// withdraw all delegator rewards
dels := app.StakingKeeper.GetAllDelegations(ctx)
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
@ -96,7 +116,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
ctx = ctx.WithBlockHeight(0)
// 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
scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator())
feePool := app.DistrKeeper.GetFeePool(ctx)
@ -109,8 +129,16 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
// reinitialize all delegations
for _, del := range dels {
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, del.DelegatorAddress, del.ValidatorAddress)
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, del.DelegatorAddress, del.ValidatorAddress)
valAddr, err := sdk.ValAddressFromBech32(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
@ -119,7 +147,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
/* Handle staking state. */
// 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 {
red.Entries[i].CreationHeight = 0
}
@ -128,7 +156,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
})
// 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 {
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
// update bond intra-tx counters.
store := ctx.KVStore(app.keys[staking.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, staking.ValidatorsKey)
store := ctx.KVStore(app.keys[stakingtypes.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
counter := int16(0)
for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(iter.Key()[1:])
validator, found := app.StakingKeeper.GetValidator(ctx, addr)
if !found {
panic("expected validator, not found")
return fmt.Errorf("expected validator %s not found", addr)
}
validator.UnbondingHeight = 0
if applyWhiteList && !whiteListMap[addr.String()] {
if applyAllowedAddrs && !allowedAddrsMap[addr.String()] {
validator.Jailed = true
}
@ -160,17 +188,20 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList
iter.Close()
_ = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil {
return err
}
/* Handle slashing state. */
// reset start height on signing infos
app.SlashingKeeper.IterateValidatorSigningInfos(
ctx,
func(addr sdk.ConsAddress, info slashing.ValidatorSigningInfo) (stop bool) {
func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) {
info.StartHeight = 0
app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
return false
},
)
return nil
}

View File

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

View File

@ -49,7 +49,7 @@ func ValidateChainID(baseCmd *cobra.Command) *cobra.Command {
// Function to replace command's RunE function
validateFn := func(cmd *cobra.Command, args []string) error {
chainID := viper.GetString(flags.FlagChainID)
chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
if !ethermint.IsValidChainID(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
generateFn := func(cmd *cobra.Command, args []string) error {
chainID := viper.GetString(flags.FlagChainID)
chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
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)
}

View File

@ -6,15 +6,16 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/ethereum/go-ethereum/common/hexutil"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/cosmos-sdk/client/flags"
"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"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/crypto/hd"
)
@ -29,12 +30,15 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
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(),
viper.GetString(flags.FlagKeyringBackend),
viper.GetString(flags.FlagHome),
keyringBackend,
rootDir,
inBuf,
hd.EthSecp256k1Options()...,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
@ -42,35 +46,44 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
decryptPassword := ""
conf := true
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
switch keyringBackend {
case keys.BackendFile:
case keyring.BackendFile:
decryptPassword, err = input.GetPassword(
"**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:",
inBuf)
case keys.BackendOS:
case keyring.BackendOS:
conf, err = input.GetConfirmation(
"**WARNING** this is an unsafe way to export your unencrypted private key, are you sure?",
inBuf)
inBuf, cmd.ErrOrStderr())
}
if err != nil || !conf {
return err
}
// Exports private key from keybase using password
privKey, err := kb.ExportPrivateKeyObject(args[0], decryptPassword)
armor, err := kr.ExportPrivKeyArmor(args[0], decryptPassword)
if err != nil {
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
emintKey, ok := privKey.(ethsecp256k1.PrivKey)
ethermintPrivKey, ok := privKey.(*ethsecp256k1.PrivKey)
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
privB := ethcrypto.FromECDSA(emintKey.ToECDSA())
privB := ethcrypto.FromECDSA(ethermintPrivKey.ToECDSA())
keyS := strings.ToUpper(hexutil.Encode(privB)[2:])
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 (
"bufio"
"encoding/json"
"errors"
"fmt"
"net"
"os"
"path/filepath"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/spf13/cobra"
tmconfig "github.com/tendermint/tendermint/config"
tmcrypto "github.com/tendermint/tendermint/crypto"
tmos "github.com/tendermint/tendermint/libs/os"
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"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
"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"
"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"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/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"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/ethermint/crypto/hd"
srvconfig "github.com/cosmos/ethermint/server/config"
ethermint "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
)
var (
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v"
flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home"
flagNodeCLIHome = "node-cli-home"
flagStartingIPAddress = "starting-ip-address"
flagCoinDenom = "coin-denom"
flagKeyAlgo = "algo"
flagIPAddrs = "ip-addrs"
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v"
flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home"
flagCoinDenom = "coin-denom"
flagIPAddrs = "ip-addresses"
)
const nodeDirPerm = 0755
// TestnetCmd initializes all files for tendermint testnet and application
func TestnetCmd(ctx *server.Context, cdc *codec.Codec,
mbm module.BasicManager, genAccIterator authtypes.GenesisAccountIterator,
func TestnetCmd(
mbm module.BasicManager, genBalancesIterator banktypes.GenesisBalancesIterator,
) *cobra.Command {
cmd := &cobra.Command{
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.`,
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 {
config := ctx.Config
clientCtx := client.GetClientContextFromCmd(cmd)
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
outputDir, _ := cmd.Flags().GetString(flagOutputDir)
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)
nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix)
nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome)
nodeCLIHome, _ := cmd.Flags().GetString(flagNodeCLIHome)
startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress)
ipAddresses, _ := cmd.Flags().GetStringSlice(flagIPAddrs)
numValidators, _ := cmd.Flags().GetInt(flagNumValidators)
algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
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(
cmd, config, cdc, mbm, genAccIterator, outputDir, chainID, coinDenom, minGasPrices,
nodeDirPrefix, nodeDaemonHome, nodeCLIHome, startingIPAddress, ipAddresses, keyringBackend, algo, numValidators,
clientCtx, cmd, config, mbm, genBalancesIterator, outputDir, chainID, coinDenom, minGasPrices,
nodeDirPrefix, nodeDaemonHome, keyringBackend, algo, ipAddresses, numValidators,
)
},
}
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(flagNodeDaemonHome, "ethermintd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagNodeCLIHome, "ethermintcli", "Home directory of the node's cli configuration")
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(flagNodeDaemonHome, "simd", "Home directory of the node's daemon 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(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(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
}
// InitTestnet initializes the testnet configuration
func InitTestnet(
clientCtx client.Context,
cmd *cobra.Command,
config *tmconfig.Config,
cdc *codec.Codec,
nodeConfig *tmconfig.Config,
mbm module.BasicManager,
genAccIterator authtypes.GenesisAccountIterator,
genBalIterator banktypes.GenesisBalancesIterator,
outputDir,
chainID,
coinDenom,
minGasPrices,
nodeDirPrefix,
nodeDaemonHome,
nodeCLIHome,
startingIPAddress string,
ipAddresses []string,
keyringBackend,
algo string,
algoStr string,
ipAddresses []string,
numValidators int,
) error {
@ -144,13 +145,19 @@ func InitTestnet(
}
nodeIDs := make([]string, numValidators)
valPubKeys := make([]tmcrypto.PubKey, numValidators)
valPubKeys := make([]cryptotypes.PubKey, numValidators)
simappConfig := srvconfig.DefaultConfig()
simappConfig.MinGasPrices = minGasPrices
appConfig := srvconfig.DefaultConfig()
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 (
genAccounts []authexported.GenesisAccount
genAccounts []authtypes.GenesisAccount
genBalances []banktypes.Balance
genFiles []string
)
@ -159,28 +166,25 @@ func InitTestnet(
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
clientDir := filepath.Join(outputDir, nodeDirName, nodeCLIHome)
gentxsDir := filepath.Join(outputDir, "gentxs")
config.SetRoot(nodeDir)
config.RPC.ListenAddress = "tcp://0.0.0.0:26657"
nodeConfig.SetRoot(nodeDir)
nodeConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657"
if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil {
_ = os.RemoveAll(outputDir)
return err
}
if err := os.MkdirAll(clientDir, nodeDirPerm); err != nil {
_ = os.RemoveAll(outputDir)
return err
}
nodeConfig.Moniker = nodeDirName
config.Moniker = nodeDirName
var (
ip string
err error
)
var ip string
var err error
if len(ipAddresses) == 0 {
ip, err = getIP(i, startingIPAddress)
if len(ipAddresses) == 1 {
ip, err = getIP(i, ipAddresses[0])
if err != nil {
_ = os.RemoveAll(outputDir)
return err
@ -189,32 +193,33 @@ func InitTestnet(
ip = ipAddresses[i]
}
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(config)
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig)
if err != nil {
_ = os.RemoveAll(outputDir)
return err
}
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(),
keyringBackend,
clientDir,
nodeDir,
inBuf,
hd.EthSecp256k1Options()...,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
cmd.Printf(
"Password for account '%s' :\n", nodeDirName,
)
keyringAlgos, _ := kb.SupportedAlgorithms()
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
if err != nil {
return err
}
keyPass := clientkeys.DefaultKeyPass
addr, secret, err := GenerateSaveCoinKey(kb, nodeDirName, keyPass, true, keys.SigningAlgo(algo))
addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo)
if err != nil {
_ = os.RemoveAll(outputDir)
return err
@ -228,7 +233,7 @@ func InitTestnet(
}
// 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
}
@ -237,13 +242,14 @@ func InitTestnet(
sdk.NewCoin(coinDenom, accStakingTokens),
)
genAccounts = append(genAccounts, ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(addr, coins, nil, 0, 0),
genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins})
genAccounts = append(genAccounts, &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0),
CodeHash: ethcrypto.Keccak256(nil),
})
valTokens := sdk.TokensFromConsensusPower(100)
msg := stakingtypes.NewMsgCreateValidator(
createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addr),
valPubKeys[i],
sdk.NewCoin(coinDenom, valTokens),
@ -252,37 +258,47 @@ func InitTestnet(
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 {
_ = os.RemoveAll(outputDir)
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 {
_ = os.RemoveAll(outputDir)
return err
}
// gather gentxs folder
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes); err != nil {
_ = os.RemoveAll(outputDir)
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
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
}
err := collectGenFiles(
cdc, config, chainID, nodeIDs, valPubKeys, numValidators,
outputDir, nodeDirPrefix, nodeDaemonHome, genAccIterator,
clientCtx, nodeConfig, chainID, nodeIDs, valPubKeys, numValidators,
outputDir, nodeDirPrefix, nodeDaemonHome, genBalIterator,
)
if err != nil {
return err
@ -293,57 +309,73 @@ func InitTestnet(
}
func initGenFiles(
cdc *codec.Codec, mbm module.BasicManager,
chainID, coinDenom string,
genAccounts []authexported.GenesisAccount,
genFiles []string, numValidators int,
clientCtx client.Context,
mbm module.BasicManager,
chainID,
coinDenom string,
genAccounts []authtypes.GenesisAccount,
genBalances []banktypes.Balance,
genFiles []string,
numValidators int,
) error {
appGenState := mbm.DefaultGenesis()
appGenState := mbm.DefaultGenesis(clientCtx.JSONMarshaler)
// set the accounts in the genesis state
var authGenState authtypes.GenesisState
cdc.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState)
clientCtx.JSONMarshaler.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState)
authGenState.Accounts = 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)
accounts, err := authtypes.PackAccounts(genAccounts)
if err != nil {
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,
AppState: appGenStateJSON,
Validators: nil,
@ -358,32 +390,10 @@ func initGenFiles(
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(
cdc *codec.Codec, config *tmconfig.Config, chainID string,
nodeIDs []string, valPubKeys []tmcrypto.PubKey,
numValidators int, outputDir, nodeDirPrefix, nodeDaemonHome string,
genAccIterator authtypes.GenesisAccountIterator,
clientCtx client.Context, nodeConfig *tmconfig.Config, chainID string,
nodeIDs []string, valPubKeys []cryptotypes.PubKey, numValidators int,
outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator,
) error {
var appState json.RawMessage
@ -393,19 +403,19 @@ func collectGenFiles(
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
gentxsDir := filepath.Join(outputDir, "gentxs")
config.Moniker = nodeDirName
nodeConfig.Moniker = nodeDirName
config.SetRoot(nodeDir)
nodeConfig.SetRoot(nodeDir)
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 {
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 {
return err
}
@ -415,7 +425,7 @@ func collectGenFiles(
appState = nodeAppState
}
genFile := config.GenesisFile()
genFile := nodeConfig.GenesisFile()
// overwrite each validator's genesis file to have a canonical genesis time
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 (
"bufio"
"encoding/json"
"errors"
"fmt"
"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/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/ethermint/crypto/hd"
ethermint "github.com/cosmos/ethermint/types"
@ -27,17 +27,13 @@ import (
)
const (
flagClientHome = "home-client"
flagVestingStart = "vesting-start-time"
flagVestingEnd = "vesting-end-time"
flagVestingAmt = "vesting-amount"
)
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
func AddGenesisAccountCmd(
ctx *server.Context, cdc *codec.Codec, defaultNodeHome, defaultClientHome string,
) *cobra.Command {
func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
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),
RunE: func(cmd *cobra.Command, args []string) error {
config := ctx.Config
config.SetRoot(viper.GetString(cli.HomeFlag))
clientCtx := client.GetClientContextFromCmd(cmd)
depCdc := clientCtx.JSONMarshaler
cdc := depCdc.(codec.Marshaler)
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
config.SetRoot(clientCtx.HomeDir)
addr, err := sdk.AccAddressFromBech32(args[0])
inBuf := bufio.NewReader(cmd.InOrStdin())
if err != nil {
// attempt to lookup address from Keybase if no address was provided
kb, err := keys.NewKeyring(
inBuf := bufio.NewReader(cmd.InOrStdin())
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
// attempt to lookup address from Keyring if no address was provided
kr, err := keyring.New(
sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend),
viper.GetString(flagClientHome),
keyringBackend,
clientCtx.HomeDir,
inBuf,
hd.EthSecp256k1Options()...,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
info, err := kb.Get(args[0])
info, err := kr.Key(args[0])
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()
}
coins, err := sdk.ParseCoins(args[1])
coins, err := sdk.ParseCoinsNormalized(args[1])
if err != nil {
return fmt.Errorf("failed to parse coins: %w", err)
}
vestingStart := viper.GetInt64(flagVestingStart)
vestingEnd := viper.GetInt64(flagVestingEnd)
vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt))
vestingStart, _ := cmd.Flags().GetInt64(flagVestingStart)
vestingEnd, _ := cmd.Flags().GetInt64(flagVestingEnd)
vestingAmtStr, _ := cmd.Flags().GetString(flagVestingAmt)
vestingAmt, err := sdk.ParseCoinsNormalized(vestingAmtStr)
if err != nil {
return fmt.Errorf("failed to parse vesting amount: %w", err)
}
// 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() {
baseVestingAccount, err := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd)
if err != nil {
return err
}
baseVestingAccount := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd)
if (coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) ||
baseVestingAccount.OriginalVesting.IsAnyGT(coins) {
if (balances.Coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) ||
baseVestingAccount.OriginalVesting.IsAnyGT(balances.Coins) {
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")
}
} else {
genAccount = ethermint.EthAccount{
genAccount = &ethermint.EthAccount{
BaseAccount: baseAccount,
CodeHash: ethcrypto.Keccak256(nil),
}
@ -125,30 +128,53 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
}
genFile := config.GenesisFile()
appState, genDoc, err := genutil.GenesisStateFromGenFile(cdc, genFile)
appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile)
if err != nil {
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)
}
// Add the new account to the set of genesis accounts and sanitize the
// accounts afterwards.
authGenState.Accounts = append(authGenState.Accounts, genAccount)
authGenState.Accounts = auth.SanitizeGenesisAccounts(authGenState.Accounts)
accs = append(accs, genAccount)
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 {
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 {
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.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().String(flagClientHome, defaultClientHome, "client'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|kwallet|pass|test)")
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().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts")
cmd.Flags().Int64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts")
cmd.Flags().Int64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts")
flags.AddQueryFlagsToCmd(cmd)
return cmd
}

View File

@ -1,129 +1,24 @@
package main
import (
"encoding/json"
"io"
"os"
"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"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
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"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"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() {
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)
tmamino.RegisterKeyType(ethsecp256k1.PrivKey{}, ethsecp256k1.PrivKeyName)
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
default:
os.Exit(1)
}
} 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 (
"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"
"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"
)
// MakeCodec registers the necessary types and interfaces for an sdk.App. This
// codec is provided to all the modules the application depends on.
//
// NOTE: This codec will be deprecated in favor of AppCodec once all modules are
// migrated to protobuf.
func MakeCodec(bm module.BasicManager) *codec.Codec {
cdc := codec.New()
bm.RegisterCodec(cdc)
vesting.RegisterCodec(cdc)
sdk.RegisterCodec(cdc)
cryptocodec.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
ethermint.RegisterCodec(cdc)
keys.RegisterCodec(cdc) // temporary. Used to register keyring.Info
return cdc
// RegisterLegacyAminoCodec registers Interfaces from types, crypto, and SDK std.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
sdk.RegisterLegacyAminoCodec(cdc)
cryptocodec.RegisterCrypto(cdc)
}
// RegisterInterfaces registers Interfaces from types, crypto, and SDK std.
func RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) {
std.RegisterInterfaces(interfaceRegistry)
cryptocodec.RegisterInterfaces(interfaceRegistry)
ethermint.RegisterInterfaces(interfaceRegistry)
}

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 (
"bytes"
"crypto/ecdsa"
"crypto/subtle"
"fmt"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"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"
)
const (
// PrivKeySize defines the size of the PrivKey bytes
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"
)
@ -28,54 +36,85 @@ const (
// ----------------------------------------------------------------------------
// secp256k1 Private Key
var _ tmcrypto.PrivKey = PrivKey{}
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
// Tendermint's PrivateKey interface.
type PrivKey []byte
var (
_ cryptotypes.PrivKey = &PrivKey{}
_ codec.AminoMarshaler = &PrivKey{}
)
// GenerateKey generates a new random private key. It returns an error upon
// failure.
func GenerateKey() (PrivKey, error) {
func GenerateKey() (*PrivKey, error) {
priv, err := ethcrypto.GenerateKey()
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.
func (privkey PrivKey) PubKey() tmcrypto.PubKey {
ecdsaPKey := privkey.ToECDSA()
return PubKey(ethcrypto.CompressPubkey(&ecdsaPKey.PublicKey))
func (privKey PrivKey) PubKey() cryptotypes.PubKey {
ecdsaPrivKey := privKey.ToECDSA()
return &PubKey{
Key: ethcrypto.CompressPubkey(&ecdsaPrivKey.PublicKey),
}
}
// Bytes returns the raw ECDSA private key bytes.
func (privkey PrivKey) Bytes() []byte {
return CryptoCodec.MustMarshalBinaryBare(privkey)
// Equals returns true if two ECDSA private keys are equal and false otherwise.
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
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
// Keccak256 hash of the provided message. The produced signature is 65 bytes
// where the last byte contains the recovery ID.
func (privkey PrivKey) Sign(msg []byte) ([]byte, error) {
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
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
return ethcrypto.Sign(ethcrypto.Keccak256Hash(msg).Bytes(), privKey.ToECDSA())
}
// ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type.
// The function will panic if the private key is invalid.
func (privkey PrivKey) ToECDSA() *ecdsa.PrivateKey {
key, err := ethcrypto.ToECDSA(privkey)
func (privKey PrivKey) ToECDSA() *ecdsa.PrivateKey {
key, err := ethcrypto.ToECDSA(privKey.Bytes())
if err != nil {
panic(err)
}
@ -85,16 +124,15 @@ func (privkey PrivKey) ToECDSA() *ecdsa.PrivateKey {
// ----------------------------------------------------------------------------
// secp256k1 Public Key
var _ tmcrypto.PubKey = (*PubKey)(nil)
// 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 []byte
var (
_ cryptotypes.PubKey = &PubKey{}
_ codec.AminoMarshaler = &PubKey{}
)
// Address returns the address of the ECDSA public key.
// The function will panic if the public key is invalid.
func (key PubKey) Address() tmcrypto.Address {
pubk, err := ethcrypto.DecompressPubkey(key)
func (pubKey PubKey) Address() tmcrypto.Address {
pubk, err := ethcrypto.DecompressPubkey(pubKey.Key)
if err != nil {
panic(err)
}
@ -103,33 +141,61 @@ func (key PubKey) Address() tmcrypto.Address {
}
// Bytes returns the raw bytes of the ECDSA public key.
// The function panics if the key cannot be marshaled to bytes.
func (key PubKey) Bytes() []byte {
bz, err := CryptoCodec.MarshalBinaryBare(key)
if err != nil {
panic(err)
}
return bz
func (pubKey PubKey) Bytes() []byte {
return pubKey.Key
}
// 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
// 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 {
// remove recovery ID if contained in the signature
sig = sig[:len(sig)-1]
}
// the signature needs to be in [R || S] format when provided to VerifySignature
return secp256k1.VerifySignature(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
return secp256k1.VerifySignature(pubKey.Key, ethcrypto.Keccak256Hash(msg).Bytes(), sig)
}

View File

@ -1,22 +1,25 @@
package ethsecp256k1
import (
"encoding/base64"
"testing"
"github.com/stretchr/testify/require"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
ethsecp256k1 "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/cosmos/cosmos-sdk/codec"
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
privKey, err := GenerateKey()
require.NoError(t, err)
require.True(t, privKey.Equals(privKey))
require.Implements(t, (*tmcrypto.PrivKey)(nil), privKey)
require.Implements(t, (*cryptotypes.PrivKey)(nil), privKey)
// validate inequality
privKey2, err := GenerateKey()
@ -31,20 +34,23 @@ func TestPrivKeyPrivKey(t *testing.T) {
// validate we can sign some bytes
msg := []byte("hello world")
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)
require.NoError(t, err)
require.Equal(t, expectedSig, sig)
}
func TestPrivKeyPubKey(t *testing.T) {
func TestPrivKey_PubKey(t *testing.T) {
privKey, err := GenerateKey()
require.NoError(t, err)
// validate type and equality
pubKey := privKey.PubKey().(PubKey)
require.Implements(t, (*tmcrypto.PubKey)(nil), pubKey)
pubKey := &PubKey{
Key: privKey.PubKey().Bytes(),
}
require.Implements(t, (*cryptotypes.PubKey)(nil), pubKey)
// validate inequality
privKey2, err := GenerateKey()
@ -56,6 +62,61 @@ func TestPrivKeyPubKey(t *testing.T) {
sig, err := privKey.Sign(msg)
require.NoError(t, err)
res := pubKey.VerifyBytes(msg, sig)
res := pubKey.VerifySignature(msg, sig)
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
import (
"fmt"
"github.com/pkg/errors"
"github.com/btcsuite/btcd/chaincfg"
"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"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
)
const (
// EthSecp256k1 defines the ECDSA secp256k1 used on Ethereum
EthSecp256k1 = keys.SigningAlgo(ethsecp256k1.KeyType)
// EthSecp256k1Type defines the ECDSA secp256k1 used on Ethereum
EthSecp256k1Type = hd.PubKeyType(ethsecp256k1.KeyType)
)
// SupportedAlgorithms defines the list of signing algorithms used on Ethermint:
// - eth_secp256k1 (Ethereum)
// - secp256k1 (Tendermint)
var SupportedAlgorithms = []keys.SigningAlgo{EthSecp256k1, keys.Secp256k1}
var (
// SupportedAlgorithms defines the list of signing algorithms used on Ethermint:
// - eth_secp256k1 (Ethereum)
// - 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.
func EthSecp256k1Options() []keys.KeybaseOption {
return []keys.KeybaseOption{
keys.WithKeygenFunc(EthermintKeygenFunc),
keys.WithDeriveFunc(DeriveKey),
keys.WithSupportedAlgos(SupportedAlgorithms),
keys.WithSupportedAlgosLedger(SupportedAlgorithms),
// EthSecp256k1Option defines a function keys options for the ethereum Secp256k1 curve.
// It supports eth_secp256k1 and secp256k1 keys for accounts.
func EthSecp256k1Option() keyring.Option {
return func(options *keyring.Options) {
options.SupportedAlgos = SupportedAlgorithms
options.SupportedAlgosLedger = SupportedAlgorithmsLedger
}
}
func DeriveKey(mnemonic, bip39Passphrase, hdPath string, algo keys.SigningAlgo) ([]byte, error) {
switch algo {
case keys.Secp256k1:
return keys.StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo)
case EthSecp256k1:
return DeriveSecp256k1(mnemonic, bip39Passphrase, hdPath)
default:
return nil, errors.Wrap(keys.ErrUnsupportedSigningAlgo, string(algo))
}
var (
_ keyring.SignatureAlgo = EthSecp256k1
// EthSecp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
EthSecp256k1 = ethSecp256k1Algo{}
)
type ethSecp256k1Algo struct {
}
// EthermintKeygenFunc is the key generation function to generate secp256k1 ToECDSA
// from ethereum.
func EthermintKeygenFunc(bz []byte, algo keys.SigningAlgo) (tmcrypto.PrivKey, error) {
if algo != EthSecp256k1 {
return nil, fmt.Errorf("signing algorithm must be %s, got %s", EthSecp256k1, algo)
}
return ethsecp256k1.PrivKey(bz), nil
// Name returns eth_secp256k1
func (s ethSecp256k1Algo) Name() hd.PubKeyType {
return EthSecp256k1Type
}
// DeriveSecp256k1 derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
func DeriveSecp256k1(mnemonic, bip39Passphrase, path string) ([]byte, error) {
hdpath, err := ethaccounts.ParseDerivationPath(path)
if err != nil {
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)
// Derive derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
func (s ethSecp256k1Algo) Derive() hd.DeriveFn {
return func(mnemonic string, bip39Passphrase, path string) ([]byte, error) {
hdpath, err := ethaccounts.ParseDerivationPath(path)
if err != nil {
return nil, err
}
}
privateKey, err := key.ECPrivKey()
if err != nil {
return nil, err
}
seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
if err != nil {
return nil, err
}
privateKeyECDSA := privateKey.ToECDSA()
derivedKey := ethsecp256k1.PrivKey(ethcrypto.FromECDSA(privateKeyECDSA))
return derivedKey, nil
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 {
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/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
"github.com/cosmos/cosmos-sdk/tests"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
cryptocodec "github.com/cosmos/ethermint/crypto/codec"
ethermint "github.com/cosmos/ethermint/types"
)
func TestEthermintKeygenFunc(t *testing.T) {
privkey, err := ethsecp256k1.GenerateKey()
require.NoError(t, err)
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 init() {
amino := codec.NewLegacyAmino()
cryptocodec.RegisterCrypto(amino)
}
func TestKeyring(t *testing.T) {
dir, cleanup := tests.NewTestCaseDir(t)
dir := t.TempDir()
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)
// fail in retrieving key
info, err := kr.Get("foo")
info, err := kr.Key("foo")
require.Error(t, err)
require.Nil(t, info)
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.NotEmpty(t, mnemonic)
require.Equal(t, "foo", info.GetName())
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 := params.String()
hdPath := ethermint.BIP44HDPath
bz, err := DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.Secp256k1)
bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, hdPath)
require.NoError(t, err)
require.NotEmpty(t, bz)
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, hdPath)
require.NoError(t, err)
require.NotEmpty(t, bz)
bz, err = DeriveKey(mnemonic, keys.DefaultBIP39Passphrase, hdPath, keys.SigningAlgo(""))
wrongBz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, "/wrong/hdPath")
require.Error(t, err)
require.Empty(t, bz)
require.Empty(t, wrongBz)
bz, err = DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, "/wrong/hdPath")
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)
privkey := EthSecp256k1.Generate()(bz)
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
@ -126,25 +68,20 @@ func TestKeyring(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"
bz, err := DeriveSecp256k1(mnemonic, keys.DefaultBIP39Passphrase, ethermint.BIP44HDPath)
bz, err := EthSecp256k1.Derive()(mnemonic, keyring.DefaultBIP39Passphrase, ethermint.BIP44HDPath)
require.NoError(t, err)
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.NotEmpty(t, badBz)
require.NotEqual(t, bz, badBz)
privkey, err := EthermintKeygenFunc(bz, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, privkey)
privkey := EthSecp256k1.Generate()(bz)
badPrivKey := EthSecp256k1.Generate()(badBz)
badPrivKey, err := EthermintKeygenFunc(badBz, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, badPrivKey)
require.NotEqual(t, privkey, badPrivKey)
require.False(t, privkey.Equals(badPrivKey))
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
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
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/btcutil v1.0.2
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/ethereum/go-ethereum v1.9.25
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/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/pkg/errors v0.9.1
github.com/prometheus/tsdb v0.9.1 // indirect
github.com/spf13/afero v1.2.2 // indirect
github.com/prometheus/tsdb v0.10.0 // 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/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/tendermint/tendermint v0.33.9
github.com/tendermint/tm-db v0.5.2
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
google.golang.org/grpc v1.30.0 // indirect
github.com/tendermint/tendermint v0.34.9
github.com/tendermint/tm-db v0.6.4
github.com/tyler-smith/go-bip39 v1.0.2
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
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.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
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/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/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.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/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
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.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/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI=
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/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-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-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 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
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.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
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/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-20200331225509-2cc472e8fbd6 h1:Pcu4aKyFfpH0aXLnYJrsTjdRvXNY4SbODsb0pMTZxhA=
github.com/aristanetworks/goarista v0.0.0-20200331225509-2cc472e8fbd6/go.mod h1:QZe5Yh80Hp1b6JxQdpfSEEe8X7hTyTEZSosSrFf/oJE=
github.com/aristanetworks/goarista v0.0.0-20201012165903-2cb20defcd66 h1:bylzF2sl5pWmmHcdwEku/BPHp5wYjcdjmOnW4siw688=
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/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/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/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-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-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 v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
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-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.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M=
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
github.com/btcsuite/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/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 v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE=
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
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/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/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/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/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/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/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.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-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-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.39.2/go.mod h1:VNUluciWBFj2vkhpMcp8rYZL/kCw0FtNc7SseUjE1KM=
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/cosmos-sdk v0.42.4 h1:yaD4PyOx0LnyfiWasC5egg1U76lT83GRxjJjupPo7Gk=
github.com/cosmos/cosmos-sdk v0.42.4/go.mod h1:I1Zw1zmU4rA/NITaakTb71pXQnQrWyFBhqo3WSeg0vA=
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/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/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/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/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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 v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
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/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/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dustin/go-humanize 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/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
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/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
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.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/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/ethereum/go-ethereum v1.9.5/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
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/fatih/color v1.3.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-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
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/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/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.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
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/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/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-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/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/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/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=
@ -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/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.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.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.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
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.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 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
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.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.3-0.20201103224600-674baa8c7fc3 h1:ur2rms48b3Ep1dxh7aUV2FZEQ8jEVO2F6ILKx8ofkAg=
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.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.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 v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
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/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
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.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.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/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
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.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
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.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/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
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.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
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/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.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/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.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/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
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.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/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-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-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-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-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-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.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
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.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/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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
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/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/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
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/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=
@ -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/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 v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
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/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/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.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.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/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/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.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
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/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/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/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 v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
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/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.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.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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 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/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.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
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.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.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
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-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
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/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/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA=
github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc=
github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
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/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
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/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-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/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
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.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
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/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
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/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.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
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/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.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/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 v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
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.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4=
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
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/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/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 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=
@ -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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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.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.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.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA=
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
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-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
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.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.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
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-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.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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.10 h1:QJQN3jYQhkamO4mhfUWqdDH2asK7ONOI9MTWjyAxNKM=
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.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.9.1 h1:IWaAmWkYlgG7/S4iw4IpAQt5Y35QaZM6/GsZ7GsjAuk=
github.com/prometheus/tsdb v0.9.1/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
github.com/rakyll/statik v0.1.6 h1:uICcfUXpgqtw2VopbIncslhAmE5hwc4g20TEyEENBNs=
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
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-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/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/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig=
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/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
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/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/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
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/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/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/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
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/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.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/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
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/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 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.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
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/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc=
github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
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 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.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
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.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
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.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.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
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-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw=
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 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
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/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
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.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.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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/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/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
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/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/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
github.com/tendermint/go-amino v0.15.1 h1:D2uk35eT4iTsvJd9jWIetzthE5C0/k2QmMFkCN+4JgQ=
github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/iavl v0.14.1 h1:jz7YOvGiPwmcqqVMcSMjxCu4WXtQYGhKdKrWTTJ5EKs=
github.com/tendermint/iavl v0.14.1/go.mod h1:QmfViflFiXzxKLQE4tAUuWQHq+RSuQFxablW5oJZ6sE=
github.com/tendermint/iavl v0.14.3 h1:tuiUAqJdA3OOyPU/9P3pMYnAcd+OL7BUdzNiE3ytUwQ=
github.com/tendermint/iavl v0.14.3/go.mod h1:vHLYxU/zuxBmxxr1v+5Vnd/JzcIsyK17n9P9RDubPVU=
github.com/tendermint/tendermint v0.33.5/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
github.com/tendermint/tendermint v0.33.9 h1:rRKIfu5qAXX5f9bwX1oUXSZz/ALFJjDuivhkbGUQxiU=
github.com/tendermint/tendermint v0.33.9/go.mod h1:0yUs9eIuuDq07nQql9BmI30FtYGcEC60Tu5JzB5IezM=
github.com/tendermint/tm-db v0.5.1 h1:H9HDq8UEA7Eeg13kdYckkgwwkQLBnJGgX4PgLJRhieY=
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/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
github.com/tendermint/tendermint v0.34.9 h1:9P2MXDEPOcPW0NBcHQ/HDSfvczZm+q5nUUw7AZ6f1Vc=
github.com/tendermint/tendermint v0.34.9/go.mod h1:kl4Z1JwGx1I+u1SXIzMDy7Z3T8LiMeCAOnzNn6AIMT4=
github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI=
github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8=
github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ=
github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw=
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/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/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 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.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/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.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
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.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/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/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
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.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.opencensus.io v0.20.1/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-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-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-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-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-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-20190911031432-227b76d455e7/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-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-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-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
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-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-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-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-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-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
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-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-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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee 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.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -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-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-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-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-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-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-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-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-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-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-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-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-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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e 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-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-20180830151530-49385e6e1522/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-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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-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-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-20190726091711-fc99dfbffb4e/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-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-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-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-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-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-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-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-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-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4=
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-20201013132646-2da7054afaeb h1:HS9IzC4UFbpMBLQUDSQcU+ViVT1vdFCQVjdPVpTlZrs=
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/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.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.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
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-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-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
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-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-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-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-20190912185636-87d9f09c5d89/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-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-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.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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -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-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-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-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-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.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.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
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.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.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
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.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
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/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 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-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/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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
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/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/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/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/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
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.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.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.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.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c 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-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=
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=

View File

@ -13,20 +13,25 @@ import (
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
sdkcodec "github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store"
sdkstore "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/params"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
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"
cryptocodec "github.com/cosmos/ethermint/crypto/ethsecp256k1"
"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"
ethcmn "github.com/ethereum/go-ethereum/common"
@ -38,8 +43,8 @@ import (
ethparams "github.com/ethereum/go-ethereum/params"
ethrlp "github.com/ethereum/go-ethereum/rlp"
abci "github.com/tendermint/tendermint/abci/types"
tmlog "github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
)
@ -64,18 +69,16 @@ func init() {
flag.Parse()
}
func newTestCodec() *sdkcodec.Codec {
cdc := sdkcodec.New()
func newTestCodec() (sdkcodec.BinaryMarshaler, *sdkcodec.LegacyAmino) {
interfaceRegistry := codectypes.NewInterfaceRegistry()
cdc := sdkcodec.NewProtoCodec(interfaceRegistry)
amino := sdkcodec.NewLegacyAmino()
evmtypes.RegisterCodec(cdc)
types.RegisterCodec(cdc)
auth.RegisterCodec(cdc)
bank.RegisterCodec(cdc)
sdk.RegisterCodec(cdc)
cryptocodec.RegisterCodec(cdc)
sdkcodec.RegisterCrypto(cdc)
sdk.RegisterLegacyAminoCodec(amino)
return cdc
codec.RegisterInterfaces(interfaceRegistry)
return cdc, amino
}
func cleanup() {
@ -99,10 +102,10 @@ func trapSignals() {
}
// 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()
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
evmKeeper.SetParams(ctx, evmtypes.DefaultParams())
@ -151,7 +154,7 @@ func createAndTestGenesis(t *testing.T, cms sdk.CommitMultiStore, ak auth.Accoun
require.NotNil(t, genAcc)
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)
}
@ -168,43 +171,50 @@ func TestImportBlocks(t *testing.T) {
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()
trapSignals()
cdc := newTestCodec()
cdc, amino := newTestCodec()
cms := store.NewCommitMultiStore(db)
authStoreKey := sdk.NewKVStoreKey(auth.StoreKey)
authStoreKey := sdk.NewKVStoreKey(authtypes.StoreKey)
bankStoreKey := sdk.NewKVStoreKey(banktypes.StoreKey)
evmStoreKey := sdk.NewKVStoreKey(evmtypes.StoreKey)
paramsStoreKey := sdk.NewKVStoreKey(params.StoreKey)
paramsTransientStoreKey := sdk.NewTransientStoreKey(params.TStoreKey)
paramsStoreKey := sdk.NewKVStoreKey(paramtypes.StoreKey)
paramsTransientStoreKey := sdk.NewTransientStoreKey(paramtypes.TStoreKey)
// mount stores
keys := []*sdk.KVStoreKey{authStoreKey, evmStoreKey, paramsStoreKey}
keys := []*sdk.KVStoreKey{authStoreKey, bankStoreKey, evmStoreKey, paramsStoreKey}
for _, key := range keys {
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, nil)
}
cms.MountStoreWithDB(paramsTransientStoreKey, sdk.StoreTypeTransient, nil)
paramsKeeper := params.NewKeeper(cdc, paramsStoreKey, paramsTransientStoreKey)
paramsKeeper := paramkeeper.NewKeeper(cdc, amino, paramsStoreKey, paramsTransientStoreKey)
// Set specific subspaces
authSubspace := paramsKeeper.Subspace(auth.DefaultParamspace)
evmSubspace := paramsKeeper.Subspace(evmtypes.DefaultParamspace).WithKeyTable(evmtypes.ParamKeyTable())
ak := auth.NewAccountKeeper(cdc, authStoreKey, authSubspace, types.ProtoAccount)
evmKeeper := evm.NewKeeper(cdc, evmStoreKey, evmSubspace, ak)
authSubspace := paramsKeeper.Subspace(authtypes.ModuleName)
bankSubspace := paramsKeeper.Subspace(banktypes.ModuleName)
evmSubspace := paramsKeeper.Subspace(evmtypes.ModuleName).WithKeyTable(evmtypes.ParamKeyTable())
// 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)
// load latest version (root)
err := cms.LoadLatestVersion()
err = cms.LoadLatestVersion()
require.NoError(t, err)
// set and test genesis block
createAndTestGenesis(t, cms, ak, evmKeeper)
createAndTestGenesis(t, cms, ak, bk, evmKeeper)
// open blockchain export file
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 new context based off of that.
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()))
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
// included uncles. The coinbase of each uncle block is also rewarded.
func accumulateRewards(
config *ethparams.ChainConfig, evmKeeper *evm.Keeper,
config *ethparams.ChainConfig, evmKeeper *evmkeeper.Keeper,
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
// SetBalance function implementation
// 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
if !evmKeeper.CommitStateDB.Exist(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
func applyTransaction(
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,
) (*ethtypes.Receipt, uint64, error) {
msg, err := tx.AsMessage(ethtypes.MakeSigner(config, header.Number))

74
init.sh
View File

@ -1,7 +1,6 @@
#!/bin/bash
KEY="mykey"
CHAINID="ethermint-1"
CHAINID="ethermint-2"
MONIKER="localtestnet"
# remove existing daemon and client
@ -9,46 +8,57 @@ rm -rf ~/.ethermint*
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
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)
ethermintd init $MONIKER --chain-id $CHAINID
ethermintd init $MONIKER --chain-id $CHAINID
# 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/.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/.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/.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["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/.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/.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/.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 (?)
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
echo "pending mode on; block times will be set to 30s."
# sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermintd/config/config.toml
sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.ethermintd/config/config.toml
if [[ "$OSTYPE" == "darwin"* ]]; then
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
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
# 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
ethermintd gentx --name $KEY --amount=1000000000000000000aphoton --keyring-backend test
ethermintd gentx $KEY 1000000000000000000stake --amount=1000000000000000000000aphoton --keyring-backend test --chain-id $CHAINID
# Collect genesis tx
ethermintd collect-gentxs
@ -56,9 +66,9 @@ ethermintd collect-gentxs
# Run this to ensure everything worked and that the genesis file is setup correctly
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\" --unlock-key $KEY --chain-id $CHAINID --trace\n"
if [[ $1 == "pending" ]]; then
echo "pending mode is on, please wait for the first block committed."
fi
# 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 --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 /
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"]

View File

@ -30,15 +30,10 @@ message GenesisState {
message GenesisAccount {
// address defines an ethereum hex formated address of an account
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.
string code = 3;
string code = 2;
// storage defines the set of state key values for the account.
repeated State storage = 4 [
repeated State storage = 3 [
(gogoproto.nullable) = false,
(gogoproto.castrepeated) = "Storage"
];

View File

@ -1,18 +1,19 @@
package rpc
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/net"
"github.com/cosmos/ethermint/rpc/namespaces/personal"
"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"
"github.com/cosmos/cosmos-sdk/client"
)
// RPC namespaces and API version
@ -24,33 +25,17 @@ const (
flagRPCAPI = "rpc-api"
apiVersion = "1.0"
flagRPCAPI = "rpc-api"
)
// 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)
backend := backend.New(clientCtx)
ethAPI := eth.NewAPI(clientCtx, backend, nonceLock, keys...)
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 {
switch api {
case Web3Namespace:
@ -62,6 +47,21 @@ func GetAPIs(clientCtx context.CLIContext, selectedApis []string, keys ...ethsec
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:
apis = append(apis,
rpc.API{

View File

@ -2,7 +2,7 @@ package backend
import (
"context"
"fmt"
"errors"
"os"
"github.com/tendermint/tendermint/libs/log"
@ -10,7 +10,7 @@ import (
rpctypes "github.com/cosmos/ethermint/rpc/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/hexutil"
@ -43,131 +43,104 @@ var _ Backend = (*EthermintBackend)(nil)
// EthermintBackend implements the Backend interface
type EthermintBackend struct {
ctx context.Context
clientCtx clientcontext.CLIContext
logger log.Logger
gasLimit int64
ctx context.Context
clientCtx client.Context
queryClient *rpctypes.QueryClient // gRPC query client
logger log.Logger
}
// New creates a new EthermintBackend instance
func New(clientCtx clientcontext.CLIContext) *EthermintBackend {
func New(clientCtx client.Context) *EthermintBackend {
return &EthermintBackend{
ctx: context.Background(),
clientCtx: clientCtx,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"),
gasLimit: int64(^uint32(0)),
ctx: context.Background(),
clientCtx: clientCtx,
queryClient: rpctypes.NewQueryClient(clientCtx),
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"),
}
}
// BlockNumber returns the current block number.
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 {
return hexutil.Uint64(0), err
}
return hexutil.Uint64(blockNumber), nil
return hexutil.Uint64(info.LastHeight), nil
}
// GetBlockByNumber returns the block identified by number.
func (b *EthermintBackend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) {
height := blockNum.Int64()
if height <= 0 {
// get latest block height
num, err := b.BlockNumber()
if err != nil {
return nil, err
}
height = int64(num)
var height *int64
// NOTE: here pending and latest are defined as a nil height, which fetches the latest block
if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
height = blockNum.TmHeight()
}
resBlock, err := b.clientCtx.Client.Block(&height)
resBlock, err := b.clientCtx.Client.Block(b.ctx, height)
if err != nil {
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.
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 {
return nil, err
}
var out evmtypes.QueryResBlockNumber
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)
return rpctypes.EthBlockFromTendermint(b.clientCtx, b.queryClient, resBlock.Block)
}
// HeaderByNumber returns the block header identified by height.
func (b *EthermintBackend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) {
height := blockNum.Int64()
if height <= 0 {
// get latest block height
num, err := b.BlockNumber()
if err != nil {
return nil, err
}
height = int64(num)
var height *int64
// NOTE: here pending and latest are defined as a nil height, which fetches the latest header
if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
height = blockNum.TmHeight()
}
resBlock, err := b.clientCtx.Client.Block(&height)
resBlock, err := b.clientCtx.Client.Block(b.ctx, height)
if err != nil {
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 {
return nil, err
}
var bloomRes evmtypes.QueryBloomFilter
b.clientCtx.Codec.MustUnmarshalJSON(res, &bloomRes)
ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header)
ethHeader.Bloom = bloomRes.Bloom
ethHeader.Bloom = ethtypes.BytesToBloom(res.Bloom)
return ethHeader, nil
}
// HeaderByHash returns the block header identified by hash.
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 {
return nil, err
}
var out evmtypes.QueryResBlockNumber
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
req := &evmtypes.QueryBlockBloomRequest{}
resBlock, err := b.clientCtx.Client.Block(&out.Number)
res, err := b.queryClient.BlockBloom(rpctypes.ContextWithHeight(resBlock.Block.Height), req)
if err != nil {
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.Bloom = bloomRes.Bloom
ethHeader.Bloom = ethtypes.BytesToBloom(res.Bloom)
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.
// If no logs are found for the tx hash, the error is nil.
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 {
return nil, err
}
out := new(evmtypes.QueryETHLogs)
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
return out.Logs, nil
return evmtypes.LogsToEthereum(res.Logs), nil
}
// PendingTransactions returns the transactions that are in the transaction pool
// and have a from address that is one of the accounts this node manages.
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 {
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.
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()))
if err != nil {
return nil, err
// NOTE: we query the state in case the tx result logs are not persisted after an upgrade.
req := &evmtypes.QueryBlockLogsRequest{
Hash: blockHash.String(),
}
var out evmtypes.QueryResBlockNumber
if err := b.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil, err
}
block, err := b.clientCtx.Client.Block(&out.Number)
res, err := b.queryClient.BlockLogs(b.ctx, req)
if err != nil {
return nil, err
}
var blockLogs = [][]*ethtypes.Log{}
for _, tx := range block.Block.Txs {
// NOTE: we query the state in case the tx result logs are not persisted after an upgrade.
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)
for _, txLog := range res.TxLogs {
blockLogs = append(blockLogs, txLog.EthLogs())
}
return blockLogs, nil
@ -259,7 +216,7 @@ func (b *EthermintBackend) BloomStatus() (uint64, uint64) {
// LatestBlockNumber gets the latest block height in int64 format.
func (b *EthermintBackend) LatestBlockNumber() (int64, error) {
// 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 {
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
import (
"bufio"
"fmt"
"os"
"strings"
"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/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/gorilla/mux"
"github.com/spf13/viper"
"github.com/cosmos/cosmos-sdk/client"
"github.com/ethereum/go-ethereum/rpc"
)
const (
flagUnlockKey = "unlock-key"
flagWebsocket = "wsport"
)
// 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) {
// RegisterEthereum creates a new ethereum JSON-RPC server and recreates a CLI command to start Cosmos REST server with web3 RPC API and
// Cosmos rest-server endpoints
func RegisterEthereum(clientCtx client.Context, r *mux.Router) {
server := rpc.NewServer()
accountName := viper.GetString(flagUnlockKey)
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)
}
}
r.HandleFunc("/", server.ServeHTTP).Methods("POST", "OPTIONS")
rpcapi := viper.GetString(flagRPCAPI)
rpcapi = strings.ReplaceAll(rpcapi, " ", "")
rpcapiArr := strings.Split(rpcapi, ",")
apis := GetAPIs(rs.CliCtx, rpcapiArr, privkeys...)
apis := GetAPIs(clientCtx, rpcapiArr)
// Register all the APIs exposed by the namespace services
// TODO: handle allowlist and private APIs
@ -71,50 +30,4 @@ func RegisterRoutes(rs *lcd.RestServer) {
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"
"math/big"
"os"
"strings"
"sync"
"time"
"github.com/gogo/protobuf/jsonpb"
"github.com/spf13/viper"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
@ -17,13 +19,10 @@ import (
"github.com/cosmos/ethermint/rpc/backend"
rpctypes "github.com/cosmos/ethermint/rpc/types"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/utils"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/rpc/client"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/ethereum/go-ethereum/accounts/keystore"
@ -32,19 +31,18 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
"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/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
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"
)
// PublicEthereumAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
type PublicEthereumAPI struct {
ctx context.Context
clientCtx clientcontext.CLIContext
clientCtx client.Context
queryClient *rpctypes.QueryClient // gRPC query client
chainIDEpoch *big.Int
logger log.Logger
backend backend.Backend
@ -55,7 +53,7 @@ type PublicEthereumAPI struct {
// NewAPI creates an instance of the public ETH Web3 API.
func NewAPI(
clientCtx clientcontext.CLIContext, backend backend.Backend, nonceLock *rpctypes.AddrLocker,
clientCtx client.Context, backend backend.Backend, nonceLock *rpctypes.AddrLocker,
keys ...ethsecp256k1.PrivKey,
) *PublicEthereumAPI {
@ -67,6 +65,7 @@ func NewAPI(
api := &PublicEthereumAPI{
ctx: context.Background(),
clientCtx: clientCtx,
queryClient: rpctypes.NewQueryClient(clientCtx),
chainIDEpoch: epoch,
logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc", "namespace", "eth"),
backend: backend,
@ -87,27 +86,26 @@ func (api *PublicEthereumAPI) GetKeyringInfo() error {
api.keyringLock.Lock()
defer api.keyringLock.Unlock()
if api.clientCtx.Keybase != nil {
return nil
}
keybase, err := keys.NewKeyring(
/*api.clientCtx.keyring won't be nil because we init node with ethermintd keys add CLI
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(
sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend),
viper.GetString(flags.FlagHome),
api.clientCtx.KeyringDir,
api.clientCtx.Input,
hd.EthSecp256k1Options()...,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
api.clientCtx.Keybase = keybase
api.clientCtx.Keyring = keybase
return nil
}
// ClientCtx returns the Cosmos SDK client context.
func (api *PublicEthereumAPI) ClientCtx() clientcontext.CLIContext {
func (api *PublicEthereumAPI) ClientCtx() client.Context {
return api.clientCtx
}
@ -138,7 +136,7 @@ func (api *PublicEthereumAPI) ChainId() (hexutil.Uint, error) { // nolint
func (api *PublicEthereumAPI) Syncing() (interface{}, error) {
api.logger.Debug("eth_syncing")
status, err := api.clientCtx.Client.Status()
status, err := api.clientCtx.Client.Status(api.ctx)
if err != nil {
return false, err
}
@ -165,7 +163,7 @@ func (api *PublicEthereumAPI) Coinbase() (common.Address, error) {
return common.Address{}, err
}
status, err := node.Status()
status, err := node.Status(api.ctx)
if err != nil {
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
infos, err := api.clientCtx.Keybase.List()
infos, err := api.clientCtx.Keyring.List()
if err != nil {
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.
//nolint:interfacer
func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) {
api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum)
clientCtx := api.clientCtx
if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) {
clientCtx = api.clientCtx.WithHeight(blockNum.Int64())
req := &evmtypes.QueryBalanceRequest{
Address: address.String(),
}
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 {
return nil, err
}
var out evmtypes.QueryResBalance
api.clientCtx.Codec.MustUnmarshalJSON(res, &out)
val, err := utils.UnmarshalBigInt(out.Balance)
balance := big.NewInt(0)
err = balance.UnmarshalText([]byte(res.Balance))
if err != nil {
return nil, err
}
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)
@ -256,28 +259,33 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp
}
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 {
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.
//nolint:interfacer
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)
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 {
return nil, err
}
var out evmtypes.QueryResStorage
api.clientCtx.Codec.MustUnmarshalJSON(res, &out)
return out.Value, nil
value := common.HexToHash(res.Value)
return value.Bytes(), nil
}
// 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.
func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint {
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
if err := api.clientCtx.Codec.UnmarshalJSON(res, &out); err != nil {
return nil
}
resBlock, err := api.clientCtx.Client.Block(&out.Number)
resBlock, err := api.clientCtx.Client.BlockByHash(api.ctx, hash.Bytes())
if err != nil {
return nil
}
@ -329,40 +328,45 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes
var (
height int64
err error
txCount hexutil.Uint
txs int
)
switch blockNum {
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 {
return nil
}
resBlock, err := api.clientCtx.Client.Block(&height)
if err != nil {
return nil
var resBlockTxLength = 0
if !resBlock.BlockID.IsZero() {
resBlockTxLength = len(resBlock.Block.Txs)
}
// get the pending transaction count
pendingTxs, err := api.backend.PendingTransactions()
if err != nil {
return nil
}
txs = len(resBlock.Block.Txs) + len(pendingTxs)
txs = resBlockTxLength + len(pendingTxs)
case rpctypes.LatestBlockNumber:
height, err = api.backend.LatestBlockNumber()
resBlock, err := api.clientCtx.Client.Block(api.ctx, nil)
if err != nil {
return nil
}
resBlock, err := api.clientCtx.Client.Block(&height)
if err != nil {
return nil
var resBlockTxLength = 0
if !resBlock.BlockID.IsZero() {
resBlockTxLength = len(resBlock.Block.Txs)
}
txs = len(resBlock.Block.Txs)
txs = resBlockTxLength
default:
height = blockNum.Int64()
resBlock, err := api.clientCtx.Client.Block(&height)
resBlock, err := api.clientCtx.Client.Block(api.ctx, &height)
if err != nil {
return nil
}
@ -373,28 +377,37 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes
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 {
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 {
return 0
}
// 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) {
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 {
return nil, err
}
var out evmtypes.QueryResCode
api.clientCtx.Codec.MustUnmarshalJSON(res, &out)
return out.Code, nil
return res.Code, nil
}
// 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
txEncoder := authclient.GetTxEncoder(api.clientCtx.Codec)
txEncoder := api.clientCtx.TxConfig.TxEncoder()
txBytes, err := txEncoder(tx)
if err != nil {
return common.Hash{}, err
@ -491,14 +504,13 @@ func (api *PublicEthereumAPI) SendRawTransaction(data hexutil.Bytes) (common.Has
}
// Encode transaction by default Tx encoder
txEncoder := authclient.GetTxEncoder(api.clientCtx.Codec)
txBytes, err := txEncoder(tx)
txBytes, err := api.clientCtx.TxConfig.TxEncoder()(tx)
if err != nil {
return common.Hash{}, err
}
// 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)
if err != nil {
return common.Hash{}, err
@ -519,7 +531,7 @@ func (api *PublicEthereumAPI) Call(args rpctypes.CallArgs, blockNr rpctypes.Bloc
return []byte{}, err
}
data, err := evmtypes.DecodeResultData(simRes.Result.Data)
data, err := evmtypes.DecodeTxResponse(simRes.Result.Data)
if err != nil {
return []byte{}, err
}
@ -533,15 +545,18 @@ func (api *PublicEthereumAPI) doCall(
args rpctypes.CallArgs, blockNum rpctypes.BlockNumber, globalGasCap *big.Int,
) (*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
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 addr common.Address
var (
addr common.Address
err error
)
// Set sender address or use a default if none specified
if args.From == nil {
addrs, err := api.Accounts()
if err == nil && len(addrs) > 0 {
@ -554,7 +569,7 @@ func (api *PublicEthereumAPI) doCall(
nonce, _ := api.accountNonce(api.clientCtx, addr, true)
// 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)
if args.Gas != nil {
gas = uint64(*args.Gas)
@ -582,50 +597,90 @@ func (api *PublicEthereumAPI) doCall(
data = []byte(*args.Data)
}
var accNum, seq uint64
// Set destination address for call
var toAddr sdk.AccAddress
if args.To != nil {
toAddr = sdk.AccAddress(args.To.Bytes())
var fromAddr sdk.AccAddress
if args.From != nil {
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
// Create new call message
msg := evmtypes.NewMsgEthermint(nonce, &toAddr, sdk.NewIntFromBigInt(value), gas,
sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes()))
msg := evmtypes.NewMsgEthereumTx(seq, args.To, value, gas, gasPrice, data)
if err := msg.ValidateBasic(); err != nil {
return nil, err
}
msgs = append(msgs, msg)
feeAmount := big.NewInt(0)
// convert the pending transactions into ethermint msgs
if blockNum == rpctypes.PendingBlockNumber {
pendingMsgs, err := api.pendingMsgs()
pendingMsgs, fee, err := api.pendingMsgs()
if err != nil {
return nil, err
}
feeAmount = new(big.Int).Add(feeAmount, fee)
msgs = append(msgs, pendingMsgs...)
}
// Generate tx to be used to simulate (signature isn't needed)
var stdSig authtypes.StdSignature
stdSigs := []authtypes.StdSignature{stdSig}
tx := authtypes.NewStdTx(msgs, authtypes.StdFee{}, stdSigs, "")
if err := tx.ValidateBasic(); err != nil {
return nil, err
privKey, exists := rpctypes.GetKeyByAddress(api.keys, addr)
if !exists {
return nil, fmt.Errorf("account with address %s does not exist in keyring", addr.String())
}
txEncoder := authclient.GetTxEncoder(clientCtx.Codec)
txBytes, err := txEncoder(tx)
// NOTE: we query the EVM denomination to allow other chains to use their custom denomination as
// the fee token
paramsRes, err := api.queryClient.Params(api.ctx, &evmtypes.QueryParamsRequest{})
if err != nil {
return nil, err
}
// Transaction simulation through query
res, _, err := clientCtx.QueryWithData("app/simulate", txBytes)
// create the fee coins with the amount equal to the sum of all msg fees
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 {
return nil, err
}
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
}
@ -663,19 +718,15 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu
return api.backend.GetBlockByNumber(blockNum, fullTx)
}
height, err := api.backend.LatestBlockNumber()
if err != nil {
return nil, err
}
// latest block info
latestBlock, err := api.clientCtx.Client.Block(&height)
// fetch latest block
latestBlock, err := api.clientCtx.Client.Block(api.ctx, nil)
if err != nil {
return nil, err
}
// 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 {
return nil, err
}
@ -689,7 +740,7 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu
tmtypes.Header{
Version: latestBlock.Block.Version,
ChainID: api.clientCtx.ChainID,
Height: height + 1,
Height: latestBlock.Block.Height + 1,
Time: time.Unix(0, 0),
LastBlockID: latestBlock.Block.LastBlockID,
ValidatorsHash: latestBlock.Block.NextValidatorsHash,
@ -707,8 +758,7 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu
// GetTransactionByHash returns the transaction identified by hash.
func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) {
api.logger.Debug("eth_getTransactionByHash", "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 {
// check if the tx is on the mempool
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
block, err := api.clientCtx.Client.Block(&tx.Height)
block, err := api.clientCtx.Client.Block(api.ctx, &tx.Height)
if err != nil {
return nil, err
}
@ -748,19 +798,11 @@ func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.
// GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index.
func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.Transaction, error) {
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 {
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)
}
@ -768,7 +810,7 @@ func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash
func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) {
api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
var (
height int64
height *int64
err error
)
@ -789,16 +831,15 @@ func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpcty
return pendingTxs[int(idx)], nil
case rpctypes.LatestBlockNumber:
height, err = api.backend.LatestBlockNumber()
if err != nil {
return nil, err
}
// nil fetches the latest block
height = nil
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 {
return nil, err
}
@ -827,14 +868,14 @@ func (api *PublicEthereumAPI) getTransactionByBlockAndIndex(block *tmtypes.Block
// GetTransactionReceipt returns the transaction receipt identified by hash.
func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
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 {
// Return nil for transaction when not found
return nil, nil
}
// 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 {
return nil, err
}
@ -854,7 +895,7 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin
cumulativeGasUsed := uint64(tx.TxResult.GasUsed)
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
@ -867,13 +908,13 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin
txData := tx.TxResult.GetData()
data, err := evmtypes.DecodeResultData(txData)
data, err := evmtypes.DecodeTxResponse(txData)
if err != nil {
status = 0 // transaction failed
}
if len(data.Logs) == 0 {
data.Logs = []*ethtypes.Log{}
if len(data.TxLogs.Logs) == 0 {
data.TxLogs.Logs = []*evmtypes.Log{}
}
receipt := map[string]interface{}{
@ -881,7 +922,7 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin
"status": status,
"cumulativeGasUsed": hexutil.Uint64(cumulativeGasUsed),
"logsBloom": data.Bloom,
"logs": data.Logs,
"logs": data.TxLogs.EthLogs(),
// Implementation fields: These fields are added by geth when processing a transaction.
// 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
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))
path := fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryAccount, address.Hex())
// 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)
ctx := rpctypes.ContextWithHeight(height)
clientCtx := api.clientCtx.WithHeight(height)
// query storage proofs
storageProofs := make([]rpctypes.StorageResult, len(storageKeys))
opts := client.ABCIQueryOptions{Height: int64(block), Prove: true}
for i, k := range storageKeys {
// Get value for key
vPath := fmt.Sprintf("custom/%s/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryStorage, address, k)
vRes, err := api.clientCtx.Client.ABCIQueryWithOptions(vPath, nil, opts)
for i, key := range storageKeys {
hexKey := common.HexToHash(key)
valueBz, proof, err := api.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes()))
if err != nil {
return nil, err
}
var value evmtypes.QueryResStorage
clientCtx.Codec.MustUnmarshalJSON(vRes.Response.GetValue(), &value)
// check for proof
proof := vRes.Response.GetProof()
proofStr := new(merkle.Proof).String()
var proofStr string
if proof != nil {
proofStr = proof.String()
}
storageProofs[i] = rpctypes.StorageResult{
Key: k,
Value: (*hexutil.Big)(common.BytesToHash(value.Value).Big()),
Key: key,
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
Proof: []string{proofStr},
}
}
req := abci.RequestQuery{
Path: fmt.Sprintf("store/%s/key", auth.StoreKey),
Data: auth.AddressStoreKey(sdk.AccAddress(address.Bytes())),
Height: int64(block),
Prove: true,
// query EVM account
req := &evmtypes.QueryAccountRequest{
Address: address.String(),
}
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 {
return nil, err
}
// check for proof
accountProof := res.GetProof()
accProofStr := new(merkle.Proof).String()
if accountProof != nil {
accProofStr = accountProof.String()
var accProofStr string
if proof != nil {
accProofStr = proof.String()
}
balance := big.NewInt(0)
err = balance.UnmarshalText([]byte(res.Balance))
if err != nil {
return nil, err
}
return &rpctypes.AccountResult{
Address: address,
AccountProof: []string{accProofStr},
Balance: (*hexutil.Big)(utils.MustUnmarshalBigInt(account.Balance)),
CodeHash: common.BytesToHash(account.CodeHash),
Nonce: hexutil.Uint64(account.Nonce),
StorageHash: common.Hash{}, // Ethermint doesn't have a storage hash
Balance: (*hexutil.Big)(balance),
CodeHash: common.BytesToHash(res.CodeHash),
Nonce: hexutil.Uint64(res.Nonce),
StorageHash: common.Hash{}, // NOTE: Ethermint doesn't have a storage hash. TODO: implement?
StorageProof: storageProofs,
}, 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
var input []byte
var input hexutil.Bytes
if args.Input != nil {
input = *args.Input
} else if args.Data != nil {
@ -1044,7 +1082,7 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty
Gas: args.Gas,
GasPrice: args.GasPrice,
Value: args.Value,
Data: args.Data,
Data: &input,
}
gl, err := api.EstimateGas(callArgs)
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)
return &msg, nil
return msg, nil
}
// pendingMsgs constructs an array of sdk.Msg. This method will check pending transactions and convert
// those transactions into ethermint messages.
func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) {
// those transactions into ethereum messages. Alonside with the msgs it returns the total fees for all the
// pending txs.
func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, *big.Int, error) {
// nolint: prealloc
var msgs []sdk.Msg
feeAmount := big.NewInt(0)
pendingTxs, err := api.PendingTransactions()
if err != nil {
return nil, err
return nil, nil, err
}
for _, pendingTx := range pendingTxs {
// NOTE: we have to construct the EVM transaction instead of just casting from the tendermint
// 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())
if err != nil {
return nil, err
return nil, nil, err
}
pendingValue := pendingTx.Value.ToInt()
@ -1090,35 +1128,38 @@ func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) {
pendingData := pendingTx.Input
nonce, _ := api.accountNonce(api.clientCtx, pendingTx.From, true)
msg := evmtypes.NewMsgEthermint(nonce, &pendingTo, sdk.NewIntFromBigInt(pendingValue), pendingGas,
sdk.NewIntFromBigInt(pendingGasPrice), pendingData, pendingFrom)
msg := evmtypes.NewMsgEthereumTx(
0,
pendingTx.To,
pendingValue,
pendingGas,
pendingGasPrice,
pendingData,
)
feeAmount = new(big.Int).Add(feeAmount, msg.Fee())
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
// 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.
func (api *PublicEthereumAPI) accountNonce(
clientCtx clientcontext.CLIContext, address common.Address, pending bool,
clientCtx client.Context, address common.Address, pending bool,
) (uint64, error) {
// Get nonce (sequence) from sender account
from := sdk.AccAddress(address.Bytes())
// use a the given client context in case its wrapped with a custom height
accRet := authtypes.NewAccountRetriever(clientCtx)
if err := accRet.EnsureExists(from); err != nil {
account, err := clientCtx.AccountRetriever.GetAccount(clientCtx, from)
if err != nil || account == nil {
// account doesn't exist yet, return 0
return 0, nil
}
_, nonce, err := accRet.GetAccountNumberSequence(from)
if err != nil {
return 0, err
}
nonce := account.GetSequence()
if !pending {
return nonce, nil
@ -1131,15 +1172,17 @@ func (api *PublicEthereumAPI) accountNonce(
return 0, err
}
if len(pendingTxs) == 0 {
return nonce, nil
}
// add the uncommitted txs to the nonce counter
if len(pendingTxs) != 0 {
for i := range pendingTxs {
if pendingTxs[i] == nil {
continue
}
if pendingTxs[i].From == address {
nonce++
}
for i := range pendingTxs {
if pendingTxs[i] == nil {
continue
}
if pendingTxs[i].From == address {
nonce++
}
}

View File

@ -6,6 +6,8 @@ import (
"sync"
"time"
"github.com/gogo/protobuf/proto"
coretypes "github.com/tendermint/tendermint/rpc/core/types"
tmtypes "github.com/tendermint/tendermint/types"
@ -14,7 +16,7 @@ import (
"github.com/ethereum/go-ethereum/eth/filters"
"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"
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
// information related to the Ethereum protocol such as blocks, transactions and logs.
type PublicFilterAPI struct {
clientCtx clientcontext.CLIContext
clientCtx client.Context
backend Backend
events *EventSystem
filtersMu sync.Mutex
@ -56,13 +58,7 @@ type PublicFilterAPI struct {
}
// NewAPI returns a new PublicFilterAPI instance.
func NewAPI(clientCtx clientcontext.CLIContext, backend Backend) *PublicFilterAPI {
// start the client to subscribe to Tendermint events
err := clientCtx.Client.Start()
if err != nil {
panic(err)
}
func NewAPI(clientCtx client.Context, backend Backend) *PublicFilterAPI {
api := &PublicFilterAPI{
clientCtx: clientCtx,
backend: backend,
@ -122,7 +118,8 @@ func (api *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID {
select {
case ev := <-txsCh:
data, _ := ev.Data.(tmtypes.EventDataTx)
txHash := common.BytesToHash(data.Tx.Hash())
txHash := common.BytesToHash(tmtypes.Tx(data.Tx).Hash())
api.filtersMu.Lock()
if f, found := api.filters[pendingTxSub.ID()]; found {
@ -167,7 +164,7 @@ func (api *PublicFilterAPI) NewPendingTransactions(ctx context.Context) (*rpc.Su
select {
case ev := <-txsCh:
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.
// 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 {
case event := <-logsCh:
// filter only events from EVM module txs
_, isMsgEthermint := event.Events[evmtypes.TypeMsgEthermint]
_, isMsgEthereumTx := event.Events[evmtypes.TypeMsgEthereumTx]
if !(isMsgEthermint || isMsgEthereumTx) {
if !isMsgEthereumTx {
// ignore transaction as it's not from the evm module
return
}
@ -313,12 +309,13 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri
return
}
resultData, err := evmtypes.DecodeResultData(dataTx.TxResult.Result.Data)
var txResponse evmtypes.MsgEthereumTxResponse
err := proto.Unmarshal(dataTx.TxResult.Result.Data, &txResponse)
if err != nil {
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 {
err = notifier.Notify(rpcSub.ID, log)
@ -381,13 +378,12 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID,
return
}
var resultData evmtypes.ResultData
resultData, err = evmtypes.DecodeResultData(dataTx.TxResult.Result.Data)
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
if err != nil {
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()
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) {
data, _ := ev.Data.(tmtypes.EventDataTx)
resultData, err := evmtypes.DecodeResultData(data.TxResult.Result.Data)
txResponse, err := evmtypes.DecodeTxResponse(data.TxResult.Result.Data)
if err != nil {
return
}
if len(resultData.Logs) == 0 {
if len(txResponse.TxLogs.Logs) == 0 {
return
}
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 {
f.logs <- matchedLogs
}
@ -272,7 +272,7 @@ func (es *EventSystem) handleLogs(ev coretypes.ResultEvent) {
func (es *EventSystem) handleTxsEvent(ev coretypes.ResultEvent) {
data, _ := ev.Data.(tmtypes.EventDataTx)
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"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/rpc"
coretypes "github.com/tendermint/tendermint/rpc/core/types"
)

View File

@ -3,7 +3,8 @@ package net
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client"
ethermint "github.com/cosmos/ethermint/types"
)
@ -13,7 +14,7 @@ type PublicNetAPI struct {
}
// 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
chainIDEpoch, err := ethermint.ParseChainID(clientCtx.ChainID)
if err != nil {

View File

@ -7,10 +7,12 @@ import (
"os"
"time"
"github.com/cosmos/ethermint/crypto/hd"
ethermint "github.com/cosmos/ethermint/types"
"github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey"
sdkcrypto "github.com/cosmos/cosmos-sdk/crypto"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
@ -18,7 +20,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
"github.com/cosmos/ethermint/crypto/hd"
"github.com/cosmos/ethermint/rpc/namespaces/eth"
rpctypes "github.com/cosmos/ethermint/rpc/types"
)
@ -27,7 +28,7 @@ import (
type PrivateAccountAPI struct {
ethAPI *eth.PublicEthereumAPI
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.
@ -42,7 +43,7 @@ func NewAPI(ethAPI *eth.PublicEthereumAPI) *PrivateAccountAPI {
return api
}
api.keyInfos, err = api.ethAPI.ClientCtx().Keybase.List()
api.keyInfos, err = api.ethAPI.ClientCtx().Keyring.List()
if err != nil {
return api
}
@ -61,27 +62,27 @@ func (api *PrivateAccountAPI) ImportRawKey(privkey, password string) (common.Add
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
list, _ := api.ethAPI.ClientCtx().Keybase.List()
list, _ := api.ethAPI.ClientCtx().Keyring.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
}
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 {
return common.Address{}, err
}
// 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.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:])
api.ethAPI.SetKeys(tmp)
api.logger.Debug("account unlocked", "address", address.String())
api.logger.Debug("account locked", "address", address.String())
return true
}
@ -128,16 +129,33 @@ func (api *PrivateAccountAPI) NewAccount(password string) (common.Address, error
api.logger.Debug("personal_newAccount")
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 {
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)
addr := common.BytesToAddress(info.GetPubKey().Address().Bytes())
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!")
return addr, nil
}
@ -150,7 +168,7 @@ func (api *PrivateAccountAPI) UnlockAccount(_ context.Context, addr common.Addre
api.logger.Debug("personal_unlockAccount", "address", addr.String())
// TODO: use duration
var keyInfo keys.Info
var keyInfo keyring.Info
for _, info := range api.keyInfos {
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())
}
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 {
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 {
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())
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) {
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)
if !ok {
return nil, fmt.Errorf("cannot find key with address %s", addr.String())

View File

@ -1,11 +1,16 @@
package types
import (
"context"
"fmt"
"math"
"math/big"
"strings"
"google.golang.org/grpc/metadata"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
"github.com/ethereum/go-ethereum/common/hexutil"
)
@ -28,6 +33,16 @@ func NewBlockNumber(n *big.Int) BlockNumber {
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:
// - "latest", "earliest" or "pending" as string arguments
// - 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"
tmtypes "github.com/tendermint/tendermint/types"
clientcontext "github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/client"
"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"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
@ -23,17 +25,17 @@ import (
)
// RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes.
func RawTxToEthTx(clientCtx clientcontext.CLIContext, bz []byte) (*evmtypes.MsgEthereumTx, error) {
tx, err := evmtypes.TxDecoder(clientCtx.Codec)(bz)
func RawTxToEthTx(clientCtx client.Context, bz []byte) (*evmtypes.MsgEthereumTx, error) {
tx, err := clientCtx.TxConfig.TxDecoder()(bz)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
ethTx, ok := tx.(evmtypes.MsgEthereumTx)
ethTx, ok := tx.(*evmtypes.MsgEthereumTx)
if !ok {
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
@ -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.
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)
if err != nil {
return nil, err
@ -80,15 +82,15 @@ func EthBlockFromTendermint(clientCtx clientcontext.CLIContext, block *tmtypes.B
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 {
return nil, err
}
var bloomRes evmtypes.QueryBloomFilter
clientCtx.Codec.MustUnmarshalJSON(res, &bloomRes)
bloom := bloomRes.Bloom
bloom := ethtypes.BytesToBloom(res.Bloom)
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
// 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{}
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.
func BlockMaxGasFromConsensusParams(_ context.Context, clientCtx clientcontext.CLIContext) (int64, error) {
resConsParams, err := clientCtx.Client.ConsensusParams(nil)
func BlockMaxGasFromConsensusParams(ctx context.Context, clientCtx client.Context) (int64, error) {
resConsParams, err := clientCtx.Client.ConsensusParams(ctx, nil)
if err != nil {
return 0, err
}
@ -194,12 +196,58 @@ func GetKeyByAddress(keys []ethsecp256k1.PrivKey, address common.Address) (key *
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
// transaction index. The returned gas used includes the gas from both the SDK and
// 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
txDecoder := evmtypes.TxDecoder(cdc)
txDecoder := clientCtx.TxConfig.TxDecoder()
for i := 0; i < idx && i < len(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) {
case authtypes.StdTx:
case *evmtypes.MsgEthereumTx:
gasUsed += tx.GetGas()
case evmtypes.MsgEthereumTx:
case sdk.FeeTx:
gasUsed += tx.GetGas()
}
}

View File

@ -15,7 +15,7 @@ import (
"github.com/ethereum/go-ethereum/eth/filters"
"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"
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
type PubSubAPI struct {
clientCtx context.CLIContext
clientCtx client.Context
events *rpcfilters.EventSystem
filtersMu sync.Mutex
filters map[rpc.ID]*wsSubscription
@ -32,7 +32,7 @@ type PubSubAPI struct {
}
// NewAPI creates an instance of the ethereum PubSub API.
func NewAPI(clientCtx context.CLIContext) *PubSubAPI {
func NewAPI(clientCtx client.Context) *PubSubAPI {
return &PubSubAPI{
clientCtx: clientCtx,
events: rpcfilters.NewEventSystem(clientCtx.Client),
@ -79,6 +79,19 @@ func (api *PubSubAPI) unsubscribe(id rpc.ID) bool {
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) {
sub, _, err := api.events.SubscribeNewHeads()
if err != nil {
@ -209,13 +222,13 @@ func (api *PubSubAPI) subscribeLogs(conn *websocket.Conn, extra interface{}) (rp
return
}
var resultData evmtypes.ResultData
resultData, err = evmtypes.DecodeResultData(dataTx.TxResult.Result.Data)
var resultData evmtypes.MsgEthereumTxResponse
resultData, err = evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
if err != nil {
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()
if f, found := api.filters[sub.ID()]; found {
@ -271,7 +284,7 @@ func (api *PubSubAPI) subscribePendingTransactions(conn *websocket.Conn) (rpc.ID
select {
case ev := <-txsCh:
data, _ := ev.Data.(tmtypes.EventDataTx)
txHash := common.BytesToHash(data.Tx.Hash())
txHash := common.BytesToHash(tmtypes.Tx(data.Tx).Hash())
api.filtersMu.Lock()
if f, found := api.filters[sub.ID()]; found {

View File

@ -12,48 +12,32 @@ import (
"os"
"strings"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log"
"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.
type Server struct {
rpcAddr string // listen address of rest-server
wsAddr string // listen address of ws server
Address string
api *PubSubAPI
logger log.Logger
}
// NewServer creates a new websocket server instance.
func NewServer(clientCtx context.CLIContext, wsAddr string) *Server {
func NewServer(clientCtx client.Context) *Server {
return &Server{
rpcAddr: viper.GetString("laddr"),
wsAddr: wsAddr,
Address: "",
api: NewAPI(clientCtx),
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) {
var upgrader = websocket.Upgrader{
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)
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
}
@ -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
// to the client over websockets
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 {
return fmt.Errorf("invalid laddr %s", s.rpcAddr)
return fmt.Errorf("invalid laddr %s", s.Address)
}
tcpConn, err := net.Dial("tcp", addr[1])
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{}
@ -179,7 +164,7 @@ func (s *Server) tcpGetAndSendResponse(conn *websocket.Conn, mb []byte) error {
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 {
return fmt.Errorf("failed to request; %s", err)
}

View File

@ -1,69 +1,63 @@
#!/bin/bash
KEY="mykey"
TESTKEY="test"
CHAINID="ethermint-100"
MONIKER="localtestnet"
# stop and remove existing daemon and client data and process(es)
rm -rf $PWD/.ethermint*
rm -rf ~/.ethermint*
pkill -f "ethermint*"
make build-ethermint
$PWD/build/ethermintcli config keyring-backend test
# 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
# if $KEY exists it should be override
"$PWD"/build/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)
$PWD/build/ethermintd init $MONIKER --chain-id $CHAINID
"$PWD"/build/ethermintd init $MONIKER --chain-id $CHAINID
# 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/.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/.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/.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["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/.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/.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/.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)
$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
$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
$PWD/build/ethermintd collect-gentxs
"$PWD"/build/ethermintd collect-gentxs
# 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
$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
$PWD/build/ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key $KEY --chain-id $CHAINID --trace --rpc-api="web3,eth,net,personal" > ethermintcli.log &
solcjs --abi "$PWD"/tests-solidity/suites/basic/contracts/Counter.sol --bin -o "$PWD"/tests-solidity/suites/basic/counter
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
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
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
# Query for the account
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[^"]*')
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
PRIVKEY="$("$PWD"/build/ethermintcli keys unsafe-export-eth-key $KEY)"
echo $PRIVKEY
#PRIVKEY="$("$PWD"/build/ethermintd keys export $KEY)"
## 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
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
RPC_PORT="854"
IP_ADDR="0.0.0.0"
@ -29,10 +32,11 @@ usage() {
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"
echo "-r <string> -- Remove test dir after, eg: true, default is false"
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
h|\?)
usage;
@ -42,6 +46,7 @@ while getopts "h?t:q:z:s:m:" args; do
z ) TEST_QTD=${OPTARG};;
s ) SLEEP_TIMEOUT=${OPTARG};;
m ) MODE=${OPTARG};;
r ) REMOVE_DATA_DIR=${OPTARG};;
esac
done
@ -54,13 +59,6 @@ if [[ ! "$DATA_DIR" ]]; then
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
@ -68,34 +66,30 @@ make build-ethermint
# PID array declaration
arr=()
# PID arraycli declaration
arrcli=()
init_func() {
echo "create and add new keys"
"$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 keys add $KEY"$i" --keyring-backend test --home "$DATA_DIR$i" --no-backup --algo "eth_secp256k1"
"$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/ethermintcli 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 keys show "$KEY$i" --keyring-backend test -a --home "$DATA_DIR$i")" 1000000000000000000aphoton,1000000000000000000stake \
--keyring-backend test --home "$DATA_DIR$i"
"$PWD"/build/ethermintd gentx "$KEY$i" 1000000000000000000stake --amount=1000000000000000000aphoton --chain-id $CHAINID --keyring-backend test --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"
if [[ $MODE == "pending" ]]; then
ls $DATA_DIR$i
# sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $DATA_DIR$i/config/config.toml
ls $DATA_DIR$i
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_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
@ -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_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
fi
fi
}
start_func() {
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" \
--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
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/ethermintcli rest-server --unlock-key $KEY"$i" --chain-id $CHAINID --trace --rpc-api="web3,eth,net,personal" \
--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 \
>"$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")
if [[ $MODE == "pending" ]]; then
echo "waiting for the first block..."
sleep 300
fi
}
# Run node with static blockchain database
@ -138,7 +128,6 @@ 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"
@ -150,37 +139,37 @@ echo "done sleeping"
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
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
echo "going to test ethermint node $HOST_RPC ..."
if [[ $MODE == "pending" ]]; then
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
MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=$time_out -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"
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
stop_func "$i"
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() {
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
fi
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_doc
proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq)
for dir in $proto_dirs; do
buf protoc \
-I "proto" \
-I "third_party/proto" \
--gocosmos_out=plugins=interfacetype+grpc,\
Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \
--gocosmos_out=plugins=interfacetype+grpc:. \
$(find "${dir}" -maxdepth 1 -name '*.proto')
# 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
# generate codec/testdata proto code
buf protoc -I "proto" -I "third_party/proto" -I "testutil/testdata" --gocosmos_out=plugins=interfacetype+grpc,\
Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. ./testutil/testdata/*.proto
# command to generate docs using protoc-gen-doc
buf protoc \
-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
cp -r github.com/cosmos/ethermint/* ./

View File

@ -3,13 +3,18 @@
export GOPATH=~/go
export PATH=$PATH:$GOPATH/bin
go build -o ./build/ethermintd ./cmd/ethermintd
go build -o ./build/ethermintcli ./cmd/ethermintcli
mkdir $GOPATH/bin
cp ./build/ethermintd $GOPATH/bin
cp ./build/ethermintcli $GOPATH/bin
localKeyAddr=0x7cb61d4117ae31a12e393a1cfa3bac666481d02e
user1Addr=0xc6fe5d33615a1c52c08018c47e8bc53646a0e101
user2Addr=0x963ebdf2e1f8db8707d05fc75bfeffba1b5bac17
CHAINID="ethermint-1337"
# build ethermint binary
make install
cd tests-solidity
if command -v yarn &> /dev/null; then
@ -22,11 +27,22 @@ else
fi
chmod +x ./init-test-node.sh
./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 &
nohup ./init-test-node.sh > ethermintd.log 2>&1 &
# 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
yarn contract-migrate
yarn test-ethermint
ok=$?
@ -35,7 +51,6 @@ if (( $? != 0 )); then
echo "initializable test failed: exit code $?"
fi
killall ethermintcli
killall ethermintd
echo "Script exited with code $ok"
@ -43,10 +58,7 @@ exit $ok
# initializable-buidler fails on CI, re-add later
./../../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 &
./../../init-test-node.sh > ethermintd.log
cd ../initializable-buidler
yarn test-ethermint
@ -56,7 +68,6 @@ if (( $? != 0 )); then
echo "initializable-buidler test failed: exit code $?"
fi
killall ethermintcli
killall ethermintd
echo "Script exited with code $ok"

View File

@ -1,5 +1,176 @@
#!/bin/sh
ethermintd --home /ethermint/node$ID/ethermintd/ start > ethermintd.log &
sleep 5
ethermintcli rest-server --laddr "tcp://localhost:8545" --chain-id "ethermint-7305661614933169792" --trace --rpc-api="web3,eth,net,personal" > ethermintcli.log &
tail -f /dev/null
#!/bin/bash
# "stable" mode tests assume data is static
# "live" mode tests assume data dynamic
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
**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`.
@ -22,10 +22,10 @@ In the first, run `ethermintd`:
./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
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:
@ -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:
- `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}'`
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).
Running `ethermintcli list keys` should output:
Running `ethermintd list keys` should output:
```json
[

View File

@ -3,41 +3,35 @@
CHAINID="ethermint-1337"
MONIKER="localtestnet"
# localKey address 0x7cb61d4117ae31a12e393a1cfa3bac666481d02e
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"
# user1 address 0xc6fe5d33615a1c52c08018c47e8bc53646a0e101
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"
# user2 address 0x963ebdf2e1f8db8707d05fc75bfeffba1b5bac17
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"
# remove existing daemon and client
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
echo $VAL_MNEMONIC | ethermintcli keys add $VAL_KEY --recover
echo $USER1_MNEMONIC | ethermintcli keys add $USER1_KEY --recover
echo $USER2_MNEMONIC | ethermintcli keys add $USER2_KEY --recover
echo $VAL_MNEMONIC | ethermintd keys add $VAL_KEY --recover --keyring-backend test --algo "eth_secp256k1"
echo $USER1_MNEMONIC | ethermintd keys add $USER1_KEY --recover --keyring-backend test --algo "eth_secp256k1"
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
# Allocate genesis accounts (cosmos formatted addresses)
ethermintd add-genesis-account $(ethermintcli keys show $VAL_KEY -a) 1000000000000000000000aphoton,10000000000000000stake
ethermintd add-genesis-account $(ethermintcli keys show $USER1_KEY -a) 1000000000000000000000aphoton,10000000000000000stake
ethermintd add-genesis-account $(ethermintcli keys show $USER2_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 "$(ethermintd keys show $USER1_KEY -a --keyring-backend test)" 1000000000000000000000aphoton,1000000000000000000stake --keyring-backend test
ethermintd add-genesis-account "$(ethermintd keys show $USER2_KEY -a --keyring-backend test)" 1000000000000000000000aphoton,1000000000000000000stake --keyring-backend test
# 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
ethermintd collect-gentxs
@ -45,9 +39,5 @@ ethermintd collect-gentxs
# Run this to ensure everything worked and that the genesis file is setup correctly
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)
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>",
"license": "GPL-3.0-or-later",
"scripts": {
"contract-compile": "yarn truffle compile",
"contract-migrate": "yarn truffle migrate --network ethermint",
"test-ganache": "yarn truffle test",
"test-ethermint": "yarn truffle test --network ethermint"
},
"devDependencies": {
"@aragon/contract-helpers-test": "^0.1.0",
"chai": "^4.2.0",
"truffle": "^5.1.42",
"web3": "^1.2.11"
"truffle": "^5.2.5",
"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) {
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
err := json.Unmarshal(rpcRes.Result, &res)
require.NoError(t, err)

View File

@ -1,9 +1,8 @@
// This is a test utility for Ethermint's Web3 JSON-RPC services.
//
// 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
import (
@ -55,6 +54,33 @@ func TestMain(m *testing.M) {
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) {
hash := DeployTestContractWithFunction(t, from)
receipt := WaitForReceipt(t, hash)
@ -72,20 +98,6 @@ func TestBlockBloom(t *testing.T) {
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) {
// TODO: this test passes on when run on its own, but fails when run with the other tests
if testing.Short() {
@ -115,18 +127,6 @@ func TestEth_GetLogs_Topics_AB(t *testing.T) {
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) {
// TODO: this test passes on when run on its own, but fails when run with the other tests
if testing.Short() {
@ -205,7 +205,8 @@ func TestEth_GetBalance(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}
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
err := storage.UnmarshalJSON(rpcRes.Result)
@ -220,7 +221,8 @@ func TestEth_GetProof(t *testing.T) {
params := make([]interface{}, 3)
params[0] = addrA
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)
require.NotNil(t, rpcRes)
@ -255,7 +257,10 @@ func TestEth_SendTransaction_Transfer(t *testing.T) {
param[0]["gasLimit"] = "0x5208"
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
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]["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
err := json.Unmarshal(rpcRes.Result, &hash)
@ -369,12 +377,15 @@ func TestEth_GetTransactionReceipt(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)
time.Sleep(time.Second * 5)
param := []string{hash.String()}
rpcRes := Call(t, "eth_getTransactionReceipt", param)
rpcRes = Call(t, "eth_getTransactionReceipt", param)
receipt := make(map[string]interface{})
err := json.Unmarshal(rpcRes.Result, &receipt)
@ -410,11 +421,7 @@ func TestEth_GetFilterChanges_NoTopics(t *testing.T) {
// get filter changes
changesRes := Call(t, "eth_getFilterChanges", []string{ID})
var logs []*ethtypes.Log
err = json.Unmarshal(changesRes.Result, &logs)
require.NoError(t, err)
require.Equal(t, 1, len(logs))
require.Equal(t, 2, len(changesRes.Result))
}
func TestEth_GetFilterChanges_Addresses(t *testing.T) {
@ -458,12 +465,7 @@ func TestEth_GetFilterChanges_Topics_AB(t *testing.T) {
// get filter changes
changesRes := Call(t, "eth_getFilterChanges", []string{ID})
var logs []*ethtypes.Log
err = json.Unmarshal(changesRes.Result, &logs)
require.NoError(t, err)
require.Equal(t, 1, len(logs))
require.Equal(t, 2, len(changesRes.Result))
}
func TestEth_GetFilterChanges_Topics_XB(t *testing.T) {
@ -488,12 +490,7 @@ func TestEth_GetFilterChanges_Topics_XB(t *testing.T) {
// get filter changes
changesRes := Call(t, "eth_getFilterChanges", []string{ID})
var logs []*ethtypes.Log
err = json.Unmarshal(changesRes.Result, &logs)
require.NoError(t, err)
require.Equal(t, 1, len(logs))
require.Equal(t, 2, len(changesRes.Result))
}
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]["to"] = "0x1122334455667788990011223344556677889900"
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.NotEmpty(t, rpcRes.Result)
@ -540,7 +541,7 @@ func TestEth_EstimateGas(t *testing.T) {
err := json.Unmarshal(rpcRes.Result, &gas)
require.NoError(t, err, string(rpcRes.Result))
require.Equal(t, "0xf560", gas)
require.Equal(t, "0xfab9", gas)
}
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]["data"] = bytecode
rpcRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""})
require.NotNil(t, rpcRes)
rpcRes = Call(t, "eth_estimateGas", param)
require.NotNil(t, rpcRes)
require.NotEmpty(t, rpcRes.Result)
@ -566,7 +570,7 @@ func TestEth_EstimateGas_ContractDeployment(t *testing.T) {
err := json.Unmarshal(rpcRes.Result, &gas)
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) {

View File

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