conflicts
This commit is contained in:
parent
20f9a72908
commit
5a3d514ba0
@ -113,4 +113,3 @@ Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
|
48
.github/workflows/release-sims.yml
vendored
48
.github/workflows/release-sims.yml
vendored
@ -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
|
||||
|
18
.github/workflows/test.yml
vendored
18
.github/workflows/test.yml
vendored
@ -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
1
.gitignore
vendored
@ -37,6 +37,7 @@ coverage.txt
|
||||
*.out
|
||||
sim_log_file
|
||||
importer/tmp
|
||||
yarn.lock
|
||||
|
||||
# Vagrant
|
||||
.vagrant/
|
||||
|
@ -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:
|
||||
|
@ -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
76
Makefile
Normal file → Executable 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
|
||||
|
||||
|
154
app/ante/ante.go
154
app/ante/ante.go
@ -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)
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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 account’s
|
||||
// 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)
|
||||
|
@ -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 := ðsecp256k1.PrivKey{Key: priv.Bytes()}
|
||||
|
||||
if err := msg.Sign(chainIDEpoch, privkey.ToECDSA()); err != nil {
|
||||
return nil, err
|
||||
|
72
app/encoding.go
Normal file
72
app/encoding.go
Normal 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, ðtx)
|
||||
if err == nil {
|
||||
return ðtx, nil
|
||||
}
|
||||
|
||||
return g.TxConfig.TxDecoder()(txBytes)
|
||||
}
|
||||
}
|
577
app/ethermint.go
577
app/ethermint.go
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
117
app/export.go
117
app/export.go
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -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,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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, ðsecp256k1.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)
|
||||
|
@ -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
61
client/keys/keys.go
Normal 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
358
client/keys/keysadd.go
Normal 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
103
client/keys/utils.go
Normal 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)
|
||||
}
|
@ -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, ðermint.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 {
|
||||
|
@ -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
|
||||
}
|
28
cmd/ethermintd/cmd_test.go
Normal file
28
cmd/ethermintd/cmd_test.go
Normal 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)
|
||||
}
|
@ -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 = ðermint.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
|
||||
}
|
||||
|
@ -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
233
cmd/ethermintd/root.go
Normal 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)
|
||||
}
|
@ -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
28
crypto/codec/amino.go
Normal 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(ðsecp256k1.PubKey{},
|
||||
ethsecp256k1.PubKeyName, nil)
|
||||
cdc.RegisterConcrete(ðsecp256k1.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
13
crypto/codec/codec.go
Normal 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), ðsecp256k1.PubKey{})
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
504
crypto/ethsecp256k1/keys.pb.go
Normal file
504
crypto/ethsecp256k1/keys.pb.go
Normal 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")
|
||||
)
|
@ -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 ðsecp256k1.PrivKey{Key: bzArr}
|
||||
}
|
||||
}
|
||||
|
@ -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
749
docs/core/proto-docs.md
Normal 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
105
docs/protodoc-markdown.tmpl
Normal 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
33
go.mod
@ -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
341
go.sum
@ -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=
|
||||
|
@ -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
74
init.sh
@ -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
|
||||
|
@ -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"]
|
@ -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"
|
||||
];
|
||||
|
50
rpc/apis.go
50
rpc/apis.go
@ -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{
|
||||
|
@ -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
|
||||
}
|
||||
|
21
rpc/cmd.go
21
rpc/cmd.go
@ -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
|
||||
}
|
107
rpc/config.go
107
rpc/config.go
@ -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
|
||||
}
|
||||
|
@ -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++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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())}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 := ðsecp256k1.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, ðsecp256k1.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())
|
||||
|
@ -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
61
rpc/types/query_client.go
Normal 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
|
||||
}
|
@ -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 ðTx, 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()
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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*"
|
@ -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
155
scripts/proto-tools-installer.sh
Executable 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
|
@ -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/* ./
|
||||
|
@ -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"
|
||||
|
181
scripts/start.sh
181
scripts/start.sh
@ -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
70
server/config/config.go
Normal 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
225
server/config/toml.go
Normal 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
29
server/flags.go
Normal 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"
|
||||
)
|
90
server/services/jsonrpc/service.go
Normal file
90
server/services/jsonrpc/service.go
Normal 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
|
||||
}
|
57
server/services/websocket/service.go
Normal file
57
server/services/websocket/service.go
Normal 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
331
server/start.go
Normal 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
199
server/util.go
Normal 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,
|
||||
)
|
||||
}
|
@ -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
|
||||
[
|
||||
|
@ -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"
|
||||
|
@ -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
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
62
third_party/proto/cosmos/auth/v1beta1/auth.proto
vendored
Normal file
62
third_party/proto/cosmos/auth/v1beta1/auth.proto
vendored
Normal 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\""
|
||||
];
|
||||
}
|
17
third_party/proto/cosmos/auth/v1beta1/genesis.proto
vendored
Normal file
17
third_party/proto/cosmos/auth/v1beta1/genesis.proto
vendored
Normal 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;
|
||||
}
|
48
third_party/proto/cosmos/auth/v1beta1/query.proto
vendored
Normal file
48
third_party/proto/cosmos/auth/v1beta1/query.proto
vendored
Normal 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 ];
|
||||
}
|
94
third_party/proto/cosmos/bank/v1beta1/bank.proto
vendored
Normal file
94
third_party/proto/cosmos/bank/v1beta1/bank.proto
vendored
Normal 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;
|
||||
}
|
45
third_party/proto/cosmos/bank/v1beta1/genesis.proto
vendored
Normal file
45
third_party/proto/cosmos/bank/v1beta1/genesis.proto
vendored
Normal 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
|
||||
];
|
||||
}
|
116
third_party/proto/cosmos/bank/v1beta1/query.proto
vendored
Normal file
116
third_party/proto/cosmos/bank/v1beta1/query.proto
vendored
Normal 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 ];
|
||||
}
|
29
third_party/proto/cosmos/bank/v1beta1/tx.proto
vendored
Normal file
29
third_party/proto/cosmos/bank/v1beta1/tx.proto
vendored
Normal 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 ];
|
||||
}
|
153
third_party/proto/cosmos/base/abci/v1beta1/abci.proto
vendored
Normal file
153
third_party/proto/cosmos/base/abci/v1beta1/abci.proto
vendored
Normal 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;
|
||||
}
|
15
third_party/proto/cosmos/base/kv/v1beta1/kv.proto
vendored
Normal file
15
third_party/proto/cosmos/base/kv/v1beta1/kv.proto
vendored
Normal 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;
|
||||
}
|
50
third_party/proto/cosmos/base/query/v1beta1/pagination.proto
vendored
Normal file
50
third_party/proto/cosmos/base/query/v1beta1/pagination.proto
vendored
Normal 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;
|
||||
}
|
46
third_party/proto/cosmos/base/reflection/v1beta1/reflection.proto
vendored
Normal file
46
third_party/proto/cosmos/base/reflection/v1beta1/reflection.proto
vendored
Normal 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;
|
||||
}
|
33
third_party/proto/cosmos/base/simulate/v1beta1/simulate.proto
vendored
Normal file
33
third_party/proto/cosmos/base/simulate/v1beta1/simulate.proto
vendored
Normal 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;
|
||||
}
|
20
third_party/proto/cosmos/base/snapshots/v1beta1/snapshot.proto
vendored
Normal file
20
third_party/proto/cosmos/base/snapshots/v1beta1/snapshot.proto
vendored
Normal 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
|
||||
}
|
29
third_party/proto/cosmos/base/store/v1beta1/commit_info.proto
vendored
Normal file
29
third_party/proto/cosmos/base/store/v1beta1/commit_info.proto
vendored
Normal 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;
|
||||
}
|
26
third_party/proto/cosmos/base/store/v1beta1/snapshot.proto
vendored
Normal file
26
third_party/proto/cosmos/base/store/v1beta1/snapshot.proto
vendored
Normal 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;
|
||||
}
|
44
third_party/proto/cosmos/base/v1beta1/coin.proto
vendored
Normal file
44
third_party/proto/cosmos/base/v1beta1/coin.proto
vendored
Normal 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 ];
|
||||
}
|
20
third_party/proto/cosmos/crypto/ed25519/keys.proto
vendored
Normal file
20
third_party/proto/cosmos/crypto/ed25519/keys.proto
vendored
Normal 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; }
|
20
third_party/proto/cosmos/crypto/multisig/keys.proto
vendored
Normal file
20
third_party/proto/cosmos/crypto/multisig/keys.proto
vendored
Normal 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
Loading…
Reference in New Issue
Block a user