Compare commits

..
8 Commits
Author SHA1 Message Date
Sai Kumar 5a6e2ec46f Integrate graphql server (#5)
* WIP: migrating the nameservice module

* WIP: migrating the nameservice module from dxns to ethermint

* refactor: move the proto package version from `v1` to `v1beta1` for vulcanize modules

* refactor: added bond module dependency to nameserivce module

* feat: added graphql for bond module

* feat: added auction module dependency to nameservice module

* refactor: refactored the nameservice module

* refactor: add human-readable attributes output to cli nameservice `list`

* WIP: add grpc query test cases

* fix: fix the sub names authority storing issue

* WIP: add the test cases

* refactor: removed legacyCodec from nameservice

* fix: fix the responses for `authority-expiry` and `records-expiry` commands query result

* refactor: sort the imports in app

* WIP:  add test cases for cli query, tx for nameservice module

* feat: add test cases for grpc of nameservice module

1. renamed grpc gateway routes from ethermint to vulcanize

* refactor: refactored the test cases for grpc lookup of nameservice

* refactor: refactored the test cases for bond module

* feat: add node status for gql

* feat: add get actions by ids in gql

* feat: add lookup authorities,resolve name, lookup name queries to gql

* updated readme file
2021-10-14 11:00:39 +05:30
Bipul Prasadandbipulprasad 34cc262218 Test cases for auction module (#8)
* Adding test cases for auction module

* Adding missing test cases and fixing failed ones

* Increasing the account balance to prevent test failures

* Addressing review comments

* Renaming test files as per directory structure

* Minor modification as per review comments

* Fixing test issues

Co-authored-by: bipulprasad <Bipul@qubecinema.com>
2021-10-14 10:49:37 +05:30
Sai Kumar db925906f3 Nameservice module cli, grpc test cases (#7)
* WIP: migrating the nameservice module

* WIP: migrating the nameservice module from dxns to ethermint

* refactor: move the proto package version from `v1` to `v1beta1` for vulcanize modules

* refactor: added bond module dependency to nameserivce module

* feat: added auction module dependency to nameservice module

* refactor: refactored the nameservice module

* refactor: add human-readable attributes output to cli nameservice `list`

* WIP: add grpc query test cases

* fix: fix the sub names authority storing issue

* WIP: add the test cases

* refactor: removed legacyCodec from nameservice

* fix: fix the responses for `authority-expiry` and `records-expiry` commands query result

* refactor: sort the imports in app

* WIP:  add test cases for cli query, tx for nameservice module

* feat: add test cases for grpc of nameservice module

1. renamed grpc gateway routes from ethermint to vulcanize

* refactor: refactored the test cases for grpc lookup of nameservice

* refactor: refactored the test cases for bond module
2021-10-13 12:07:19 +05:30
Sai Kumar 95dde36e1c Migrating the nameservice module from dxns (#2)
* WIP: migrating the nameservice module

* WIP: migrating the nameservice module from dxns to ethermint

* refactor: move the proto package version from `v1` to `v1beta1` for vulcanize modules

* refactor: added bond module dependency to nameserivce module

* feat: added auction module dependency to nameservice module

* refactor: refactored the nameservice module

* refactor: add human-readable attributes output to cli nameservice `list`

* fix: fix the sub names authority storing issue

* refactor: removed legacyCodec from nameservice

* fix: fix the responses for `authority-expiry` and `records-expiry` commands query result

* refactor: sort the imports in app

* refactor: removed json encoder and decoder
2021-10-06 11:35:51 +05:30
Bipul Prasadandbipulprasad 9301487351 Rectifying empty params issue with auction module (#6)
Co-authored-by: bipulprasad <Bipul@qubecinema.com>
2021-10-01 16:52:55 +05:30
Bipul Prasadandbipulprasad 505ad2ab70 [vulcanize/dxns#8] Migrating auctions module from DXNS (#3)
* Migrating auctions module from DXNS

* Adding appropriate comments on proto definitions

* Addressing review comments and fixing build issues

* Addressing review comments

* Adding README for auction module and fixing build/run issues

* Removing DXNS references and migrating DXNS utils to Ethermint

* Setting default genesis param values

* Defining constants in params and assigning ParamSetPairs

* Fixing issues with auction bid reveals

Co-authored-by: bipulprasad <Bipul@qubecinema.com>
2021-10-01 15:19:01 +05:30
Sai Kumar d28ef888ff dxns bond module test (#4)
* WIP : added bond module tx and query cli commands

* added bond module invariant

* update the go.mod

* addressed the pr changes

* update to proto files

* refactor: move the proto package version from `v1` to `v1beta1` for vulcanize modules

* WIP : addin the unit test scripts to bond module

* refactor: refactored the test cases for bond module

* refactor: refactored the bond module test cases
1. refactored grpc gateway  endpoints of bond module
2. added test cases to cli query , cli tx and grpc end points

* addressed the pr comments
1. changed query-by-owner to by-owner in cli cmd
2. changed bonds-by-owner route to by-owner in bond module
2021-09-29 18:18:30 +05:30
Sai Kumar feb9790325 Migrating the bond module from dxns (#1)
* WIP : added bond module tx and query cli commands

* added bond module invariant

* update the go.mod

* addressed the pr changes

* update to proto files

* refactor: move the proto package version from `v1` to `v1beta1` for vulcanize modules

* updated the readme file for bond module

* refactor: address the pr changes
2021-09-27 12:11:16 +05:30
455 changed files with 53769 additions and 32029 deletions
-5
View File
@@ -1,5 +0,0 @@
# Configuration docs: https://bencher.orijtech.com/configuration/
suppress_failure_on_regression: false
global:
reg_min: 10
imp_min: -10
-8
View File
@@ -1,8 +0,0 @@
client/docs/swagger-ui/* linguist-vendored
client/docs/statik/* linguist-vendored
third-party/* linguist-vendored
client/docs/* linguist-documentation
docs/* linguist-documentation
x/**/spec/* linguist-documentation
**/*.pb.go linguist-generated
**/*.pb.gw.go linguist-generated
+1 -1
View File
@@ -1,4 +1,4 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
# Primary repo maintainers
* @fedekunze @khoslaventures @jolube
* @fedekunze @khoslaventures @nzoghb
+29
View File
@@ -0,0 +1,29 @@
name: Docs build
# This workflow runs when a PR is labeled with `docs`
# This will check if the docs build successfully by running `npm run build`
on:
pull_request:
push:
branches:
- main
- release/*
jobs:
check-docs-build:
name: Check docs build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
with:
persist-credentials: false
fetch-depth: 0
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
docs/*
SUFFIX_FILTER: |
.md
- name: Install dependencies and build docs 🧱
run: |
make build-docs
+3 -6
View File
@@ -16,11 +16,8 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
with:
go-version: 1.17
- uses: technote-space/get-diff-action@v6.0.1
- uses: actions/checkout@v2.3.4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
SUFFIX_FILTER: |
@@ -29,4 +26,4 @@ jobs:
.sum
- run: |
make build
if: env.GIT_DIFF
if: "env.GIT_DIFF != ''"
+19
View File
@@ -0,0 +1,19 @@
name: Remove old artifacts
# Remove old artifacts runs a crob job that removes old artifacts
# generated from the split tests workflow.
on:
schedule:
# Every day at 1am
- cron: "0 1 * * *"
jobs:
remove-old-artifacts:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Remove old artifacts
uses: c-hive/gha-remove-artifacts@v1.2.0
with:
age: "7 days"
+1 -1
View File
@@ -39,7 +39,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+4 -4
View File
@@ -16,14 +16,14 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2.3.4
- name: Use Node.js
uses: actions/setup-node@v3
uses: actions/setup-node@v2.4.0
with:
node-version: '12.x'
- name: Install dependencies
run: npm install
- uses: technote-space/get-diff-action@v6.0.1
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
SUFFIX_FILTER: |
@@ -35,4 +35,4 @@ jobs:
run: |
sudo make contract-tools
sudo make test-contract
if: env.GIT_DIFF
if: "env.GIT_DIFF != ''"
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
environment: release
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
submodules: true
- name: Set up Go
-29
View File
@@ -1,29 +0,0 @@
name: Notion Sync
on:
workflow_dispatch:
issues:
types:
[
opened,
edited,
labeled,
unlabeled,
assigned,
unassigned,
milestoned,
demilestoned,
reopened,
closed,
]
jobs:
notion_job:
runs-on: ubuntu-latest
name: Add GitHub Issues to Notion
steps:
- name: Add GitHub Issues to Notion
uses: vulcanize/notion-github-action@v1.2.4-issueid
with:
notion-token: ${{ secrets.NOTION_TOKEN }}
notion-db: ${{ secrets.NOTION_DATABASE }}
+1 -1
View File
@@ -9,6 +9,6 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
- uses: actions/labeler@v3
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+2 -2
View File
@@ -6,7 +6,7 @@ jobs:
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: gaurav-nelson/github-action-markdown-link-check@1.0.14
- uses: actions/checkout@v2.3.4
- uses: gaurav-nelson/github-action-markdown-link-check@1.0.13
with:
folder-path: "docs"
+3 -3
View File
@@ -13,8 +13,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
- uses: actions/checkout@v2.3.4
- uses: technote-space/get-diff-action@v5
with:
SUFFIX_FILTER: |
.go
@@ -23,7 +23,7 @@ jobs:
- uses: golangci/golangci-lint-action@v2.5.2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.42.1
version: v1.29
args: --timeout 10m
github-token: ${{ secrets.github_token }}
# Check only if there are differences in the source code
+4 -4
View File
@@ -9,8 +9,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
- uses: actions/checkout@master
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.proto
@@ -20,8 +20,8 @@ jobs:
breakage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
- uses: actions/checkout@master
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.proto
-34
View File
@@ -1,34 +0,0 @@
name: Run Gosec
on:
pull_request:
push:
branches:
- main
jobs:
Gosec:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v3
- name: Get Diff
uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/*.go
go.mod
go.sum
- name: Run Gosec Security Scanner
uses: informalsystems/gosec@master
with:
# we let the report trigger content trigger a failure using the GitHub Security features.
args: '-no-fail -fmt sarif -out results.sarif ./...'
if: "env.GIT_DIFF_FILTERED != ''"
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
# Path to SARIF file relative to the root of the repository
sarif_file: results.sarif
if: "env.GIT_DIFF_FILTERED != ''"
-41
View File
@@ -1,41 +0,0 @@
name: Semgrep
on:
# Scan changed files in PRs, block on new issues only (existing issues ignored)
pull_request: {}
push:
branches:
- main
paths:
- .github/workflows/semgrep.yml
schedule:
- cron: '0 0 * * 0'
jobs:
semgrep:
name: Scan
runs-on: ubuntu-latest
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@v3
- name: Get Diff
uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/*.go
**/*.js
**/*.ts
**/*.sol
go.mod
go.sum
- uses: returntocorp/semgrep-action@v1
with:
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
# Upload findings to GitHub Advanced Security Dashboard [step 1/2]
# See also the next step.
generateSarif: "1"
if: "env.GIT_DIFF_FILTERED != ''"
# Upload findings to GitHub Advanced Security Dashboard [step 2/2]
- name: Upload SARIF file for GitHub Advanced Security Dashboard
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: semgrep.sarif
if: "env.GIT_DIFF_FILTERED != ''"
+21
View File
@@ -0,0 +1,21 @@
name: "Close stale issues & pull requests"
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: "This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed in 7 days-before-close if no further activity occurs."
stale-issue-message: "This issue is stale because it has been open 45 days with no activity. Remove `Status: Stale` label or comment or this will be closed in 7 days."
days-before-stale: 45
days-before-close: 7
exempt-issue-labels: "Status: Blocked, Type: Bug, pinned, automerge"
exempt-pr-labels: "Status: Blocked, Type: Bug, pinned, automerge"
stale-pr-label: "Status: Stale"
stale-issue-label: "Status: Stale"
+31 -78
View File
@@ -26,7 +26,7 @@ jobs:
- name: Install tparse
run: |
export GO111MODULE="on" && go get github.com/mfridman/tparse@latest
- uses: actions/cache@v3
- uses: actions/cache@v2.1.6
with:
path: ~/go/bin
key: ${{ runner.os }}-go-tparse-binary
@@ -37,8 +37,8 @@ jobs:
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
- uses: actions/checkout@v2.3.4
- uses: technote-space/get-diff-action@v5
with:
PATTERNS: |
**/**.sol
@@ -55,62 +55,54 @@ jobs:
fail_ci_if_error: true
if: env.GIT_DIFF
test-importer:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
id: git_diff
with:
SUFFIX_FILTER: |
.go
.mod
.sum
- name: test-importer
run: |
make test-import
if: env.GIT_DIFF
# TODO: refactor before enabling
# test-importer:
# runs-on: ubuntu-latest
# timeout-minutes: 10
# steps:
# - uses: actions/checkout@v2.3.4
# - uses: actions/setup-go@v2.1.4
# with:
# go-version: 1.17
# - uses: technote-space/get-diff-action@v5
# id: git_diff
# with:
# SUFFIX_FILTER: |
# .go
# .mod
# .sum
# - name: test-importer
# run: |
# make test-import
# if: "env.GIT_DIFF != ''"
test-solidity:
runs-on: ubuntu-latest
timeout-minutes: 240
strategy:
fail-fast: false
matrix:
batch: ['1-3', '2-3', '3-3']
timeout-minutes: 15
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
with:
go-version: 1.17
- uses: technote-space/get-diff-action@v6.0.1
- uses: actions/checkout@v2.3.4
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
**/**.sol
**/**.go
tests/solidity/**/*.js
tests/solidity/**/*.sh
go.mod
go.sum
- name: test-solidity
run: |
./scripts/run-solidity-tests.sh --batch=${{ matrix.batch }}
if: env.GIT_DIFF
make test-solidity
if: "env.GIT_DIFF != ''"
liveness-test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2.3.4
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: technote-space/get-diff-action@v6.0.1
- uses: technote-space/get-diff-action@v5
id: git_diff
with:
PATTERNS: |
@@ -130,43 +122,4 @@ jobs:
sleep 2m
./contrib/scripts/test_localnet_liveness.sh 100 5 50 localhost
if: env.GIT_DIFF
test-rpc:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.sol
**/**.go
go.mod
go.sum
- name: Test rpc endpoint
run: |
make test-rpc
if: env.GIT_DIFF
test-e2e:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.sol
**/**.go
go.mod
go.sum
- name: Test e2e
run: |
make test-integration
if: env.GIT_DIFF
+1 -2
View File
@@ -70,5 +70,4 @@ dependency-graph.png
# Node.js
tests/**/node_modules/*
tests-solidity/**/node_modules/*
**/**.json
tests-solidity/**/node_modules/*
+4 -3
View File
@@ -15,20 +15,21 @@ linters:
- gocritic
- gofmt
- goimports
- revive
- golint
- gosec
- gosimple
- govet
- ineffassign
# - lll TODO: enable
- misspell
- maligned
- nakedret
- prealloc
- exportloopref
- scopelint
- staticcheck
- structcheck
- stylecheck
# - typecheck #TODO: enable
- typecheck
- unconvert
- unparam
- unused
+1 -1
View File
@@ -106,4 +106,4 @@ changelog:
- '^docs:'
- '^test:'
snapshot:
name_template: "{{ .Tag }}-next"
name_template: "{{ .Tag }}-next"
+2 -25
View File
@@ -1,33 +1,10 @@
queue_rules:
- name: default
conditions:
- "#approved-reviews-by>1"
pull_request_rules:
- name: automerge to the base branch with label automerge and branch protection passing
- name: automerge to base branch with label automerge and branch protection passing
conditions:
- "#approved-reviews-by>1"
- base=main
- label=automerge
actions:
queue:
name: default
merge:
method: squash
commit_message: title+body
- name: backport patches to v0.9.x branch
conditions:
- base=main
- label=backport/0.9.x
actions:
backport:
branches:
- release/v0.9.x
- name: backport patches to v0.7.x branch
conditions:
- base=main
- label=backport/0.7.x
actions:
backport:
branches:
- release/v0.7.x
strict: true
-29
View File
@@ -1,29 +0,0 @@
# Ignore git items
.gitignore
.git/
:include .gitignore
# Common large paths
node_modules/
build/
dist/
vendor/
.env/
.venv/
.tox/
*.min.js
*.pb.gw.go
# Common test paths
test/
tests/
*_test.go
# Semgrep rules folder
.semgrep
# Semgrep-action log folder
.semgrep_logs/
# Documentation
client/docs/
+96 -319
View File
@@ -1,4 +1,3 @@
<!--
Guiding Principles:
@@ -36,227 +35,12 @@ Ref: https://keepachangelog.com/en/1.0.0/
# Changelog
## [v0.12.2] - 2022-03-30
### Bug Fixes
* (feemarket) [tharsis#1021](https://github.com/tharsis/ethermint/pull/1021) Fix fee market migration.
## [v0.12.1] - 2022-03-29
### Bug Fixes
* (evm) [tharsis#1016](https://github.com/tharsis/ethermint/pull/1016) Update validate basic check for storage state.
## [v0.12.0] - 2022-03-24
### Bug Fixes
* (rpc) [tharsis#1012](https://github.com/tharsis/ethermint/pull/1012) fix the tx hash in filter entries created by `eth_newPendingTransactionFilter`.
* (rpc) [tharsis#1006](https://github.com/tharsis/ethermint/pull/1006) Use `string` as the parameters type to correct ambiguous results.
* (ante) [tharsis#1004](https://github.com/tharsis/ethermint/pull/1004) Make `MaxTxGasWanted` configurable.
* (ante) [tharsis#991](https://github.com/tharsis/ethermint/pull/991) Set an upper bound to gasWanted to prevent DoS attack.
* (rpc) [tharsis#990](https://github.com/tharsis/ethermint/pull/990) Calculate reward values from all `MsgEthereumTx` from a block in `eth_feeHistory`.
## [v0.11.0] - 2022-03-06
### State Machine Breaking
* (ante) [tharsis#964](https://github.com/tharsis/ethermint/pull/964) add NewInfiniteGasMeterWithLimit for storing the user provided gas limit. Fixes block's consumed gas calculation in the block creation phase.
### Bug Fixes
* (rpc) [tharsis#975](https://github.com/tharsis/ethermint/pull/975) Fix unexpected `nil` values for `reward`, returned by `EffectiveGasTipValue(blockBaseFee)` in the `eth_feeHistory` RPC method.
### Improvements
- (rpc) [tharsis#979](https://github.com/tharsis/ethermint/pull/979) Add configurable timeouts to http server
- (rpc) [tharsis#988](https://github.com/tharsis/ethermint/pull/988) json-rpc server always use local rpc client
## [v0.10.1] - 2022-03-04
### Bug Fixes
* (rpc) [tharsis#970](https://github.com/tharsis/ethermint/pull/970) Fix unexpected nil reward values on `eth_feeHistory` response
* (evm) [tharsis#529](https://github.com/tharsis/ethermint/issues/529) Add support return value on trace tx response.
### Improvements
* (rpc) [tharsis#968](https://github.com/tharsis/ethermint/pull/968) Add some buffer to returned gas price to provide better default UX for client.
## [v0.10.0] - 2022-02-26
### API Breaking
* (ante) [tharsis#866](https://github.com/tharsis/ethermint/pull/866) `NewAnteHandler` constructor now receives a `HandlerOptions` field.
* (evm) [tharsis#849](https://github.com/tharsis/ethermint/pull/849) `PostTxProcessing` hook now takes an Ethereum tx `Receipt` and a `from` `Address` as arguments.
* (ante) [tharsis#916](https://github.com/tharsis/ethermint/pull/916) Don't check min-gas-price for eth tx if london hardfork enabled and feemarket enabled.
### State Machine Breaking
* (deps) [tharsis#912](https://github.com/tharsis/ethermint/pull/912) Bump Cosmos SDK version to [`v0.45.1`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.1)
* (evm) [tharsis#840](https://github.com/tharsis/ethermint/pull/840) Store empty topics as empty array rather than nil.
* (feemarket) [tharsis#822](https://github.com/tharsis/ethermint/pull/822) Update EIP1559 base fee in `BeginBlock`.
* (evm) [tharsis#817](https://github.com/tharsis/ethermint/pull/817) Use `effectiveGasPrice` in ante handler, add `effectiveGasPrice` to tx receipt.
* (evm) [tharsis#808](https://github.com/tharsis/ethermint/issues/808) increase nonce in ante handler for contract creation transaction.
* (evm) [tharsis#851](https://github.com/tharsis/ethermint/pull/851) fix contract address used in EVM, this issue is caused by [tharsis#808](https://github.com/tharsis/ethermint/issues/808).
* (evm) Reject invalid `MsgEthereumTx` wrapping tx
* (evm) Fix `SelfDestruct` opcode by deleting account code and state.
* (feemarket) [tharsis#855](https://github.com/tharsis/ethermint/pull/855) Consistent `BaseFee` check logic.
* (evm) [tharsis#729](https://github.com/tharsis/ethermint/pull/729) Refactor EVM `StateDB` implementation.
* (evm) [tharsis#945](https://github.com/tharsis/ethermint/pull/945) Bumb Go-ethereum version to [`v1.10.16`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.16)
### Features
* (ante) [tharsis#950](https://github.com/tharsis/ethermint/pull/950) Add support for EIP712 signed Cosmos transactions
### Improvements
* (types) [tharsis#884](https://github.com/tharsis/ethermint/pull/884) Introduce a new `EthAccountI` interface for EVM-compatible account types.
* (types) [tharsis#849](https://github.com/tharsis/ethermint/pull/849) Add `Type` function to distinguish EOAs from Contract accounts.
* (evm) [tharsis#826](https://github.com/tharsis/ethermint/issues/826) Improve allocation of bytes of `tx.To` address.
* (evm) [tharsis#827](https://github.com/tharsis/ethermint/issues/827) Speed up creation of event logs by using the slice insertion idiom with indices.
* (ante) [tharsis#819](https://github.com/tharsis/ethermint/pull/819) Remove redundant ante handlers
* (app) [tharsis#873](https://github.com/tharsis/ethermint/pull/873) Validate code hash in GenesisAccount
* (evm) [tharsis#901](https://github.com/tharsis/ethermint/pull/901) Support multiple `MsgEthereumTx` in single tx.
* (config) [tharsis#908](https://github.com/tharsis/ethermint/pull/908) Add `api.enable` flag for Cosmos SDK Rest server
* (feemarket) [tharsis#919](https://github.com/tharsis/ethermint/pull/919) Initialize baseFee in default genesis state.
* (feemarket) [tharsis#943](https://github.com/tharsis/ethermint/pull/943) Store the base fee as a module param instead of using state storage.
### Bug Fixes
* (rpc) [tharsis#955](https://github.com/tharsis/ethermint/pull/955) Fix websocket server push duplicated messages to subscriber.
* (rpc) [tharsis#953](https://github.com/tharsis/ethermint/pull/953) Add `eth_signTypedData` api support.
* (log) [tharsis#948](https://github.com/tharsis/ethermint/pull/948) Redirect go-ethereum's logs to cosmos-sdk logger.
* (evm) [tharsis#884](https://github.com/tharsis/ethermint/pull/884) Support multiple account types on the EVM `StateDB`.
* (rpc) [tharsis#831](https://github.com/tharsis/ethermint/pull/831) Fix BaseFee value when height is specified.
* (evm) [tharsis#838](https://github.com/tharsis/ethermint/pull/838) Fix splitting of trace.Memory into 32 chunks.
* (rpc) [tharsis#860](https://github.com/tharsis/ethermint/pull/860) Fix `eth_getLogs` when specify blockHash without address/topics, and limit the response size.
* (rpc) [tharsis#865](https://github.com/tharsis/ethermint/pull/865) Fix RPC Filter parameters being ignored
* (evm) [tharsis#871](https://github.com/tharsis/ethermint/pull/871) Set correct nonce in `EthCall` and `EstimateGas` grpc query.
* (rpc) [tharsis#878](https://github.com/tharsis/ethermint/pull/878) Workaround to make GetBlock RPC api report correct block gas used.
* (rpc) [tharsis#900](https://github.com/tharsis/ethermint/pull/900) `newPendingTransactions` filter return ethereum tx hash.
* (rpc) [tharsis#933](https://github.com/tharsis/ethermint/pull/933) Fix `newPendingTransactions` subscription deadlock when a Websocket client exits without unsubscribing and the node errors.
* (evm) [tharsis#932](https://github.com/tharsis/ethermint/pull/932) Fix base fee check logic in state transition.
## [v0.9.0] - 2021-12-01
### State Machine Breaking
* (evm) [tharsis#802](https://github.com/tharsis/ethermint/pull/802) Clear access list for each transaction
### Improvements
* (app) [tharsis#794](https://github.com/tharsis/ethermint/pull/794) Setup in-place store migrators.
* (ci) [tharsis#784](https://github.com/tharsis/ethermint/pull/784) Enable automatic backport of PRs.
* (rpc) [tharsis#786](https://github.com/tharsis/ethermint/pull/786) Improve error message of `SendTransaction`/`SendRawTransaction` JSON-RPC APIs.
* (rpc) [tharsis#810](https://github.com/tharsis/ethermint/pull/810) Optimize tx index lookup in web3 rpc
### Bug Fixes
* (license) [tharsis#800](https://github.com/tharsis/ethermint/pull/800) Re-license project to [LGPLv3](https://choosealicense.com/licenses/lgpl-3.0/#) to comply with go-ethereum.
* (evm) [tharsis#794](https://github.com/tharsis/ethermint/pull/794) Register EVM gRPC `Msg` server.
* (rpc) [tharsis#781](https://github.com/tharsis/ethermint/pull/781) Fix get block invalid transactions filter.
* (rpc) [tharsis#782](https://github.com/tharsis/ethermint/pull/782) Fix wrong block gas limit returned by JSON-RPC.
* (evm) [tharsis#798](https://github.com/tharsis/ethermint/pull/798) Fix the semantic of `ForEachStorage` callback's return value
## [v0.8.1] - 2021-11-23
### Bug Fixes
* (feemarket) [tharsis#770](https://github.com/tharsis/ethermint/pull/770) Enable fee market (EIP1559) by default.
* (rpc) [tharsis#769](https://github.com/tharsis/ethermint/pull/769) Fix default Ethereum signer for JSON-RPC.
## [v0.8.0] - 2021-11-17
### State Machine Breaking
* (evm, ante) [tharsis#620](https://github.com/tharsis/ethermint/pull/620) Add fee market field to EVM `Keeper` and `AnteHandler`.
* (all) [tharsis#231](https://github.com/tharsis/ethermint/pull/231) Bump go-ethereum version to [`v1.10.9`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.9)
* (ante) [tharsis#703](https://github.com/tharsis/ethermint/pull/703) Fix some fields in transaction are not authenticated by signature.
* (evm) [tharsis#751](https://github.com/tharsis/ethermint/pull/751) don't revert gas refund logic when transaction reverted
### Features
* (rpc, evm) [tharsis#673](https://github.com/tharsis/ethermint/pull/673) Use tendermint events to store fee market basefee.
* (rpc) [tharsis#624](https://github.com/tharsis/ethermint/pull/624) Implement new JSON-RPC endpoints from latest geth version
* (evm) [tharsis#662](https://github.com/tharsis/ethermint/pull/662) Disable basefee for non london blocks
* (cmd) [tharsis#712](https://github.com/tharsis/ethermint/pull/712) add tx cli to build evm transaction
* (rpc) [tharsis#733](https://github.com/tharsis/ethermint/pull/733) add JSON_RPC endpoint `personal_unpair`
* (rpc) [tharsis#734](https://github.com/tharsis/ethermint/pull/734) add JSON_RPC endpoint `eth_feeHistory`
* (rpc) [tharsis#740](https://github.com/tharsis/ethermint/pull/740) add JSON_RPC endpoint `personal_initializeWallet`
* (rpc) [tharsis#743](https://github.com/tharsis/ethermint/pull/743) add JSON_RPC endpoint `debug_traceBlockByHash`
* (rpc) [tharsis#748](https://github.com/tharsis/ethermint/pull/748) add JSON_RPC endpoint `personal_listWallets`
* (rpc) [tharsis#754](https://github.com/tharsis/ethermint/pull/754) add JSON_RPC endpoint `debug_intermediateRoots`
### Bug Fixes
* (evm) [tharsis#746](https://github.com/tharsis/ethermint/pull/746) Set EVM debugging based on tracer configuration.
* (app,cli) [tharsis#725](https://github.com/tharsis/ethermint/pull/725) Fix cli-config for `keys` command.
* (rpc) [tharsis#727](https://github.com/tharsis/ethermint/pull/727) Decode raw transaction using RLP.
* (rpc) [tharsis#661](https://github.com/tharsis/ethermint/pull/661) Fix OOM bug when creating too many filters using JSON-RPC.
* (evm) [tharsis#660](https://github.com/tharsis/ethermint/pull/660) Fix `nil` pointer panic in `ApplyNativeMessage`.
* (evm, test) [tharsis#649](https://github.com/tharsis/ethermint/pull/649) Test DynamicFeeTx.
* (evm) [tharsis#702](https://github.com/tharsis/ethermint/pull/702) Fix panic in web3 RPC handlers
* (rpc) [tharsis#720](https://github.com/tharsis/ethermint/pull/720) Fix `debug_traceTransaction` failure
* (rpc) [tharsis#741](https://github.com/tharsis/ethermint/pull/741) Fix `eth_getBlockByNumberAndHash` return with non eth txs
* (rpc) [tharsis#743](https://github.com/tharsis/ethermint/pull/743) Fix debug JSON RPC handler crash on non-existing block
### Improvements
* (tests) [tharsis#704](https://github.com/tharsis/ethermint/pull/704) Introduce E2E testing framework for clients
* (deps) [tharsis#737](https://github.com/tharsis/ethermint/pull/737) Bump ibc-go to [`v2.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v2.0.0)
* (rpc) [tharsis#671](https://github.com/tharsis/ethermint/pull/671) Don't pass base fee externally for `EthCall`/`EthEstimateGas` apis.
* (evm) [tharsis#674](https://github.com/tharsis/ethermint/pull/674) Refactor `ApplyMessage`, remove
`ApplyNativeMessage`.
* (rpc) [tharsis#714](https://github.com/tharsis/ethermint/pull/714) remove `MsgEthereumTx` support in `TxConfig`
## [v0.7.2] - 2021-10-24
### Improvements
* (deps) [tharsis#692](https://github.com/tharsis/ethermint/pull/692) Bump Cosmos SDK version to [`v0.44.3`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.44.3).
* (rpc) [tharsis#679](https://github.com/tharsis/ethermint/pull/679) Fix file close handle.
* (deps) [tharsis#668](https://github.com/tharsis/ethermint/pull/668) Bump Tendermint version to [`v0.34.14`](https://github.com/tendermint/tendermint/releases/tag/v0.34.14).
### Bug Fixes
* (rpc) [tharsis#667](https://github.com/tharsis/ethermint/issues/667) Fix `ExpandHome` restrictions bypass
## [v0.7.1] - 2021-10-08
### Bug Fixes
* (evm) [tharsis#650](https://github.com/tharsis/ethermint/pull/650) Fix panic when flattening the cache context in case transaction is reverted.
* (rpc, test) [tharsis#608](https://github.com/tharsis/ethermint/pull/608) Fix rpc test.
## [v0.7.0] - 2021-10-07
### API Breaking
* (rpc) [tharsis#400](https://github.com/tharsis/ethermint/issues/400) Restructure JSON-RPC directory and rename server config
### Improvements
* (deps) [tharsis#621](https://github.com/tharsis/ethermint/pull/621) Bump IBC-go to [`v1.2.1`](https://github.com/cosmos/ibc-go/releases/tag/v1.2.1)
* (evm) [tharsis#613](https://github.com/tharsis/ethermint/pull/613) Refactor `traceTx`
* (deps) [tharsis#610](https://github.com/tharsis/ethermint/pull/610) Bump Cosmos SDK to [v0.44.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.44.1).
### Bug Fixes
* (rpc) [tharsis#642](https://github.com/tharsis/ethermint/issues/642) Fix `eth_getLogs` when string is specified in filter's from or to fields
* (evm) [tharsis#616](https://github.com/tharsis/ethermint/issues/616) Fix halt on deeply nested stack of cache context. Stack is now flattened before iterating over the tx logs.
* (rpc, evm) [tharsis#614](https://github.com/tharsis/ethermint/issues/614) Use JSON for (un)marshaling tx `Log`s from events.
* (rpc) [tharsis#611](https://github.com/tharsis/ethermint/pull/611) Fix panic on JSON-RPC when querying for an invalid block height.
* (cmd) [tharsis#483](https://github.com/tharsis/ethermint/pull/483) Use config values on genesis accounts.
## [v0.6.0] - 2021-09-29
## Unreleased
### State Machine Breaking
* (app) [tharsis#476](https://github.com/tharsis/ethermint/pull/476) Update Bech32 HRP to `ethm`.
* (evm) [tharsis#556](https://github.com/tharsis/ethermint/pull/556) Remove tx logs and block bloom from chain state
* (evm) [tharsis#590](https://github.com/tharsis/ethermint/pull/590) Contract storage key is not hashed anymore
* (evm) [tharsis#556](https://github.com/tharsis/ethermint/pull/556) Remove tx logs and block bloom from chain state
### API Breaking
@@ -265,16 +49,12 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features
* (evm) [tharsis#469](https://github.com/tharsis/ethermint/pull/469) Support [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
* (evm) [tharsis#417](https://github.com/tharsis/ethermint/pull/417) Add `EvmHooks` for tx post-processing
* (evm) [tharsis#417](https://github.com/tharsis/ethermint/pull/417) Add `EvmHooks` for tx post-processing
* (rpc) [tharsis#506](https://github.com/tharsis/ethermint/pull/506) Support for `debug_traceTransaction` RPC endpoint
* (rpc) [tharsis#555](https://github.com/tharsis/ethermint/pull/555) Support for `debug_traceBlockByNumber` RPC endpoint
### Bug Fixes
* (rpc, server) [tharsis#600](https://github.com/tharsis/ethermint/pull/600) Add TLS configuration for websocket API
* (rpc) [tharsis#598](https://github.com/tharsis/ethermint/pull/598) Check truncation when creating a `BlockNumber` from `big.Int`
* (evm) [tharsis#597](https://github.com/tharsis/ethermint/pull/597) Check for `uint64` -> `int64` block height overflow on `GetHashFn`
* (evm) [tharsis#579](https://github.com/tharsis/ethermint/pull/579) Update `DeriveChainID` function to handle `v` signature values `< 35`.
* (encoding) [tharsis#478](https://github.com/tharsis/ethermint/pull/478) Register `Evidence` to amino codec.
* (rpc) [tharsis#478](https://github.com/tharsis/ethermint/pull/481) Getting the node configuration when calling the `miner` rpc methods.
* (cli) [tharsis#561](https://github.com/tharsis/ethermint/pull/561) `Export` and `Start` commands now use the same home directory.
@@ -282,9 +62,6 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements
* (evm) [tharsis#461](https://github.com/tharsis/ethermint/pull/461) Increase performance of `StateDB` transaction log storage (r/w).
* (evm) [tharsis#566](https://github.com/tharsis/ethermint/pull/566) Introduce `stateErr` store in `StateDB` to avoid meaningless operations if any error happened before
* (rpc, evm) [tharsis#587](https://github.com/tharsis/ethermint/pull/587) Apply bloom filter when query ethlogs with range of blocks
* (evm) [tharsis#586](https://github.com/tharsis/ethermint/pull/586) Benchmark evm keeper
## [v0.5.0] - 2021-08-20
@@ -301,7 +78,7 @@ the Tracer type used to collect execution traces from the EVM transaction execut
* (evm) [tharsis#68](https://github.com/tharsis/ethermint/issues/68) Replace block hash storage map to use staking `HistoricalInfo`.
* (evm) [tharsis#276](https://github.com/tharsis/ethermint/pull/276) Vm errors don't result in cosmos tx failure, just
different tx state and events.
* (evm) [tharsis#342](https://github.com/tharsis/ethermint/issues/342) Don't clear balance when resetting the account.
* (evm) [tharsis#342](https://github.com/tharsis/ethermint/issues/342) Don't clear balance when resetting the account.
* (evm) [tharsis#334](https://github.com/tharsis/ethermint/pull/334) Log index changed to the index in block rather than
tx.
* (evm) [tharsis#399](https://github.com/tharsis/ethermint/pull/399) Exception in sub-message call reverts the call if it's not propagated.
@@ -315,8 +92,8 @@ the Tracer type used to collect execution traces from the EVM transaction execut
* The `TxReceipt`, `TxReceiptsByBlockHeight` endpoints have been removed from the Query service.
* The `ContractAddress`, `Bloom` have been removed from the `MsgEthereumTxResponse` and the
response now contains the ethereum-formatted `Hash` in hex format.
* (eth) [tharsis#845](https://github.com/cosmos/ethermint/pull/845) The `eth` namespace must be included in the list of API's as default to run the rpc server without error.
* (evm) [tharsis#202](https://github.com/tharsis/ethermint/pull/202) Web3 api `SendTransaction`/`SendRawTransaction` returns ethereum compatible transaction hash, and query api `GetTransaction*` also accept that.
* (eth) [\#845](https://github.com/cosmos/ethermint/pull/845) The `eth` namespace must be included in the list of API's as default to run the rpc server without error.
* (evm) [#202](https://github.com/tharsis/ethermint/pull/202) Web3 api `SendTransaction`/`SendRawTransaction` returns ethereum compatible transaction hash, and query api `GetTransaction*` also accept that.
* (rpc) [tharsis#258](https://github.com/tharsis/ethermint/pull/258) Return empty `BloomFilter` instead of throwing an error when it cannot be found (`nil` or empty).
* (rpc) [tharsis#277](https://github.com/tharsis/ethermint/pull/321) Fix `BloomFilter` response.
@@ -332,13 +109,13 @@ the Tracer type used to collect execution traces from the EVM transaction execut
* (deps) [tharsis#423](https://github.com/tharsis/ethermint/pull/423) Bump Cosmos SDK and Tendermint versions to [v0.43.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.43.0) and [v0.34.11](https://github.com/tendermint/tendermint/releases/tag/v0.34.11), respectively.
* (evm) [tharsis#66](https://github.com/tharsis/ethermint/issues/66) Support legacy transaction types for signing.
* (evm) [tharsis#24](https://github.com/tharsis/ethermint/pull/24) Implement metrics for `MsgEthereumTx`, state transitions, `BeginBlock` and `EndBlock`.
* (rpc) [tharsis#124](https://github.com/tharsis/ethermint/issues/124) Implement `txpool_content`, `txpool_inspect` and `txpool_status` RPC methods
* (rpc) [#124](https://github.com/tharsis/ethermint/issues/124) Implement `txpool_content`, `txpool_inspect` and `txpool_status` RPC methods
* (rpc) [tharsis#112](https://github.com/tharsis/ethermint/pull/153) Fix `eth_coinbase` to return the ethereum address of the validator
* (rpc) [tharsis#176](https://github.com/tharsis/ethermint/issues/176) Support fetching pending nonce
* (rpc) [tharsis#272](https://github.com/tharsis/ethermint/pull/272) do binary search to estimate gas accurately
* (rpc) [tharsis#313](https://github.com/tharsis/ethermint/pull/313) Implement internal debug namespace (Not including logger functions nor traces).
* (rpc) [tharsis#349](https://github.com/tharsis/ethermint/pull/349) Implement configurable JSON-RPC APIs to manage enabled namespaces.
* (rpc) [tharsis#377](https://github.com/tharsis/ethermint/pull/377) Implement `miner_` namespace. `miner_setEtherbase` and `miner_setGasPrice` are working as intended. All the other calls are not applicable and return `unsupported`.
* (rpc) [tharsis#272](https://github.com/tharsis/ethermint/pull/272) do binary search to estimate gas accurately
* (rpc) [#313](https://github.com/tharsis/ethermint/pull/313) Implement internal debug namespace (Not including logger functions nor traces).
* (rpc) [#349](https://github.com/tharsis/ethermint/pull/349) Implement configurable JSON-RPC APIs to manage enabled namespaces.
* (rpc) [#377](https://github.com/tharsis/ethermint/pull/377) Implement `miner_` namespace. `miner_setEtherbase` and `miner_setGasPrice` are working as intended. All the other calls are not applicable and return `unsupported`.
* (eth) [tharsis#460](https://github.com/tharsis/ethermint/issues/460) Add support for EIP-1898.
### Bug Fixes
@@ -352,41 +129,41 @@ the Tracer type used to collect execution traces from the EVM transaction execut
### API Breaking
* (faucet) [tharsis#678](https://github.com/cosmos/ethermint/pull/678) Faucet module has been removed in favor of client libraries such as [`@cosmjs/faucet`](https://github.com/cosmos/cosmjs/tree/master/packages/faucet).
* (evm) [tharsis#670](https://github.com/cosmos/ethermint/pull/670) Migrate types to the ones defined by the protobuf messages, which are required for the stargate release.
* (faucet) [\#678](https://github.com/cosmos/ethermint/pull/678) Faucet module has been removed in favor of client libraries such as [`@cosmjs/faucet`](https://github.com/cosmos/cosmjs/tree/master/packages/faucet).
* (evm) [\#670](https://github.com/cosmos/ethermint/pull/670) Migrate types to the ones defined by the protobuf messages, which are required for the stargate release.
### Bug Fixes
* (evm) [tharsis#799](https://github.com/cosmos/ethermint/issues/799) Fix wrong precision in calculation of gas fee.
* (evm) [tharsis#760](https://github.com/cosmos/ethermint/issues/760) Fix Failed to call function EstimateGas.
* (evm) [tharsis#767](https://github.com/cosmos/ethermint/issues/767) Fix error of timeout when using Truffle to deploy contract.
* (evm) [tharsis#751](https://github.com/cosmos/ethermint/issues/751) Fix misused method to calculate block hash in evm related function.
* (evm) [tharsis#721](https://github.com/cosmos/ethermint/issues/721) Fix mismatch block hash in rpc response when use eht.getBlock.
* (evm) [tharsis#730](https://github.com/cosmos/ethermint/issues/730) Fix 'EIP2028' not open when Istanbul version has been enabled.
* (evm) [tharsis#749](https://github.com/cosmos/ethermint/issues/749) Fix panic in `AnteHandler` when gas price larger than 100000
* (evm) [tharsis#747](https://github.com/cosmos/ethermint/issues/747) Fix format errors in String() of QueryETHLogs
* (evm) [tharsis#742](https://github.com/cosmos/ethermint/issues/742) Add parameter check for evm query func.
* (evm) [tharsis#687](https://github.com/cosmos/ethermint/issues/687) Fix nonce check to explicitly check for the correct nonce, rather than a simple 'greater than' comparison.
* (api) [tharsis#687](https://github.com/cosmos/ethermint/issues/687) Returns error for a transaction with an incorrect nonce.
* (evm) [tharsis#674](https://github.com/cosmos/ethermint/issues/674) Reset all cache after account data has been committed in `EndBlock` to make sure every node state consistent.
* (evm) [tharsis#672](https://github.com/cosmos/ethermint/issues/672) Fix panic of `wrong Block.Header.AppHash` when restart a node with snapshot.
* (evm) [tharsis#775](https://github.com/cosmos/ethermint/issues/775) MisUse of headHash as blockHash when create EVM context.
* (evm) [\#799](https://github.com/cosmos/ethermint/issues/799) Fix wrong precision in calculation of gas fee.
* (evm) [\#760](https://github.com/cosmos/ethermint/issues/760) Fix Failed to call function EstimateGas.
* (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 eht.getBlock.
* (evm) [\#730](https://github.com/cosmos/ethermint/issues/730) Fix 'EIP2028' not open when Istanbul version has been enabled.
* (evm) [\#749](https://github.com/cosmos/ethermint/issues/749) Fix panic in `AnteHandler` when gas price larger than 100000
* (evm) [\#747](https://github.com/cosmos/ethermint/issues/747) Fix format errors in String() of QueryETHLogs
* (evm) [\#742](https://github.com/cosmos/ethermint/issues/742) Add parameter check for evm query func.
* (evm) [\#687](https://github.com/cosmos/ethermint/issues/687) Fix nonce check to explicitly check for the correct nonce, rather than a simple 'greater than' comparison.
* (api) [\#687](https://github.com/cosmos/ethermint/issues/687) Returns error for a transaction with an incorrect nonce.
* (evm) [\#674](https://github.com/cosmos/ethermint/issues/674) Reset all cache after account data has been committed in `EndBlock` to make sure every node state consistent.
* (evm) [\#672](https://github.com/cosmos/ethermint/issues/672) Fix panic of `wrong Block.Header.AppHash` when restart a node with snapshot.
* (evm) [\#775](https://github.com/cosmos/ethermint/issues/775) MisUse of headHash as blockHash when create EVM context.
### Features
* (api) [tharsis#821](https://github.com/cosmos/ethermint/pull/821) Individually enable the api modules. Will be implemented in the latest version of ethermint with the upcoming stargate upgrade.
* (api) [\#821](https://github.com/cosmos/ethermint/pull/821) Individually enable the api modules. Will be implemented in the latest version of ethermint with the upcoming stargate upgrade.
### Features
* (api) [tharsis#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.
* (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
* (evm) [tharsis#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`.
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`.
### Features
* (rpc) [tharsis#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to JSON-RPC calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state:
* (rpc) [\#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to JSON-RPC calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state:
* `eth_getBalance`
* `eth_getTransactionCount`
* `eth_getBlockTransactionCountByNumber`
@@ -397,149 +174,149 @@ the Tracer type used to collect execution traces from the EVM transaction execut
### Improvements
* (evm) [tharsis#661](https://github.com/cosmos/ethermint/pull/661) Add invariant check for account balance and account nonce.
* (deps) [tharsis#654](https://github.com/cosmos/ethermint/pull/654) Bump go-ethereum version to [v1.9.25](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.25)
* (evm) [tharsis#627](https://github.com/cosmos/ethermint/issues/627) Add extra EIPs parameter to apply custom EVM jump tables.
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Add invariant check for account balance and account nonce.
* (deps) [\#654](https://github.com/cosmos/ethermint/pull/654) Bump go-ethereum version to [v1.9.25](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.25)
* (evm) [\#627](https://github.com/cosmos/ethermint/issues/627) Add extra EIPs parameter to apply custom EVM jump tables.
### Bug Fixes
* (evm) [tharsis#661](https://github.com/cosmos/ethermint/pull/661) Set nonce to the EVM account on genesis initialization.
* (rpc) [tharsis#648](https://github.com/cosmos/ethermint/issues/648) Fix block cumulative gas used value.
* (evm) [tharsis#621](https://github.com/cosmos/ethermint/issues/621) EVM `GenesisAccount` fields now share the same format as the auth module `Account`.
* (evm) [tharsis#618](https://github.com/cosmos/ethermint/issues/618) Add missing EVM `Context` `GetHash` field that retrieves a the header hash from a given block height.
* (app) [tharsis#617](https://github.com/cosmos/ethermint/issues/617) Fix genesis export functionality.
* (rpc) [tharsis#574](https://github.com/cosmos/ethermint/issues/574) Fix outdated version from `eth_protocolVersion`.
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Set nonce to the EVM account on genesis initialization.
* (rpc) [\#648](https://github.com/cosmos/ethermint/issues/648) Fix block cumulative gas used value.
* (evm) [\#621](https://github.com/cosmos/ethermint/issues/621) EVM `GenesisAccount` fields now share the same format as the auth module `Account`.
* (evm) [\#618](https://github.com/cosmos/ethermint/issues/618) Add missing EVM `Context` `GetHash` field that retrieves a the header hash from a given block height.
* (app) [\#617](https://github.com/cosmos/ethermint/issues/617) Fix genesis export functionality.
* (rpc) [\#574](https://github.com/cosmos/ethermint/issues/574) Fix outdated version from `eth_protocolVersion`.
## [v0.3.1] - 2020-11-24
### Improvements
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2)
* (deps) [tharsis#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+.
* (evm) [tharsis#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
* (deps) [tharsis#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9)
* (deps) [\#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2)
* (deps) [\#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+.
* (evm) [#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
* (deps) [\#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9)
### Bug Fixes
* (rpc) [tharsis#613](https://github.com/cosmos/ethermint/issues/613) Fix potential deadlock caused if the keyring `List` returned an error.
* (rpc) [\#613](https://github.com/cosmos/ethermint/issues/613) Fix potential deadlock caused if the keyring `List` returned an error.
## [v0.3.0] - 2020-11-16
### API Breaking
* (crypto) [tharsis#559](https://github.com/cosmos/ethermint/pull/559) Refactored crypto package in preparation for the SDK's Stargate release:
* (crypto) [\#559](https://github.com/cosmos/ethermint/pull/559) Refactored crypto package in preparation for the SDK's Stargate release:
* `crypto.PubKeySecp256k1` and `crypto.PrivKeySecp256k1` are now `ethsecp256k1.PubKey` and `ethsecp256k1.PrivKey`, respectively
* Moved SDK `SigningAlgo` implementation for Ethermint's Secp256k1 key to `crypto/hd` package.
* (rpc) [tharsis#588](https://github.com/cosmos/ethermint/pull/588) The `rpc` package has been refactored to account for the separation of each
* (rpc) [\#588](https://github.com/cosmos/ethermint/pull/588) The `rpc` package has been refactored to account for the separation of each
corresponding Ethereum API namespace:
* `rpc/namespaces/eth`: `eth` namespace. Exposes the `PublicEthereumAPI` and the `PublicFilterAPI`.
* `rpc/namespaces/personal`: `personal` namespace. Exposes the `PrivateAccountAPI`.
* `rpc/namespaces/net`: `net` namespace. Exposes the `PublicNetAPI`.
* `rpc/namespaces/web3`: `web3` namespace. Exposes the `PublicWeb3API`.
* (evm) [tharsis#588](https://github.com/cosmos/ethermint/pull/588) The EVM transaction CLI has been removed in favor of the JSON-RPC.
* (evm) [\#588](https://github.com/cosmos/ethermint/pull/588) The EVM transaction CLI has been removed in favor of the JSON-RPC.
### Improvements
* (deps) [tharsis#594](https://github.com/cosmos/ethermint/pull/594) Bump go-ethereum version to [v1.9.24](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.24)
* (deps) [\#594](https://github.com/cosmos/ethermint/pull/594) Bump go-ethereum version to [v1.9.24](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.24)
### Bug Fixes
* (ante) [tharsis#597](https://github.com/cosmos/ethermint/pull/597) Fix incorrect fee check on `AnteHandler`.
* (evm) [tharsis#583](https://github.com/cosmos/ethermint/pull/583) Fixes incorrect resetting of tx count and block bloom during `BeginBlock`, as well as gas consumption.
* (crypto) [tharsis#577](https://github.com/cosmos/ethermint/pull/577) Fix `BIP44HDPath` that did not prepend `m/` to the path. This now uses the `DefaultBaseDerivationPath` variable from go-ethereum to ensure addresses are consistent.
* (ante) [\#597](https://github.com/cosmos/ethermint/pull/597) Fix incorrect fee check on `AnteHandler`.
* (evm) [\#583](https://github.com/cosmos/ethermint/pull/583) Fixes incorrect resetting of tx count and block bloom during `BeginBlock`, as well as gas consumption.
* (crypto) [\#577](https://github.com/cosmos/ethermint/pull/577) Fix `BIP44HDPath` that did not prepend `m/` to the path. This now uses the `DefaultBaseDerivationPath` variable from go-ethereum to ensure addresses are consistent.
## [v0.2.1] - 2020-09-30
### Features
* (rpc) [tharsis#552](https://github.com/cosmos/ethermint/pull/552) Implement Eth Personal namespace `personal_importRawKey`.
* (rpc) [\#552](https://github.com/cosmos/ethermint/pull/552) Implement Eth Personal namespace `personal_importRawKey`.
### Bug fixes
* (keys) [tharsis#554](https://github.com/cosmos/ethermint/pull/554) Fix private key derivation.
* (app/ante) [tharsis#550](https://github.com/cosmos/ethermint/pull/550) Update ante handler nonce verification to accept any nonce greater than or equal to the expected nonce to allow to successive transactions.
* (keys) [\#554](https://github.com/cosmos/ethermint/pull/554) Fix private key derivation.
* (app/ante) [\#550](https://github.com/cosmos/ethermint/pull/550) Update ante handler nonce verification to accept any nonce greater than or equal to the expected nonce to allow to successive transactions.
## [v0.2.0] - 2020-09-24
### State Machine Breaking
* (app) [tharsis#540](https://github.com/cosmos/ethermint/issues/540) Chain identifier's format has been changed to match the Cosmos `chainID` [standard](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-5.md), which is required for IBC. The epoch number of the ID is used as the EVM `chainID`.
* (app) [\#540](https://github.com/cosmos/ethermint/issues/540) Chain identifier's format has been changed to match the Cosmos `chainID` [standard](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-5.md), which is required for IBC. The epoch number of the ID is used as the EVM `chainID`.
### API Breaking
* (types) [tharsis#503](https://github.com/cosmos/ethermint/pull/503) The `types.DenomDefault` constant for `"aphoton"` has been renamed to `types.AttoPhoton`.
* (types) [\#503](https://github.com/cosmos/ethermint/pull/503) The `types.DenomDefault` constant for `"aphoton"` has been renamed to `types.AttoPhoton`.
### Improvements
* (types) [tharsis#504](https://github.com/cosmos/ethermint/pull/504) Unmarshal a JSON `EthAccount` using an Ethereum hex address in addition to Bech32.
* (types) [tharsis#503](https://github.com/cosmos/ethermint/pull/503) Add `--coin-denom` flag to testnet command that sets the given coin denomination to SDK and Ethermint parameters.
* (types) [tharsis#502](https://github.com/cosmos/ethermint/pull/502) `EthAccount` now also exposes the Ethereum hex address in `string` format to clients.
* (types) [tharsis#494](https://github.com/cosmos/ethermint/pull/494) Update `EthAccount` public key JSON type to `string`.
* (app) [tharsis#471](https://github.com/cosmos/ethermint/pull/471) Add `x/upgrade` module for managing software updates.
* (evm) [tharsis#458](https://github.com/cosmos/ethermint/pull/458) Define parameter for token denomination used for the EVM module.
* (evm) [tharsis#443](https://github.com/cosmos/ethermint/issues/443) Support custom Ethereum `ChainConfig` params.
* (types) [tharsis#434](https://github.com/cosmos/ethermint/issues/434) Update default denomination to Atto Photon (`aphoton`).
* (types) [tharsis#515](https://github.com/cosmos/ethermint/pull/515) Update minimum gas price to be 1.
* (types) [\#504](https://github.com/cosmos/ethermint/pull/504) Unmarshal a JSON `EthAccount` using an Ethereum hex address in addition to Bech32.
* (types) [\#503](https://github.com/cosmos/ethermint/pull/503) Add `--coin-denom` flag to testnet command that sets the given coin denomination to SDK and Ethermint parameters.
* (types) [\#502](https://github.com/cosmos/ethermint/pull/502) `EthAccount` now also exposes the Ethereum hex address in `string` format to clients.
* (types) [\#494](https://github.com/cosmos/ethermint/pull/494) Update `EthAccount` public key JSON type to `string`.
* (app) [\#471](https://github.com/cosmos/ethermint/pull/471) Add `x/upgrade` module for managing software updates.
* (`x/evm`) [\#458](https://github.com/cosmos/ethermint/pull/458) Define parameter for token denomination used for the EVM module.
* (`x/evm`) [\#443](https://github.com/cosmos/ethermint/issues/443) Support custom Ethereum `ChainConfig` params.
* (types) [\#434](https://github.com/cosmos/ethermint/issues/434) Update default denomination to Atto Photon (`aphoton`).
* (types) [\#515](https://github.com/cosmos/ethermint/pull/515) Update minimum gas price to be 1.
### Bug Fixes
* (ante) [tharsis#525](https://github.com/cosmos/ethermint/pull/525) Add message validation decorator to `AnteHandler` for `MsgEthereumTx`.
* (types) [tharsis#507](https://github.com/cosmos/ethermint/pull/507) Fix hardcoded `aphoton` on `EthAccount` balance getter and setter.
* (types) [tharsis#501](https://github.com/cosmos/ethermint/pull/501) Fix bech32 encoding error by using the compressed ethereum secp256k1 public key.
* (evm) [tharsis#496](https://github.com/cosmos/ethermint/pull/496) Fix bugs on `journal.revert` and `CommitStateDB.Copy`.
* (types) [tharsis#480](https://github.com/cosmos/ethermint/pull/480) Update [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) coin type to `60` to satisfy [EIP84](https://github.com/ethereum/EIPs/issues/84).
* (types) [tharsis#513](https://github.com/cosmos/ethermint/pull/513) Fix simulated transaction bug that was causing a consensus error by unintentionally affecting the state.
* (ante) [\#525](https://github.com/cosmos/ethermint/pull/525) Add message validation decorator to `AnteHandler` for `MsgEthereumTx`.
* (types) [\#507](https://github.com/cosmos/ethermint/pull/507) Fix hardcoded `aphoton` on `EthAccount` balance getter and setter.
* (types) [\#501](https://github.com/cosmos/ethermint/pull/501) Fix bech32 encoding error by using the compressed ethereum secp256k1 public key.
* (`x/evm`) [\#496](https://github.com/cosmos/ethermint/pull/496) Fix bugs on `journal.revert` and `CommitStateDB.Copy`.
* (types) [\#480](https://github.com/cosmos/ethermint/pull/480) Update [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) coin type to `60` to satisfy [EIP84](https://github.com/ethereum/EIPs/issues/84).
* (types) [\#513](https://github.com/cosmos/ethermint/pull/513) Fix simulated transaction bug that was causing a consensus error by unintentionally affecting the state.
## [v0.1.0] - 2020-08-23
### Improvements
* (sdk) [tharsis#386](https://github.com/cosmos/ethermint/pull/386) Bump Cosmos SDK version to [v0.39.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.39.1)
* (evm) [tharsis#181](https://github.com/cosmos/ethermint/issues/181) Updated EVM module to the recommended module structure.
* (app) [tharsis#188](https://github.com/cosmos/ethermint/issues/186) Misc cleanup:
* (evm) Rename `EthereumTxMsg` --> `MsgEthereumTx` and `EmintMsg` --> `MsgEthermint` for consistency with SDK standards
* (sdk) [\#386](https://github.com/cosmos/ethermint/pull/386) Bump Cosmos SDK version to [v0.39.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.39.1)
* (`x/evm`) [\#181](https://github.com/cosmos/ethermint/issues/181) Updated EVM module to the recommended module structure.
* (app) [\#188](https://github.com/cosmos/ethermint/issues/186) Misc cleanup:
* (`x/evm`) Rename `EthereumTxMsg` --> `MsgEthereumTx` and `EmintMsg` --> `MsgEthermint` for consistency with SDK standards
* Updated integration and unit tests to use `EthermintApp` as testing suite
* Use expected `Keeper` interface for `AccountKeeper`
* Replaced `count` type in keeper with `int`
* Add SDK events for transactions
* [tharsis#236](https://github.com/cosmos/ethermint/pull/236) Changes from upgrade:
* [\#236](https://github.com/cosmos/ethermint/pull/236) Changes from upgrade:
* (`app/ante`) Moved `AnteHandler` implementation to `app/ante`
* (keys) Marked `ExportEthKeyCommand` as **UNSAFE**
* (evm) Moved `BeginBlock` and `EndBlock` to `x/evm/abci.go`
* (evm) [tharsis#255](https://github.com/cosmos/ethermint/pull/255) Add missing `GenesisState` fields and support `ExportGenesis` functionality.
* [tharsis#272](https://github.com/cosmos/ethermint/pull/272) Add `Logger` for evm module.
* [tharsis#317](https://github.com/cosmos/ethermint/pull/317) `GenesisAccount` validation.
* (evm) [tharsis#319](https://github.com/cosmos/ethermint/pull/319) Various evm improvements:
* (`x/evm`) Moved `BeginBlock` and `EndBlock` to `x/evm/abci.go`
* (`x/evm`) [\#255](https://github.com/cosmos/ethermint/pull/255) Add missing `GenesisState` fields and support `ExportGenesis` functionality.
* [\#272](https://github.com/cosmos/ethermint/pull/272) Add `Logger` for evm module.
* [\#317](https://github.com/cosmos/ethermint/pull/317) `GenesisAccount` validation.
* (`x/evm`) [\#319](https://github.com/cosmos/ethermint/pull/319) Various evm improvements:
* Add transaction `[]*ethtypes.Logs` to evm's `GenesisState` to persist logs after an upgrade.
* Remove evm `CodeKey` and `BlockKey`in favor of a prefix `Store`.
* Set `BlockBloom` during `EndBlock` instead of `BeginBlock`.
* `Commit` state object and `Finalize` storage after `InitGenesis` setup.
* (rpc) [tharsis#325](https://github.com/cosmos/ethermint/pull/325) `eth_coinbase` JSON-RPC query now returns the node's validator address.
* (rpc) [\#325](https://github.com/cosmos/ethermint/pull/325) `eth_coinbase` JSON-RPC query now returns the node's validator address.
### Features
* (build) [tharsis#378](https://github.com/cosmos/ethermint/pull/378) Create multi-node, local, automated testnet setup with `make localnet-start`.
* (rpc) [tharsis#330](https://github.com/cosmos/ethermint/issues/330) Implement `PublicFilterAPI`'s `EventSystem` which subscribes to Tendermint events upon `Filter` creation.
* (rpc) [tharsis#231](https://github.com/cosmos/ethermint/issues/231) Implement `NewBlockFilter` in rpc/filters.go which instantiates a polling block filter
* (build) [\#378](https://github.com/cosmos/ethermint/pull/378) Create multi-node, local, automated testnet setup with `make localnet-start`.
* (rpc) [\#330](https://github.com/cosmos/ethermint/issues/330) Implement `PublicFilterAPI`'s `EventSystem` which subscribes to Tendermint events upon `Filter` creation.
* (rpc) [\#231](https://github.com/cosmos/ethermint/issues/231) Implement `NewBlockFilter` in rpc/filters.go which instantiates a polling block filter
* Polls for new blocks via `BlockNumber` rpc call; if block number changes, it requests the new block via `GetBlockByNumber` rpc call and adds it to its internal list of blocks
* Update `uninstallFilter` and `getFilterChanges` accordingly
* `uninstallFilter` stops the polling goroutine
* `getFilterChanges` returns the filter's internal list of block hashes and resets it
* (rpc) [tharsis#54](https://github.com/cosmos/ethermint/issues/54), [tharsis#55](https://github.com/cosmos/ethermint/issues/55)
* (rpc) [\#54](https://github.com/cosmos/ethermint/issues/54), [\#55](https://github.com/cosmos/ethermint/issues/55)
Implement `eth_getFilterLogs` and `eth_getLogs`:
* For a given filter, look through each block for transactions. If there are transactions in the block, get the logs from it, and filter using the filterLogs method
* `eth_getLogs` and `eth_getFilterChanges` for log filters use the same underlying method as `eth_getFilterLogs`
* update `HandleMsgEthereumTx` to store logs using the ethereum hash
* (app) [tharsis#187](https://github.com/cosmos/ethermint/issues/187) Add support for simulations.
* (app) [\#187](https://github.com/cosmos/ethermint/issues/187) Add support for simulations.
### Bug Fixes
* (evm) [tharsis#767](https://github.com/cosmos/ethermint/issues/767) Fix error of timeout when using Truffle to deploy contract.
* (evm) [tharsis#751](https://github.com/cosmos/ethermint/issues/751) Fix misused method to calculate block hash in evm related function.
* (evm) [tharsis#721](https://github.com/cosmos/ethermint/issues/721) Fix mismatch block hash in rpc response when use eth.getBlock.
* (evm) [tharsis#730](https://github.com/cosmos/ethermint/issues/730) Fix 'EIP2028' not open when Istanbul version has been enabled.
* (app) [tharsis#749](https://github.com/cosmos/ethermint/issues/749) Fix panic in `AnteHandler` when gas price larger than 100000
* (rpc) [tharsis#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.
* (evm) [tharsis#319](https://github.com/cosmos/ethermint/pull/319) Fix `SetBlockHash` that was setting the incorrect height during `BeginBlock`.
* (evm) [tharsis#176](https://github.com/cosmos/ethermint/issues/176) Updated Web3 transaction hash from using RLP hash. Now all transaction hashes exposed are amino hashes:
* (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:
* Removes `Hash()` (RLP) function from `MsgEthereumTx` to avoid confusion or misuse in future.
+10
View File
@@ -106,6 +106,16 @@ items. In addition, use the following review explanations:
- If you sat down with the PR submitter and did a pairing review, add this information in the `Approval` or your PR comments.
- If you are only making "surface level" reviews, submit any notes as `Comments` without adding a review.
### Updating Documentation
If you open a PR on Ethermint, it is mandatory to update the relevant documentation in `/docs`.
- If your change relates to the core SDK (baseapp, store, ...), be sure to update the content in `docs/basics/`, `docs/core/` and/or `docs/building-modules/` folders.
- If your changes relate to the core of the CLI (not specifically to module's CLI/Rest), then modify the content in the `docs/run-node/` folder.
- If your changes relate to a module, then be sure to update the module's spec in `x/moduleName/docs/spec/`.
When writing documentation, follow the [Documentation Writing Guidelines](./docs/DOC_WRITING_GUIDELINES.md).
## Forking
Go requires code to live under absolute paths, and this requirement complicates forking.
-351
View File
@@ -1,351 +0,0 @@
# Vulcanize chiba-clonk gql
> Browser : http://localhost:9473 for gql
## Start server
```shell
./build/chibaclonkd start --gql-playground --gql-server
```
Basic node status:
```graphql
{
getStatus {
version
node {
id
network
moniker
}
sync {
latest_block_height
catching_up
}
num_peers
peers {
is_outbound
remote_ip
}
disk_usage
}
}
```
Full node status:
```graphql
{
getStatus {
version
node {
id
network
moniker
}
sync {
latest_block_hash
latest_block_time
latest_block_height
catching_up
}
validator {
address
voting_power
proposer_priority
}
validators {
address
voting_power
proposer_priority
}
num_peers
peers {
node {
id
network
moniker
}
is_outbound
remote_ip
}
disk_usage
}
}
```
Get records by IDs.
```graphql
{
getRecordsByIds(ids: ["QmYDtNCKtTu6u6jaHaFAC5PWZXcj7fAmry6NoWwMaixFHz"]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
```
Query records.
```graphql
{
queryRecords(attributes: [{ key: "type", value: { string: "crn:bot" } }]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
```
Get account details:
```graphql
{
getAccounts(addresses: ["cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094"]) {
address
pubKey
number
sequence
balance {
type
quantity
}
}
}
```
Query bonds:
```graphql
{
queryBonds(
attributes: [
{
key: "owner"
value: { string: "cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094" }
}
]
) {
id
owner
balance {
type
quantity
}
}
}
```
Get bonds by IDs.
```graphql
{
getBondsByIds(ids :
[
"1c2b677cb2a27c88cc6bf8acf675c94b69051125b40c4fd073153b10f046dd87",
"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440"
])
{
id
owner
balance{
type
quantity
}
}
}
```
Query Bonds by Owner
```graphql
{
queryBondsByOwner(ownerAddresses: ["ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"])
{
owner
bonds{
id
owner
balance
{
type
quantity
}
}
}
}
```
Query auctions by ids
```graphql
{
getAuctionsByIds(ids: ["be98f2073c246194276554eefdb4c95b682a35a0f06fbe619a6da57c10c93e90"]){
id
ownerAddress
createTime
minimumBid{
type
quantity
}
commitFee{
type
quantity
}
commitsEndTime
revealFee{
type
quantity
}
revealsEndTime
winnerBid{
type
quantity
}
winnerPrice{
type
quantity
}
winnerAddress
bids{
bidderAddress
commitHash
commitTime
commitFee{
type
quantity
}
revealFee{
type
quantity
}
revealTime
bidAmount{
type
quantity
}
status
}
}
}
```
LookUp Authorities
```graphql
{
lookupAuthorities(names: []){
ownerAddress
ownerAddress
height
bondId
status
expiryTime
auction {
id
ownerAddress
createTime
minimumBid{
type
quantity
}
commitFee{
type
quantity
}
commitsEndTime
revealFee{
type
quantity
}
revealsEndTime
winnerBid{
type
quantity
}
winnerPrice{
type
quantity
}
winnerAddress
bids{
bidderAddress
commitHash
commitTime
commitFee{
type
quantity
}
revealFee{
type
quantity
}
revealTime
bidAmount{
type
quantity
}
status
}
}
}
}
```
LookUp Names
```graphql
{
lookupNames(names: ["crn://hello/test"]){
latest{
id
height
}
history{
id
height
}
}
}
```
Resolve Names
```graphql
{
resolveNames(names: ["asd"]){
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
```
+5 -5
View File
@@ -4,7 +4,7 @@ FROM golang:alpine AS build-env
ENV PACKAGES git build-base
# Set working directory for the build
WORKDIR /go/src/github.com/vulcanize/chiba-clonk
WORKDIR /go/src/github.com/tharsis/ethermint
# Install dependencies
RUN apk add --update $PACKAGES
@@ -17,14 +17,14 @@ COPY . .
RUN make build
# Final image
FROM alpine:3.15
FROM alpine
# Install ca-certificates
RUN apk add --update ca-certificates jq
WORKDIR /
# Copy over binaries from the build-env
COPY --from=build-env /go/src/github.com/vulcanize/chiba-clonk/build/chibaclonkd /usr/bin/chibaclonkd
COPY --from=build-env /go/src/github.com/tharsis/ethermint/build/ethermintd /usr/bin/ethermintd
# Run chibaclonkd by default
CMD ["chibaclonkd"]
# Run ethermintd by default
CMD ["ethermintd"]
+169 -133
View File
@@ -1,165 +1,201 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
0. Additional Definitions.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
1. Exception to Section 3 of the GNU GPL.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Conveying Modified Versions.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
3. Object Code Incorporating Material from Library Header Files.
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
4. Combined Works.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
d) Do one of the following:
END OF TERMS AND CONDITIONS
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
APPENDIX: How to apply the Apache License to your work.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
Copyright [yyyy] [name of copyright owner]
5. Combined Libraries.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
http://www.apache.org/licenses/LICENSE-2.0
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+131 -90
View File
@@ -7,11 +7,11 @@ TMVERSION := $(shell go list -m github.com/tendermint/tendermint | sed 's:.* ::'
COMMIT := $(shell git log -1 --format='%H')
LEDGER_ENABLED ?= true
BINDIR ?= $(GOPATH)/bin
CHIBACLONK_BINARY = chibaclonkd
CHIBACLONK_DIR = chibaclonk
ETHERMINT_BINARY = ethermintd
ETHERMINT_DIR = ethermint
BUILDDIR ?= $(CURDIR)/build
SIMAPP = ./app
HTTPS_GIT := https://github.com/vulcanize/chiba-clonk.git
HTTPS_GIT := https://github.com/tharsis/ethermint.git
DOCKER := $(shell which docker)
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
@@ -62,8 +62,8 @@ build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags))
# process linker flags
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=chibaclonk \
-X github.com/cosmos/cosmos-sdk/version.AppName=$(CHIBACLONK_BINARY) \
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=ethermint \
-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)" \
@@ -73,10 +73,8 @@ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=chibaclonk \
ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS)))
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=cleveldb
endif
ifeq (badgerdb,$(findstring badgerdb,$(COSMOS_BUILD_OPTIONS)))
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=badgerdb
BUILD_TAGS += badgerdb
endif
# handle rocksdb
ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS)))
@@ -90,27 +88,18 @@ ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS)))
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=boltdb
endif
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
ldflags += -w -s
endif
ldflags += $(LDFLAGS)
ldflags := $(strip $(ldflags))
build_tags += $(BUILD_TAGS)
build_tags := $(strip $(build_tags))
BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)'
# Check for debug option
ifeq (debug,$(findstring debug,$(COSMOS_BUILD_OPTIONS)))
BUILD_FLAGS += -gcflags 'all=-N -l'
COSMOS_BUILD_OPTIONS += nostrip
endif
# check for nostrip option
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
BUILD_FLAGS += -trimpath
ldflags += -w -s
endif
all: tools build lint test
# # The below include contains the tools and runsim targets.
# include contrib/devtools/Makefile
@@ -122,16 +111,14 @@ BUILD_TARGETS := build install
build: BUILD_ARGS=-o $(BUILDDIR)/
build-linux:
GOOS=linux GOARCH=$(if $(findstring aarch64,$(shell uname -m)) || $(findstring arm64,$(shell uname -m)),arm64,amd64) LEDGER_ENABLED=false $(MAKE) build
GOOS=linux GOARCH=amd64 LEDGER_ENABLED=false $(MAKE) build
$(BUILD_TARGETS): go.sum $(BUILDDIR)/
go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./...
go $@ $(BUILD_FLAGS) $(BUILD_ARGS) ./...
$(BUILDDIR)/:
mkdir -p $(BUILDDIR)/
.PHONY: build build-linux cosmovisor
docker-build:
# TODO replace with kaniko
docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} .
@@ -162,43 +149,6 @@ build-all: tools build lint test
.PHONY: distclean clean build-all
###############################################################################
### Releasing ###
###############################################################################
PACKAGE_NAME:=github.com/tharsis/ethermint
GOLANG_CROSS_VERSION = v1.17.1
GOPATH ?= '$(HOME)/go'
release-dry-run:
docker run \
--rm \
--privileged \
-e CGO_ENABLED=1 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v `pwd`:/go/src/$(PACKAGE_NAME) \
-v ${GOPATH}/pkg:/go/pkg \
-w /go/src/$(PACKAGE_NAME) \
ghcr.io/troian/golang-cross:${GOLANG_CROSS_VERSION} \
--rm-dist --skip-validate --skip-publish
release:
@if [ ! -f ".release-env" ]; then \
echo "\033[91m.release-env is required for release\033[0m";\
exit 1;\
fi
docker run \
--rm \
--privileged \
-e CGO_ENABLED=1 \
--env-file .release-env \
-v /var/run/docker.sock:/var/run/docker.sock \
-v `pwd`:/go/src/$(PACKAGE_NAME) \
-w /go/src/$(PACKAGE_NAME) \
ghcr.io/troian/golang-cross:${GOLANG_CROSS_VERSION} \
release --rm-dist --skip-validate
.PHONY: release-dry-run release
###############################################################################
### Tools & Dependencies ###
###############################################################################
@@ -266,8 +216,16 @@ else
@echo "solcjs already installed; skipping..."
endif
docs-tools:
ifeq (, $(shell which yarn))
@echo "Installing yarn..."
@npm install -g yarn
else
@echo "yarn already installed; skipping..."
endif
tools: tools-stamp
tools-stamp: contract-tools proto-tools statik runsim
tools-stamp: contract-tools docs-tools proto-tools statik runsim
# Create dummy file to satisfy dependency and avoid
# rebuilding when this Makefile target is hit twice
# in a row.
@@ -277,7 +235,13 @@ tools-clean:
rm -f $(RUNSIM)
rm -f tools-stamp
.PHONY: runsim statik tools contract-tools proto-tools tools-stamp tools-clean
docs-tools-stamp: docs-tools
# Create dummy file to satisfy dependency and avoid
# rebuilding when this Makefile target is hit twice
# in a row.
touch $@
.PHONY: runsim statik tools contract-tools docs-tools proto-tools tools-stamp tools-clean docs-tools-stamp
go.sum: go.mod
echo "Ensure dependencies have not been modified ..." >&2
@@ -302,13 +266,41 @@ godocs:
@echo "--> Wait a few seconds and visit http://localhost:6060/pkg/github.com/tharsis/ethermint/types"
godoc -http=:6060
# Start docs site at localhost:8080
docs-serve:
@cd docs && \
yarn && \
yarn run serve
# Build the site into docs/.vuepress/dist
build-docs:
@$(MAKE) docs-tools-stamp && \
cd docs && \
yarn && \
yarn run build
# This builds a docs site for each branch/tag in `./docs/versions`
# and copies each site to a version prefixed path. The last entry inside
# the `versions` file will be the default root index.html.
build-docs-versioned:
@$(MAKE) docs-tools-stamp && \
cd docs && \
while read -r branch path_prefix; do \
(git checkout $${branch} && npm install && VUEPRESS_BASE="/$${path_prefix}/" npm run build) ; \
mkdir -p ~/output/$${path_prefix} ; \
cp -r .vuepress/dist/* ~/output/$${path_prefix}/ ; \
cp ~/output/$${path_prefix}/index.html ~/output ; \
done < versions ;
.PHONY: docs-serve build-docs build-docs-versioned
###############################################################################
### Tests & Simulation ###
###############################################################################
test: test-unit
test-all: test-unit test-race
PACKAGES_UNIT=$(shell go list ./... | grep -Ev 'vendor|importer')
PACKAGES_UNIT=$(shell go list ./...)
TEST_PACKAGES=./...
TEST_TARGETS := test-unit test-unit-cover test-race
@@ -333,17 +325,22 @@ else
endif
test-import:
go test -run TestImporterTestSuite -v --vet=off github.com/tharsis/ethermint/tests/importer
@go test ./tests/importer -v --vet=off --run=TestImportBlocks --datadir tmp \
--blockchain blockchain
rm -rf tests/importer/tmp
test-rpc:
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
test-integration:
./scripts/integration-test-all.sh -t "integration" -q 1 -z 1 -s 2 -m "integration" -r "true"
test-rpc-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)
@type "solcjs" 2> /dev/null || (echo 'Solcjs does not exist. Please install solcjs using make contract-tools."' && exit 1)
@type "protoc" 2> /dev/null || (echo 'Failed to install protoc. Please reinstall protoc using make contract-tools.' && exit 1)
bash scripts/contract-test.sh
test-solidity:
@echo "Beginning solidity tests..."
./scripts/run-solidity-tests.sh
@@ -358,8 +355,8 @@ test-sim-nondeterminism:
test-sim-custom-genesis-fast:
@echo "Running custom genesis simulation..."
@echo "By default, ${HOME}/.$(CHIBACLONK_DIR)/config/genesis.json will be used."
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.$(CHIBACLONK_DIR)/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
@@ -372,8 +369,8 @@ test-sim-after-import: runsim
test-sim-custom-genesis-multi-seed: runsim
@echo "Running multi-seed custom genesis simulation..."
@echo "By default, ${HOME}/.$(CHIBACLONK_DIR)/config/genesis.json will be used."
@$(BINDIR)/runsim -Genesis=${HOME}/.$(CHIBACLONK_DIR)/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
@echo "By default, ${HOME}/.$(ETHERMINT_DIR)/config/genesis.json will be used."
@$(BINDIR)/runsim -Genesis=${HOME}/.$(ETHERMINT_DIR)/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
test-sim-multi-seed-long: runsim
@echo "Running long multi-seed application simulation. This may take awhile!"
@@ -426,23 +423,30 @@ format-fix:
### Protobuf ###
###############################################################################
containerProtoVer=v0.2
containerProtoImage=tendermintdev/sdk-proto-gen:$(containerProtoVer)
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(containerProtoVer)
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(containerProtoVer)
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(containerProtoVer)
protoVer=v0.2
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(protoVer)
containerProtoGenAny=$(PROJECT_NAME)-proto-gen-any-$(protoVer)
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(protoVer)
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(protoVer)
proto-all: proto-format proto-lint proto-gen
proto-gen:
@echo "Generating Protobuf files"
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(containerProtoImage) \
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
sh ./scripts/protocgen.sh; fi
# This generates the SDK's custom wrapper for google.protobuf.Any. It should only be run manually when needed
proto-gen-any:
@echo "Generating Protobuf Any"
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGenAny}$$"; then docker start -a $(containerProtoGenAny); else docker run --name $(containerProtoGenAny) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
sh ./scripts/protocgen-any.sh; fi
proto-swagger-gen:
@echo "Generating Protobuf Swagger"
@./scripts/proto-tools-installer.sh
@./scripts/protoc-swagger-gen.sh
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGenSwagger}$$"; then docker start -a $(containerProtoGenSwagger); else docker run --name $(containerProtoGenSwagger) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
sh ./scripts/protoc-swagger-gen.sh; fi
proto-format:
@echo "Formatting Protobuf files"
@@ -508,19 +512,19 @@ ifeq ($(OS),Windows_NT)
mkdir localnet-setup &
@$(MAKE) localnet-build
IF not exist "build/node0/$(CHIBACLONK_BINARY)/config/genesis.json" docker run --rm -v $(CURDIR)/build\ethermint\Z chibaclonkd/node sh -c "chibaclonkd testnet init-files --v 4 --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 --keyring-backend=test --ip-addresses ethermintdnode0,ethermintdnode1,ethermintdnode2,ethermintdnode3"
docker-compose up -d
else
mkdir -p localnet-setup
@$(MAKE) localnet-build
if ! [ -f localnet-setup/node0/$(CHIBACLONK_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/localnet-setup:/localnet-setup:Z chibaclonkd/node sh -c "chibaclonkd testnet init-files --v 4 --keyring-backend=test"; fi
if ! [ -f localnet-setup/node0/$(ETHERMINT_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/localnet-setup:/ethermint:Z ethermintd/node "./ethermintd testnet --v 4 -o /ethermint --keyring-backend=test --ip-addresses ethermintdnode0,ethermintdnode1,ethermintdnode2,ethermintdnode3"; fi
docker-compose up -d
endif
# Stop testnet
localnet-stop:
docker-compose down -v
docker-compose down
# Clean testnet
localnet-clean:
@@ -531,15 +535,15 @@ localnet-clean:
localnet-unsafe-reset:
docker-compose down
ifeq ($(OS),Windows_NT)
@docker run --rm -v $(CURDIR)\localnet-setup\node0\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node1\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node2\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node3\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node0\ethermitd:ethermint\Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
@docker run --rm -v $(CURDIR)\localnet-setup\node1\ethermitd:ethermint\Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
@docker run --rm -v $(CURDIR)\localnet-setup\node2\ethermitd:ethermint\Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
@docker run --rm -v $(CURDIR)\localnet-setup\node3\ethermitd:ethermint\Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
else
@docker run --rm -v $(CURDIR)/localnet-setup/node0/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node1/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node2/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node3/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node0/ethermitd:/ethermint:Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
@docker run --rm -v $(CURDIR)/localnet-setup/node1/ethermitd:/ethermint:Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
@docker run --rm -v $(CURDIR)/localnet-setup/node2/ethermitd:/ethermint:Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
@docker run --rm -v $(CURDIR)/localnet-setup/node3/ethermitd:/ethermint:Z ethermintd/node "./ethermintd unsafe-reset-all --home=/ethermint"
endif
# Clean testnet
@@ -547,3 +551,40 @@ localnet-show-logstream:
docker-compose logs --tail=1000 -f
.PHONY: build-docker-local-ethermint localnet-start localnet-stop
###############################################################################
### Releasing ###
###############################################################################
PACKAGE_NAME:=github.com/tharsis/ethermint
GOLANG_CROSS_VERSION = v1.17
release-dry-run:
docker run \
--rm \
--privileged \
-e CGO_ENABLED=1 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v `pwd`:/go/src/$(PACKAGE_NAME) \
-v ${GOPATH}/pkg:/go/pkg \
-w /go/src/$(PACKAGE_NAME) \
troian/golang-cross:${GOLANG_CROSS_VERSION} \
--rm-dist --skip-validate --skip-publish
release:
@if [ ! -f ".release-env" ]; then \
echo "\033[91m.release-env is required for release\033[0m";\
exit 1;\
fi
docker run \
--rm \
--privileged \
-e CGO_ENABLED=1 \
--env-file .release-env \
-v /var/run/docker.sock:/var/run/docker.sock \
-v `pwd`:/go/src/$(PACKAGE_NAME) \
-w /go/src/$(PACKAGE_NAME) \
troian/golang-cross:${GOLANG_CROSS_VERSION} \
release --rm-dist --skip-validate
.PHONY: release-dry-run release
+16 -9
View File
@@ -30,21 +30,28 @@ parent:
<a href="https://discord.gg/trje9XuAmy">
<img alt="Discord" src="https://img.shields.io/discord/809048090249134080.svg" />
</a>
<!-- <a href="https://github.com/tharsis/ethermint/actions?query=branch%3Amain+workflow%3ABuild">
<img alt="Build Status" src="https://github.com/tharsis/ethermint/actions/workflows/build.yml/badge.svg?branch=main" />
</a> -->
<a href="https://github.com/tharsis/ethermint/actions?query=branch%3Amain+workflow%3ALint">
<img alt="Lint Status" src="https://github.com/tharsis/ethermint/actions/workflows/lint.yml/badge.svg?branch=main" />
</a>
<a href="https://codecov.io/gh/tharsis/ethermint">
<img alt="Code Coverage" src="https://codecov.io/gh/tharsis/ethermint/branch/main/graph/badge.svg" />
</a>
<a href="https://twitter.com/ethermint">
<img alt="Twitter Follow Ethermint" src="https://img.shields.io/twitter/follow/ethermint"/>
</a>
</div>
Ethermint is a scalable and interoperable Ethereum library, built on Proof-of-Stake with fast-finality using the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk/) which runs on top of [Tendermint Core](https://github.com/tendermint/tendermint) consensus engine.
Ethermint is a scalable, high-throughput Proof-of-Stake blockchain that is fully compatible and
interoperable with Ethereum. It's build using the the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk/) which runs on top of [Tendermint Core](https://github.com/tendermint/tendermint) consensus engine.
**Note**: Requires [Go 1.17+](https://golang.org/dl/)
## Installation
For prerequisites and detailed build instructions please read the Evmos [Installation](https://evmos.dev/quickstart/installation.html) instructions. Once the dependencies are installed, run:
For prerequisites and detailed build instructions please read the [Installation](https://ethermint.dev/quickstart/installation.html) instructions. Once the dependencies are installed, run:
```bash
make install
@@ -54,18 +61,18 @@ Or check out the latest [release](https://github.com/tharsis/ethermint/releases)
## Quick Start
To learn how the Ethermint works from a high-level perspective, go to the [Introduction](https://evmos.dev/intro/overview.html) section from the documentation. You can also check the instructions to [Run a Node](https://evmos.dev/quickstart/run_node.html).
To learn how the Ethermint works from a high-level perspective, go to the [Introduction](https://ethermint.dev/intro/overview.html) section from the documentation. You can also check the instructions to [Run a Node](https://ethermint.dev/quickstart/run_node.html).
For an example on how Ethermint can be used on any Cosmos-SDK chain, please refer to [Evmos](https://www.github.com/tharsis/evmos).
For more, please refer to the [Ethermint Docs](./docs/), which are also hosted on [ethermint.dev](https://ethermint.dev/).
## Community
The following chat channels and forums are a great spot to ask questions about Ethermint:
- [Evmos Twitter](https://twitter.com/EvmosOrg)
- [Evmos Discord](https://discord.gg/trje9XuAmy)
- [Evmos Telegram](https://t.me/EvmosOrg)
- [Tharsis Twitter](https://twitter.com/TharsisHQ)
- [Ethermint Twitter](https://twitter.com/ethermint)
- [Tharsis Twitter](https://twitter.com/ethermint)
- [Ethermint Discord](https://discord.gg/trje9XuAmy)
- [Ethermint Forum](https://forum.cosmos.network/c/ethermint)
## Contributing
@@ -75,4 +82,4 @@ For additional instructions, standards and style guides, please refer to the [Co
## Careers
See our open positions on [Cosmos Jobs](https://jobs.cosmos.network/project/evmos-d0sk1uxuh-remote/), [Notion](https://tharsis.notion.site), or feel free to [reach out](mailto:careers@thars.is) via email.
See our open positions on [Cosmos Jobs](https://jobs.cosmos.network/project/ethermint-d0sk1uxuh-remote/), [Notion](https://tharsis.notion.site/Jobs-at-Tharsis-5a1642eb89b34747ae6f2db2d356fc0d), or feel free to [reach out](mailto:careers@thars.is) via email.
-17
View File
@@ -1,17 +0,0 @@
package app
import (
sdk "github.com/cosmos/cosmos-sdk/types"
cmdcfg "github.com/tharsis/ethermint/cmd/config"
)
// sdk config
func init() {
config := sdk.GetConfig()
cmdcfg.SetBech32Prefixes(config)
cmdcfg.SetBip44CoinType(config)
config.Seal()
cmdcfg.RegisterDenoms()
}
+54 -10
View File
@@ -4,15 +4,22 @@ import (
"fmt"
"runtime/debug"
"github.com/palantir/stacktrace"
tmlog "github.com/tendermint/tendermint/libs/log"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper"
ibcante "github.com/cosmos/ibc-go/modules/core/ante"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
const (
@@ -23,7 +30,14 @@ const (
// 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(options HandlerOptions) sdk.AnteHandler {
func NewAnteHandler(
ak evmtypes.AccountKeeper,
bankKeeper evmtypes.BankKeeper,
evmKeeper EVMKeeper,
feeGrantKeeper authante.FeegrantKeeper,
channelKeeper channelkeeper.Keeper,
signModeHandler authsigning.SignModeHandler,
) sdk.AnteHandler {
return func(
ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) {
@@ -38,14 +52,25 @@ func NewAnteHandler(options HandlerOptions) sdk.AnteHandler {
switch typeURL := opts[0].GetTypeUrl(); typeURL {
case "/ethermint.evm.v1.ExtensionOptionsEthereumTx":
// handle as *evmtypes.MsgEthereumTx
anteHandler = newEthAnteHandler(options)
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
anteHandler = newCosmosAnteHandlerEip712(options)
anteHandler = sdk.ChainAnteDecorators(
NewEthSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
authante.NewMempoolFeeDecorator(),
authante.NewTxTimeoutHeightDecorator(),
authante.NewValidateMemoDecorator(ak),
NewEthValidateBasicDecorator(),
NewEthSigVerificationDecorator(evmKeeper),
NewEthAccountVerificationDecorator(ak, bankKeeper, evmKeeper),
NewEthNonceVerificationDecorator(ak),
NewEthGasConsumeDecorator(ak, bankKeeper, evmKeeper),
NewCanTransferDecorator(evmKeeper),
NewEthIncrementSenderSequenceDecorator(ak), // innermost AnteDecorator.
)
default:
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrUnknownExtensionOptions,
"rejecting tx with unsupported extension option: %s", typeURL,
return ctx, stacktrace.Propagate(
sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, typeURL),
"rejecting tx with unsupported extension option",
)
}
@@ -54,11 +79,30 @@ func NewAnteHandler(options HandlerOptions) sdk.AnteHandler {
}
// handle as totally normal Cosmos SDK tx
switch tx.(type) {
case sdk.Tx:
anteHandler = newCosmosAnteHandler(options)
anteHandler = sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
authante.NewRejectExtensionOptionsDecorator(),
authante.NewMempoolFeeDecorator(),
authante.NewValidateBasicDecorator(),
authante.NewTxTimeoutHeightDecorator(),
authante.NewValidateMemoDecorator(ak),
ibcante.NewAnteDecorator(channelKeeper),
authante.NewConsumeGasForTxSizeDecorator(ak),
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
authante.NewValidateSigCountDecorator(ak),
authante.NewDeductFeeDecorator(ak, bankKeeper, feeGrantKeeper),
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)
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx),
"transaction is not an SDK tx",
)
}
return anteHandler(ctx, tx, sim)
+19 -559
View File
@@ -1,22 +1,16 @@
package ante_test
import (
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"math/big"
"strings"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/core/types"
ethparams "github.com/ethereum/go-ethereum/params"
"github.com/tharsis/ethermint/tests"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
func (suite AnteTestSuite) TestAnteHandler() {
suite.enableFeemarket = false
suite.SetupTest() // reset
addr, privKey := tests.NewAddrKey()
to := tests.GenerateAddress()
@@ -24,9 +18,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
suite.Require().NoError(acc.SetSequence(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000))
suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100))
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(10000000000))
testCases := []struct {
name string
@@ -38,20 +30,10 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"success - DeliverTx (contract)",
func() sdk.Tx {
signedContractTx := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedContractTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
return tx
},
false, false, true,
@@ -59,20 +41,10 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"success - CheckTx (contract)",
func() sdk.Tx {
signedContractTx := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
2,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedContractTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
return tx
},
true, false, true,
@@ -80,20 +52,10 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"success - ReCheckTx (contract)",
func() sdk.Tx {
signedContractTx := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
3,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedContractTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
tx := suite.CreateTestTx(signedContractTx, privKey, 1, true)
return tx
},
false, true, true,
@@ -101,21 +63,10 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"success - DeliverTx",
func() sdk.Tx {
signedTx := evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
4,
&to,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
},
false, false, true,
@@ -123,21 +74,10 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"success - CheckTx",
func() sdk.Tx {
signedTx := evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
5,
&to,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 2, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
},
true, false, true,
@@ -145,39 +85,17 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"success - ReCheckTx",
func() sdk.Tx {
signedTx := evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
6,
&to,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 3, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
}, false, true, true,
},
{
"success - CheckTx (cosmos tx not signed)",
func() sdk.Tx {
signedTx := evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
7,
&to,
big.NewInt(10),
100000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
nil,
)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
@@ -187,212 +105,31 @@ func (suite AnteTestSuite) TestAnteHandler() {
{
"fail - CheckTx (cosmos tx is not valid)",
func() sdk.Tx {
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 8, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 4, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
// bigger than MaxGasWanted
txBuilder.SetGasLimit(uint64(1 << 63))
return txBuilder.GetTx()
}, true, false, false,
}, false, true, false,
},
{
"fail - CheckTx (memo too long)",
func() sdk.Tx {
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, true)
txBuilder.SetMemo(strings.Repeat("*", 257))
return txBuilder.GetTx()
}, true, false, false,
},
{
"fail - CheckTx (ExtensionOptionsEthereumTx not set)",
func() sdk.Tx {
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 5, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false, true)
return txBuilder.GetTx()
}, true, false, false,
},
// Based on EVMBackend.SendTransaction, for cosmos tx, forcing null for some fields except ExtensionOptions, Fee, MsgEthereumTx
// should be part of consensus
{
"fail - DeliverTx (cosmos tx signed)",
func() sdk.Tx {
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, true)
return tx
}, false, false, false,
},
{
"fail - DeliverTx (cosmos tx with memo)",
func() sdk.Tx {
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
txBuilder.SetMemo("memo for cosmos tx not allowed")
return txBuilder.GetTx()
}, false, false, false,
},
{
"fail - DeliverTx (cosmos tx with timeoutheight)",
func() sdk.Tx {
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
txBuilder.SetTimeoutHeight(10)
return txBuilder.GetTx()
}, false, false, false,
},
{
"fail - DeliverTx (invalid fee amount)",
func() sdk.Tx {
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
txData, err := evmtypes.UnpackTxData(signedTx.Data)
suite.Require().NoError(err)
expFee := txData.Fee()
invalidFee := new(big.Int).Add(expFee, big.NewInt(1))
invalidFeeAmount := sdk.Coins{sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(invalidFee))}
txBuilder.SetFeeAmount(invalidFeeAmount)
return txBuilder.GetTx()
}, false, false, false,
},
{
"fail - DeliverTx (invalid fee gaslimit)",
func() sdk.Tx {
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
signedTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
expGasLimit := signedTx.GetGas()
invalidGasLimit := expGasLimit + 1
txBuilder.SetGasLimit(invalidGasLimit)
return txBuilder.GetTx()
}, false, false, false,
},
{
"success - DeliverTx EIP712 signed Cosmos Tx with MsgSend",
func() sdk.Tx {
from := acc.GetAddress()
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{
"success - DeliverTx EIP712 signed Cosmos Tx with DelegateMsg",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgDelegate(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
func() sdk.Tx {
from := acc.GetAddress()
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9002-1", gas, amount)
return txBuilder.GetTx()
}, false, false, false,
},
{
"fails - DeliverTx EIP712 signed Cosmos Tx with different gas fees",
func() sdk.Tx {
from := acc.GetAddress()
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
txBuilder.SetGasLimit(uint64(300000))
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(30))))
return txBuilder.GetTx()
}, false, false, false,
},
{
"fails - DeliverTx EIP712 signed Cosmos Tx with empty signature",
func() sdk.Tx {
from := acc.GetAddress()
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
sigsV2 := signing.SignatureV2{}
txBuilder.SetSignatures(sigsV2)
return txBuilder.GetTx()
}, false, false, false,
},
{
"fails - DeliverTx EIP712 signed Cosmos Tx with invalid sequence",
func() sdk.Tx {
from := acc.GetAddress()
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
sigsV2 := signing.SignatureV2{
PubKey: privKey.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
},
Sequence: nonce - 1,
}
txBuilder.SetSignatures(sigsV2)
return txBuilder.GetTx()
}, false, false, false,
},
{
"fails - DeliverTx EIP712 signed Cosmos Tx with invalid signMode",
func() sdk.Tx {
from := acc.GetAddress()
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
suite.Require().NoError(err)
sigsV2 := signing.SignatureV2{
PubKey: privKey.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_UNSPECIFIED,
},
Sequence: nonce,
}
txBuilder.SetSignatures(sigsV2)
return txBuilder.GetTx()
}, false, false, false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
suite.ctx = suite.ctx.WithIsCheckTx(tc.reCheckTx).WithIsReCheckTx(tc.reCheckTx)
// expConsumed := params.TxGasContractCreation + params.TxGas
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
@@ -408,280 +145,3 @@ func (suite AnteTestSuite) TestAnteHandler() {
})
}
}
func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
addr, privKey := tests.NewAddrKey()
to := tests.GenerateAddress()
testCases := []struct {
name string
txFn func() sdk.Tx
enableLondonHF bool
checkTx bool
reCheckTx bool
expPass bool
}{
{
"success - DeliverTx (contract)",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
true,
false, false, true,
},
{
"success - CheckTx (contract)",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
true,
true, false, true,
},
{
"success - ReCheckTx (contract)",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
true,
false, true, true,
},
{
"success - DeliverTx",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
},
true,
false, false, true,
},
{
"success - CheckTx",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
},
true,
true, false, true,
},
{
"success - ReCheckTx",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
},
true,
false, true, true,
},
{
"success - CheckTx (cosmos tx not signed)",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()
tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
},
true,
false, true, true,
},
{
"fail - CheckTx (cosmos tx is not valid)",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
// bigger than MaxGasWanted
txBuilder.SetGasLimit(uint64(1 << 63))
return txBuilder.GetTx()
},
true,
true, false, false,
},
{
"fail - CheckTx (memo too long)",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
txBuilder.SetMemo(strings.Repeat("*", 257))
return txBuilder.GetTx()
},
true,
true, false, false,
},
{
"fail - DynamicFeeTx without london hark fork",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
false,
false, false, false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.enableFeemarket = true
suite.enableLondonHF = tc.enableLondonHF
suite.SetupTest() // reset
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.Require().NoError(acc.SetSequence(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000))
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
suite.enableFeemarket = false
suite.enableLondonHF = true
}
-272
View File
@@ -1,272 +0,0 @@
package ante
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/ethereum/eip712"
ethermint "github.com/tharsis/ethermint/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
var ethermintCodec codec.ProtoCodecMarshaler
func init() {
registry := codectypes.NewInterfaceRegistry()
ethermint.RegisterInterfaces(registry)
ethermintCodec = codec.NewProtoCodec(registry)
}
// Eip712SigVerificationDecorator Verify all signatures for a tx and return an error if any are invalid. Note,
// the Eip712SigVerificationDecorator decorator will not get executed on ReCheck.
//
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
// CONTRACT: Tx must implement SigVerifiableTx interface
type Eip712SigVerificationDecorator struct {
ak evmtypes.AccountKeeper
signModeHandler authsigning.SignModeHandler
}
// NewEip712SigVerificationDecorator creates a new Eip712SigVerificationDecorator
func NewEip712SigVerificationDecorator(ak evmtypes.AccountKeeper, signModeHandler authsigning.SignModeHandler) Eip712SigVerificationDecorator {
return Eip712SigVerificationDecorator{
ak: ak,
signModeHandler: signModeHandler,
}
}
// AnteHandle handles validation of EIP712 signed cosmos txs.
// it is not run on RecheckTx
func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// no need to verify signatures on recheck tx
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
}
authSignTx, ok := tx.(authsigning.Tx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
}
// stdSigs contains the sequence number, account number, and signatures.
// When simulating, this would just be a 0-length slice.
sigs, err := sigTx.GetSignaturesV2()
if err != nil {
return ctx, err
}
signerAddrs := sigTx.GetSigners()
// EIP712 allows just one signature
if len(sigs) != 1 {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
}
// check that signer length and signature length are the same
if len(sigs) != len(signerAddrs) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
}
// EIP712 has just one signature, avoid looping here and only read index 0
i := 0
sig := sigs[i]
acc, err := authante.GetSignerAcc(ctx, svd.ak, signerAddrs[i])
if err != nil {
return ctx, err
}
// retrieve pubkey
pubKey := acc.GetPubKey()
if !simulate && pubKey == nil {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
}
// Check account sequence number.
if sig.Sequence != acc.GetSequence() {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrWrongSequence,
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
)
}
// retrieve signer data
genesis := ctx.BlockHeight() == 0
chainID := ctx.ChainID()
var accNum uint64
if !genesis {
accNum = acc.GetAccountNumber()
}
signerData := authsigning.SignerData{
ChainID: chainID,
AccountNumber: accNum,
Sequence: acc.GetSequence(),
}
if simulate {
return next(ctx, tx, simulate)
}
if err := VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg.Error())
}
return next(ctx, tx, simulate)
}
// VerifySignature verifies a transaction signature contained in SignatureData abstracting over different signing modes
// and single vs multi-signatures.
func VerifySignature(
pubKey cryptotypes.PubKey,
signerData authsigning.SignerData,
sigData signing.SignatureData,
_ authsigning.SignModeHandler,
tx authsigning.Tx,
) error {
switch data := sigData.(type) {
case *signing.SingleSignatureData:
if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
return sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
}
// Note: this prevents the user from sending thrash data in the signature field
if len(data.Signature) != 0 {
return sdkerrors.Wrap(sdkerrors.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
}
// @contract: this code is reached only when Msg has Web3Tx extension (so this custom Ante handler flow),
// and the signature is SIGN_MODE_LEGACY_AMINO_JSON which is supported for EIP712 for now
msgs := tx.GetMsgs()
if len(msgs) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
}
txBytes := legacytx.StdSignBytes(
signerData.ChainID,
signerData.AccountNumber,
signerData.Sequence,
tx.GetTimeoutHeight(),
legacytx.StdFee{
Amount: tx.GetFee(),
Gas: tx.GetGas(),
},
msgs, tx.GetMemo(), tx.GetTip(),
)
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
if err != nil {
return sdkerrors.Wrapf(err, "failed to parse chainID: %s", signerData.ChainID)
}
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
}
opts := txWithExtensions.GetExtensionOptions()
if len(opts) != 1 {
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
}
var optIface ethermint.ExtensionOptionsWeb3TxI
if err := ethermintCodec.UnpackAny(opts[0], &optIface); err != nil {
return sdkerrors.Wrap(err, "failed to proto-unpack ExtensionOptionsWeb3Tx")
}
extOpt, ok := optIface.(*ethermint.ExtensionOptionsWeb3Tx)
if !ok {
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "unknown extension option")
}
if extOpt.TypedDataChainID != signerChainID.Uint64() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "invalid chainID")
}
if len(extOpt.FeePayer) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
}
feePayer, err := sdk.AccAddressFromBech32(extOpt.FeePayer)
if err != nil {
return sdkerrors.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
}
feeDelegation := &eip712.FeeDelegationOptions{
FeePayer: feePayer,
}
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
if err != nil {
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
}
sigHash, err := eip712.ComputeTypedDataHash(typedData)
if err != nil {
return err
}
feePayerSig := extOpt.FeePayerSig
if len(feePayerSig) != ethcrypto.SignatureLength {
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
}
// Remove the recovery offset if needed (ie. Metamask eip712 signature)
if feePayerSig[ethcrypto.RecoveryIDOffset] == 27 || feePayerSig[ethcrypto.RecoveryIDOffset] == 28 {
feePayerSig[ethcrypto.RecoveryIDOffset] -= 27
}
feePayerPubkey, err := secp256k1.RecoverPubkey(sigHash, feePayerSig)
if err != nil {
return sdkerrors.Wrap(err, "failed to recover delegated fee payer from sig")
}
ecPubKey, err := ethcrypto.UnmarshalPubkey(feePayerPubkey)
if err != nil {
return sdkerrors.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
}
pk := &ethsecp256k1.PubKey{
Key: ethcrypto.CompressPubkey(ecPubKey),
}
if !pubKey.Equals(pk) {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
}
recoveredFeePayerAcc := sdk.AccAddress(pk.Address().Bytes())
if !recoveredFeePayerAcc.Equals(feePayer) {
return sdkerrors.Wrapf(sdkerrors.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
}
// VerifySignature of ethsecp256k1 accepts 64 byte signature [R||S]
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
if !secp256k1.VerifySignature(pubKey.Bytes(), sigHash, feePayerSig[:len(feePayerSig)-1]) {
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
}
return nil
default:
return sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
}
}
+268 -254
View File
@@ -7,16 +7,31 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/palantir/stacktrace"
ethermint "github.com/tharsis/ethermint/types"
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
// EVMKeeper defines the expected keeper interface used on the Eth AnteHandler
type EVMKeeper interface {
vm.StateDB
ChainID() *big.Int
GetParams(ctx sdk.Context) evmtypes.Params
WithContext(ctx sdk.Context)
ResetRefundTransient(ctx sdk.Context)
NewEVM(msg core.Message, config *params.ChainConfig, params evmtypes.Params, coinbase common.Address, tracer vm.Tracer) *vm.EVM
GetCodeHash(addr common.Address) common.Hash
}
// EthSigVerificationDecorator validates an ethereum signatures
type EthSigVerificationDecorator struct {
evmKeeper EVMKeeper
@@ -35,6 +50,13 @@ func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
// won't see the error message.
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if tx == nil || len(tx.GetMsgs()) != 1 {
return ctx, stacktrace.Propagate(
sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "only 1 ethereum msg supported per tx"),
"",
)
}
chainID := esvd.evmKeeper.ChainID()
params := esvd.evmKeeper.GetParams(ctx)
@@ -43,27 +65,28 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
blockNum := big.NewInt(ctx.BlockHeight())
signer := ethtypes.MakeSigner(ethCfg, blockNum)
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
sender, err := signer.Sender(msgEthTx.AsTransaction())
if err != nil {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrorInvalidSigner,
"couldn't retrieve sender address ('%s') from the ethereum transaction: %s",
msgEthTx.From,
err.Error(),
)
}
// set up the sender to the transaction field if not already
msgEthTx.From = sender.Hex()
msg := tx.GetMsgs()[0]
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction",
)
}
return next(ctx, tx, simulate)
sender, err := signer.Sender(msgEthTx.AsTransaction())
if err != nil {
return ctx, stacktrace.Propagate(
sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, err.Error()),
"couldn't retrieve sender address ('%s') from the ethereum transaction",
msgEthTx.From,
)
}
// set up the sender to the transaction field if not already
msgEthTx.From = sender.Hex()
return next(ctx, msgEthTx, simulate)
}
// EthAccountVerificationDecorator validates an account balance checks
@@ -93,59 +116,128 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
return next(ctx, tx, simulate)
}
avd.evmKeeper.WithContext(ctx)
evmDenom := avd.evmKeeper.GetParams(ctx).EvmDenom
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction %d", i,
)
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
return ctx, stacktrace.Propagate(err, "failed to unpack tx data any for tx %d", i)
}
// sender address should be in the tx cache from the previous AnteHandle call
from := msgEthTx.GetFrom()
if from.Empty() {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty")
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "from address cannot be empty"),
"sender address should have been in the tx field from the previous AnteHandle call",
)
}
// check whether the sender address is EOA
fromAddr := common.BytesToAddress(from)
acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
if acct == nil {
acc := avd.ak.NewAccountWithAddress(ctx, from)
avd.ak.SetAccount(ctx, acc)
acct = statedb.NewEmptyAccount()
} else if acct.IsContract() {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
codeHash := avd.evmKeeper.GetCodeHash(fromAddr)
if codeHash != common.BytesToHash(evmtypes.EmptyCodeHash) {
return ctx, stacktrace.Propagate(sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
"the sender is not EOA: address <%v>, codeHash <%s>", fromAddr, codeHash), "")
}
if err := evmkeeper.CheckSenderBalance(sdk.NewIntFromBigInt(acct.Balance), txData); err != nil {
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
acc := avd.ak.GetAccount(ctx, from)
if acc == nil {
acc = avd.ak.NewAccountWithAddress(ctx, from)
avd.ak.SetAccount(ctx, acc)
}
if err := evmkeeper.CheckSenderBalance(ctx, avd.bankKeeper, from, txData, evmDenom); err != nil {
return ctx, stacktrace.Propagate(err, "failed to check sender balance")
}
}
// recover the original gas meter
avd.evmKeeper.WithContext(ctx)
return next(ctx, tx, simulate)
}
// EthNonceVerificationDecorator checks that the account nonce from the transaction matches
// the sender account sequence.
type EthNonceVerificationDecorator struct {
ak evmtypes.AccountKeeper
}
// NewEthNonceVerificationDecorator creates a new EthNonceVerificationDecorator
func NewEthNonceVerificationDecorator(ak evmtypes.AccountKeeper) EthNonceVerificationDecorator {
return EthNonceVerificationDecorator{
ak: ak,
}
}
// AnteHandle validates that the transaction nonces are valid and equivalent to the sender accounts
// current nonce.
func (nvd EthNonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// no need to check the nonce on ReCheckTx
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction %d", i,
)
}
// sender address should be in the tx cache from the previous AnteHandle call
seq, err := nvd.ak.GetSequence(ctx, msgEthTx.GetFrom())
if err != nil {
return ctx, stacktrace.Propagate(err, "sequence not found for address %s", msgEthTx.From)
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
// if multiple transactions are submitted in succession with increasing nonces,
// all will be rejected except the first, since the first needs to be included in a block
// before the sequence increments
if txData.GetNonce() != seq {
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(
sdkerrors.ErrInvalidSequence,
"invalid nonce; got %d, expected %d", txData.GetNonce(), seq,
),
"",
)
}
}
return next(ctx, tx, simulate)
}
// EthGasConsumeDecorator validates enough intrinsic gas for the transaction and
// gas consumption.
type EthGasConsumeDecorator struct {
evmKeeper EVMKeeper
maxGasWanted uint64
ak evmtypes.AccountKeeper
bankKeeper evmtypes.BankKeeper
evmKeeper EVMKeeper
}
// NewEthGasConsumeDecorator creates a new EthGasConsumeDecorator
func NewEthGasConsumeDecorator(
evmKeeper EVMKeeper,
maxGasWanted uint64,
) EthGasConsumeDecorator {
func NewEthGasConsumeDecorator(ak evmtypes.AccountKeeper, bankKeeper evmtypes.BankKeeper, ek EVMKeeper) EthGasConsumeDecorator {
return EthGasConsumeDecorator{
evmKeeper,
maxGasWanted,
ak: ak,
bankKeeper: bankKeeper,
evmKeeper: ek,
}
}
@@ -157,13 +249,16 @@ func NewEthGasConsumeDecorator(
// of data supplied with the transaction.
//
// This AnteHandler decorator will fail if:
// - the transaction contains more than one message
// - the message is not a MsgEthereumTx
// - sender account cannot be found
// - transaction's gas limit is lower than the intrinsic gas
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
// - transaction or block gas meter runs out of gas
// - sets the gas meter limit
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// reset the refund gas value in the keeper for the current transaction
egcd.evmKeeper.ResetRefundTransient(ctx)
params := egcd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
@@ -171,44 +266,36 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
blockHeight := big.NewInt(ctx.BlockHeight())
homestead := ethCfg.IsHomestead(blockHeight)
istanbul := ethCfg.IsIstanbul(blockHeight)
london := ethCfg.IsLondon(blockHeight)
evmDenom := params.EvmDenom
gasWanted := uint64(0)
var events sdk.Events
for _, msg := range tx.GetMsgs() {
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction %d", i,
)
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
if ctx.IsCheckTx() {
// We can't trust the tx gas limit, because we'll refund the unused gas.
if txData.GetGas() > egcd.maxGasWanted {
gasWanted += egcd.maxGasWanted
} else {
gasWanted += txData.GetGas()
}
} else {
gasWanted += txData.GetGas()
}
fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
fees, err := evmkeeper.DeductTxCostsFromUserBalance(
ctx,
egcd.bankKeeper,
egcd.ak,
*msgEthTx,
txData,
evmDenom,
homestead,
istanbul,
london,
)
if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance")
return ctx, stacktrace.Propagate(err, "failed to deduct transaction costs from user balance")
}
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
@@ -228,12 +315,9 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
}
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
gasConsumed := ctx.GasMeter().GasConsumed()
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
// we know that we have enough gas on the pool to cover the intrinsic gas
// set up the updated context to the evm Keeper
egcd.evmKeeper.WithContext(ctx)
return next(ctx, tx, simulate)
}
@@ -253,64 +337,106 @@ func NewCanTransferDecorator(evmKeeper EVMKeeper) CanTransferDecorator {
// AnteHandle creates an EVM from the message and calls the BlockContext CanTransfer function to
// see if the address can execute the transaction.
func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
ctd.evmKeeper.WithContext(ctx)
params := ctd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(ctd.evmKeeper.ChainID())
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))
for _, msg := range tx.GetMsgs() {
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction %d", i,
)
}
baseFee := ctd.evmKeeper.BaseFee(ctx, ethCfg)
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
coreMsg, err := msgEthTx.AsMessage(signer)
if err != nil {
return ctx, sdkerrors.Wrapf(
return ctx, stacktrace.Propagate(
err,
"failed to create an ethereum core.Message from signer %T", signer,
)
}
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
cfg := &evmtypes.EVMConfig{
ChainConfig: ethCfg,
Params: params,
CoinBase: common.Address{},
BaseFee: baseFee,
}
stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB)
evm := ctd.evmKeeper.NewEVM(coreMsg, ethCfg, params, common.Address{}, nil)
// check that caller has enough balance to cover asset transfer for **topmost** call
// NOTE: here the gas consumed is from the context with the infinite gas meter
if coreMsg.Value().Sign() > 0 && !evm.Context.CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"failed to transfer %s from address %s using the EVM block context transfer function",
coreMsg.Value(),
coreMsg.From(),
if coreMsg.Value().Sign() > 0 && !evm.Context.CanTransfer(ctd.evmKeeper, coreMsg.From(), coreMsg.Value()) {
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "address %s", coreMsg.From()),
"failed to transfer %s using the EVM block context transfer function", coreMsg.Value(),
)
}
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
if baseFee == nil {
return ctx, sdkerrors.Wrap(
evmtypes.ErrInvalidBaseFee,
"base fee is supported but evm block context value is nil",
)
}
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee,
"max fee per gas less than block base fee (%s < %s)",
coreMsg.GasFeeCap(), baseFee,
)
}
}
}
ctd.evmKeeper.WithContext(ctx)
// set the original gas meter
return next(ctx, tx, simulate)
}
// AccessListDecorator prepare an access list for the sender if Yolov3/Berlin/EIPs 2929 and 2930 are
// applicable at the current block number.
type AccessListDecorator struct {
evmKeeper EVMKeeper
}
// NewAccessListDecorator creates a new AccessListDecorator.
func NewAccessListDecorator(evmKeeper EVMKeeper) AccessListDecorator {
return AccessListDecorator{
evmKeeper: evmKeeper,
}
}
// AnteHandle handles the preparatory steps for executing an EVM state transition with
// regards to both EIP-2929 and EIP-2930:
//
// - Add sender to access list (2929)
// - Add destination to access list (2929)
// - Add precompiles to access list (2929)
// - Add the contents of the optional tx access list (2930)
//
// The AnteHandler will only prepare the access list if Yolov3/Berlin/EIPs 2929 and 2930 are applicable at the current number.
func (ald AccessListDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
params := ald.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(ald.evmKeeper.ChainID())
rules := ethCfg.Rules(big.NewInt(ctx.BlockHeight()))
// we don't need to prepare the access list if the chain is not currently on the Berlin upgrade
if !rules.IsBerlin {
return next(ctx, tx, simulate)
}
// setup the keeper context before setting the access list
ald.evmKeeper.WithContext(ctx)
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction %d", i,
)
}
sender := common.BytesToAddress(msgEthTx.GetFrom())
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
ald.evmKeeper.PrepareAccessList(sender, txData.GetTo(), vm.ActivePrecompiles(rules), txData.GetAccessList())
}
// set the original gas meter
ald.evmKeeper.WithContext(ctx)
return next(ctx, tx, simulate)
}
@@ -330,56 +456,60 @@ func NewEthIncrementSenderSequenceDecorator(ak evmtypes.AccountKeeper) EthIncrem
// contract creation, the nonce will be incremented during the transaction execution and not within
// this AnteHandler decorator.
func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
for _, msg := range tx.GetMsgs() {
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}),
"failed to cast transaction %d", i,
)
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
return ctx, stacktrace.Propagate(err, "failed to unpack tx data")
}
// increase sequence of sender
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
if acc == nil {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrUnknownAddress,
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
)
}
nonce := acc.GetSequence()
// we merged the nonce verification to nonce increment, so when tx includes multiple messages
// with same sender, they'll be accepted.
if txData.GetNonce() != nonce {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInvalidSequence,
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
)
// NOTE: on contract creation, the nonce is incremented within the EVM Create function during tx execution
// and not previous to the state transition ¯\_(ツ)_/¯
if txData.GetTo() == nil {
// contract creation, don't increment sequence on AnteHandler but on tx execution
// continue to the next item
continue
}
if err := acc.SetSequence(nonce + 1); err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
}
// increment sequence of all signers
for _, addr := range msg.GetSigners() {
acc := issd.ak.GetAccount(ctx, addr)
issd.ak.SetAccount(ctx, acc)
if acc == nil {
return ctx, stacktrace.Propagate(
sdkerrors.Wrapf(
sdkerrors.ErrUnknownAddress,
"account %s (%s) is nil", common.BytesToAddress(addr.Bytes()), addr,
),
"signer account not found",
)
}
if err := acc.SetSequence(acc.GetSequence() + 1); err != nil {
return ctx, stacktrace.Propagate(err, "failed to set sequence to %d", acc.GetSequence()+1)
}
issd.ak.SetAccount(ctx, acc)
}
}
// set the original gas meter
return next(ctx, tx, simulate)
}
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
type EthValidateBasicDecorator struct {
evmKeeper EVMKeeper
}
type EthValidateBasicDecorator struct{}
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
return EthValidateBasicDecorator{
evmKeeper: ek,
}
func NewEthValidateBasicDecorator() EthValidateBasicDecorator {
return EthValidateBasicDecorator{}
}
// AnteHandle handles basic validation of tx
@@ -392,70 +522,7 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
err := tx.ValidateBasic()
// ErrNoSignatures is fine with eth tx
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
return ctx, sdkerrors.Wrap(err, "tx basic validation failed")
}
// For eth type cosmos tx, some fields should be veified as zero values,
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
if wrapperTx, ok := tx.(protoTxProvider); ok {
protoTx := wrapperTx.GetProtoTx()
body := protoTx.Body
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
}
if len(body.ExtensionOptions) != 1 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
}
txFee := sdk.Coins{}
txGasLimit := uint64(0)
for _, msg := range protoTx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
txGasLimit += msgEthTx.GetGas()
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
}
params := vbd.evmKeeper.GetParams(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.BaseFee(ctx, ethCfg)
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}
txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee())))
}
authInfo := protoTx.AuthInfo
if len(authInfo.SignerInfos) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
}
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
}
if !authInfo.Fee.Amount.IsEqual(txFee) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
}
if authInfo.Fee.GasLimit != txGasLimit {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
}
sigs := protoTx.Signatures
if len(sigs) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty")
}
return ctx, stacktrace.Propagate(err, "tx basic validation failed")
}
return next(ctx, tx, simulate)
@@ -463,14 +530,10 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
// by setting the gas meter to infinite
type EthSetupContextDecorator struct {
evmKeeper EVMKeeper
}
type EthSetupContextDecorator struct{}
func NewEthSetUpContextDecorator(evmKeeper EVMKeeper) EthSetupContextDecorator {
return EthSetupContextDecorator{
evmKeeper: evmKeeper,
}
func NewEthSetUpContextDecorator() EthSetupContextDecorator {
return EthSetupContextDecorator{}
}
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
@@ -481,54 +544,5 @@ func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
}
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
// Reset transient gas used to prepare the execution of current cosmos tx.
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
esc.evmKeeper.ResetTransientGasUsed(ctx)
return next(newCtx, tx, simulate)
}
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
// as the local validator's minimum gasFee (defined in validator config).
// If fee is too low, decorator returns error and tx is rejected from mempool.
// Note this only applies when ctx.CheckTx = true
// If fee is high enough or not CheckTx, then call next AnteHandler
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
type EthMempoolFeeDecorator struct {
evmKeeper EVMKeeper
}
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
return EthMempoolFeeDecorator{
evmKeeper: ek,
}
}
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator,
// if this is a CheckTx. This is only for local mempool purposes, and thus
// is only ran on check tx.
// It only do the check if london hardfork not enabled or feemarket not enabled, because in that case feemarket will take over the task.
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if ctx.IsCheckTx() && !simulate {
params := mfd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(mfd.evmKeeper.ChainID())
baseFee := mfd.evmKeeper.BaseFee(ctx, ethCfg)
if baseFee == nil {
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
evmDenom := params.EvmDenom
feeAmt := ethMsg.GetFee()
glDec := sdk.NewDec(int64(ethMsg.GetGas()))
requiredFee := ctx.MinGasPrices().AmountOf(evmDenom).Mul(glDec)
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeAmt, requiredFee)
}
}
}
}
return next(ctx, tx, simulate)
}
+120 -91
View File
@@ -6,11 +6,10 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/app/ante"
"github.com/tharsis/ethermint/server/config"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
@@ -22,7 +21,7 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
addr, privKey := tests.NewAddrKey()
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
signedTx.From = addr.Hex()
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
@@ -33,11 +32,11 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
reCheckTx bool
expPass bool
}{
{"ReCheckTx", &invalidTx{}, true, false},
{"ReCheckTx", nil, true, false},
{"invalid transaction type", &invalidTx{}, false, false},
{
"invalid sender",
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
false,
false,
},
@@ -64,11 +63,9 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
addr := tests.GenerateAddress()
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex()
var vmdb *statedb.StateDB
testCases := []struct {
name string
tx sdk.Tx
@@ -80,7 +77,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
{"invalid transaction type", &invalidTx{}, func() {}, true, false},
{
"sender not set to msg",
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
func() {},
true,
false,
@@ -90,7 +87,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
tx,
func() {
// set not as an EOA
vmdb.SetCode(addr, []byte("1"))
suite.app.EvmKeeper.SetCode(addr, []byte("1"))
},
true,
false,
@@ -100,7 +97,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
tx,
func() {
// reset back to EOA
vmdb.SetCode(addr, nil)
suite.app.EvmKeeper.SetCode(addr, nil)
},
true,
false,
@@ -109,7 +106,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
"success new account",
tx,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
},
true,
true,
@@ -121,7 +118,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
vmdb.AddBalance(addr, big.NewInt(1000000))
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
},
true,
true,
@@ -130,10 +127,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
for _, tc := range testCases {
suite.Run(tc.name, func() {
vmdb = suite.StateDB()
tc.malleate()
suite.Require().NoError(vmdb.Commit())
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(tc.checkTx), tc.tx, false, nextFn)
if tc.expPass {
@@ -146,12 +140,11 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
}
func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
suite.SetupTest()
dec := ante.NewEthIncrementSenderSequenceDecorator(suite.app.AccountKeeper)
dec := ante.NewEthNonceVerificationDecorator(suite.app.AccountKeeper)
addr := tests.GenerateAddress()
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex()
testCases := []struct {
@@ -161,7 +154,7 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
reCheckTx bool
expPass bool
}{
{"ReCheckTx", &invalidTx{}, func() {}, true, false},
{"ReCheckTx", nil, func() {}, true, true},
{"invalid transaction type", &invalidTx{}, func() {}, false, false},
{"sender account not found", tx, func() {}, false, false},
{
@@ -202,65 +195,69 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
}
func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
dec := ante.NewEthGasConsumeDecorator(suite.app.EvmKeeper, config.DefaultMaxTxGasWanted)
dec := ante.NewEthGasConsumeDecorator(
suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper,
)
addr := tests.GenerateAddress()
txGasLimit := uint64(1000)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), txGasLimit, big.NewInt(1), nil, nil, nil, nil)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex()
tx2GasLimit := uint64(1000000)
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, big.NewInt(1), nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000000, big.NewInt(1), nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2.From = addr.Hex()
var vmdb *statedb.StateDB
testCases := []struct {
name string
tx sdk.Tx
gasLimit uint64
malleate func()
expPass bool
expPanic bool
}{
{"invalid transaction type", &invalidTx{}, 0, func() {}, false, false},
{"invalid transaction type", &invalidTx{}, func() {}, false, false},
{
"sender not found",
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
0,
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
func() {},
false, false,
},
{
"gas limit too low",
tx,
0,
func() {},
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
false, false,
},
{
"not enough balance for fees",
tx2,
0,
func() {},
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
false, false,
},
{
"not enough tx gas",
tx2,
0,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
},
false, true,
},
{
"not enough block gas",
tx2,
0,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1))
},
@@ -269,9 +266,11 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
{
"success",
tx2,
config.DefaultMaxTxGasWanted, // it's capped
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(10000000000000000000))
},
@@ -281,9 +280,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
for _, tc := range testCases {
suite.Run(tc.name, func() {
vmdb = suite.StateDB()
tc.malleate()
suite.Require().NoError(vmdb.Commit())
if tc.expPanic {
suite.Require().Panics(func() {
@@ -292,14 +289,12 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
return
}
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, nextFn)
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
// TODO: needs to check the gasmeter limit issue
// suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
})
}
}
@@ -309,38 +304,14 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
addr, privKey := tests.NewAddrKey()
suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100))
tx := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
1000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
&ethtypes.AccessList{},
)
tx2 := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
1000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
&ethtypes.AccessList{},
)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, &ethtypes.AccessList{})
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, &ethtypes.AccessList{})
tx.From = addr.Hex()
err := tx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
var vmdb *statedb.StateDB
testCases := []struct {
name string
tx sdk.Tx
@@ -365,7 +336,7 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
vmdb.AddBalance(addr, big.NewInt(1000000))
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
},
true,
},
@@ -373,9 +344,7 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
for _, tc := range testCases {
suite.Run(tc.name, func() {
vmdb = suite.StateDB()
tc.malleate()
suite.Require().NoError(vmdb.Commit())
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
@@ -388,26 +357,82 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
}
}
func (suite AnteTestSuite) TestAccessListDecorator() {
dec := ante.NewAccessListDecorator(suite.app.EvmKeeper)
addr := tests.GenerateAddress()
al := &ethtypes.AccessList{
{Address: addr, StorageKeys: []common.Hash{{}}},
}
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, al)
tx.From = addr.Hex()
tx2.From = addr.Hex()
testCases := []struct {
name string
tx sdk.Tx
malleate func()
expPass bool
}{
{"invalid transaction type", &invalidTx{}, func() {}, false},
{
"success - no access list",
tx,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
},
true,
},
{
"success - with access list",
tx2,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(1000000))
},
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tc.malleate()
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
dec := ante.NewEthIncrementSenderSequenceDecorator(suite.app.AccountKeeper)
addr, privKey := tests.NewAddrKey()
contract := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
contract := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
contract.From = addr.Hex()
to := tests.GenerateAddress()
tx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 0, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
tx.From = addr.Hex()
err := contract.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
to := tests.GenerateAddress()
tx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 0, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx.From = addr.Hex()
err = tx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
tx2 := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx2.From = addr.Hex()
err = tx2.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
testCases := []struct {
name string
tx sdk.Tx
@@ -423,9 +448,9 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
},
{
"no signers",
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil),
func() {},
false, false,
false, true,
},
{
"account not set to store",
@@ -444,7 +469,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
},
{
"success - call",
tx2,
tx,
func() {},
true, false,
},
@@ -470,8 +495,12 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
txData, err := evmtypes.UnpackTxData(msg.Data)
suite.Require().NoError(err)
nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, addr)
suite.Require().Equal(txData.GetNonce()+1, nonce)
nonce := suite.app.EvmKeeper.GetNonce(addr)
if txData.GetTo() == nil {
suite.Require().Equal(txData.GetNonce(), nonce)
} else {
suite.Require().Equal(txData.GetNonce()+1, nonce)
}
} else {
suite.Require().Error(err)
}
@@ -480,8 +509,8 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
}
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
dec := ante.NewEthSetUpContextDecorator(suite.app.EvmKeeper)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
dec := ante.NewEthSetUpContextDecorator()
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
testCases := []struct {
name string
-103
View File
@@ -1,103 +0,0 @@
package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
ibcante "github.com/cosmos/ibc-go/v3/modules/core/ante"
ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
// channel keeper, EVM Keeper and Fee Market Keeper.
type HandlerOptions struct {
AccountKeeper evmtypes.AccountKeeper
BankKeeper evmtypes.BankKeeper
IBCKeeper *ibckeeper.Keeper
FeeMarketKeeper evmtypes.FeeMarketKeeper
EvmKeeper EVMKeeper
FeegrantKeeper ante.FeegrantKeeper
SignModeHandler authsigning.SignModeHandler
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
MaxTxGasWanted uint64
TxFeeChecker ante.TxFeeChecker
}
func (options HandlerOptions) Validate() error {
if options.AccountKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
}
if options.BankKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
}
if options.SignModeHandler == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}
if options.FeeMarketKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
}
if options.EvmKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
}
return nil
}
func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
NewEthValidateBasicDecorator(options.EvmKeeper),
NewEthSigVerificationDecorator(options.EvmKeeper),
NewEthAccountVerificationDecorator(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted),
NewCanTransferDecorator(options.EvmKeeper),
NewEthIncrementSenderSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator.
)
}
func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
// SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewAnteDecorator(options.IBCKeeper),
)
}
func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(),
// NOTE: extensions option decorator removed
// ante.NewRejectExtensionOptionsDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
// SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
// Note: signature verification uses EIP instead of the cosmos signature validator
NewEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewAnteDecorator(options.IBCKeeper),
)
}
-33
View File
@@ -1,33 +0,0 @@
package ante
import (
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
tx "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
// EVMKeeper defines the expected keeper interface used on the Eth AnteHandler
type EVMKeeper interface {
statedb.Keeper
ChainID() *big.Int
GetParams(ctx sdk.Context) evmtypes.Params
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) *vm.EVM
DeductTxCostsFromUserBalance(
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
) (sdk.Coins, error)
BaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
ResetTransientGasUsed(ctx sdk.Context)
}
type protoTxProvider interface {
GetProtoTx() *tx.Tx
}
-25
View File
@@ -1,25 +0,0 @@
package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
// RejectMessagesDecorator prevents invalid msg types from being executed
type RejectMessagesDecorator struct{}
// AnteHandle rejects messages that requires ethereum-specific authentication.
// For example `MsgEthereumTx` requires fee to be deducted in the antehandler in
// order to perform the refund.
func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
for _, msg := range tx.GetMsgs() {
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInvalidType,
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
)
}
}
return next(ctx, tx, simulate)
}
-46
View File
@@ -1,46 +0,0 @@
package ante_test
import (
"math/big"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
func (suite AnteTestSuite) TestSignatures() {
suite.enableFeemarket = false
suite.SetupTest() // reset
addr, privKey := tests.NewAddrKey()
to := tests.GenerateAddress()
acc := statedb.NewEmptyAccount()
acc.Nonce = 1
acc.Balance = big.NewInt(10000000000)
suite.app.EvmKeeper.SetAccount(suite.ctx, addr, *acc)
msgEthereumTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
msgEthereumTx.From = addr.Hex()
// CreateTestTx will sign the msgEthereumTx but not sign the cosmos tx since we have signCosmosTx as false
tx := suite.CreateTestTx(msgEthereumTx, privKey, 1, false)
sigs, err := tx.GetSignaturesV2()
suite.Require().NoError(err)
// signatures of cosmos tx should be empty
suite.Require().Equal(len(sigs), 0)
txData, err := evmtypes.UnpackTxData(msgEthereumTx.Data)
suite.Require().NoError(err)
msgV, msgR, msgS := txData.GetRawSignatureValues()
ethTx := msgEthereumTx.AsTransaction()
ethV, ethR, ethS := ethTx.RawSignatureValues()
// The signatures of MsgehtereumTx should be the same with the corresponding eth tx
suite.Require().Equal(msgV, ethV)
suite.Require().Equal(msgR, ethR)
suite.Require().Equal(msgS, ethS)
}
+12 -157
View File
@@ -1,19 +1,9 @@
package ante_test
import (
"math"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/tharsis/ethermint/ethereum/eip712"
"github.com/tharsis/ethermint/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/suite"
@@ -22,7 +12,6 @@ import (
"github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
@@ -34,9 +23,7 @@ import (
ante "github.com/tharsis/ethermint/app/ante"
"github.com/tharsis/ethermint/encoding"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
@@ -44,44 +31,16 @@ import (
type AnteTestSuite struct {
suite.Suite
ctx sdk.Context
app *app.EthermintApp
clientCtx client.Context
anteHandler sdk.AnteHandler
ethSigner ethtypes.Signer
enableFeemarket bool
enableLondonHF bool
}
func (suite *AnteTestSuite) StateDB() *statedb.StateDB {
return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes())))
ctx sdk.Context
app *app.EthermintApp
clientCtx client.Context
anteHandler sdk.AnteHandler
ethSigner ethtypes.Signer
}
func (suite *AnteTestSuite) SetupTest() {
checkTx := false
suite.app = app.Setup(suite.T(), checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
if suite.enableFeemarket {
// setup feemarketGenesis params
feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.Params.NoBaseFee = false
// Verify feeMarket genesis
err := feemarketGenesis.Validate()
suite.Require().NoError(err)
genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
}
if !suite.enableLondonHF {
evmGenesis := evmtypes.DefaultGenesisState()
maxInt := sdk.NewInt(math.MaxInt64)
evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.MergeForkBlock = &maxInt
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
}
return genesis
})
suite.app = app.Setup(checkTx)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 2, ChainID: "ethermint_9000-1", Time: time.Now().UTC()})
suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(sdk.NewDecCoin(evmtypes.DefaultEVMDenom, sdk.OneInt())))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1000000000000000000))
@@ -89,6 +48,7 @@ func (suite *AnteTestSuite) SetupTest() {
infCtx := suite.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
suite.app.AccountKeeper.SetParams(infCtx, authtypes.DefaultParams())
suite.app.EvmKeeper.SetParams(infCtx, evmtypes.DefaultParams())
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
// We're using TestMsg amino encoding in some tests, so register it here.
@@ -96,33 +56,17 @@ func (suite *AnteTestSuite) SetupTest() {
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
options := ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
EvmKeeper: suite.app.EvmKeeper,
FeegrantKeeper: suite.app.FeeGrantKeeper,
IBCKeeper: suite.app.IBCKeeper,
FeeMarketKeeper: suite.app.FeeMarketKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
}
suite.Require().NoError(options.Validate())
suite.anteHandler = ante.NewAnteHandler(options)
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper, suite.app.FeeGrantKeeper, suite.app.IBCKeeper.ChannelKeeper, encodingConfig.TxConfig.SignModeHandler())
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
}
func TestAnteTestSuite(t *testing.T) {
suite.Run(t, &AnteTestSuite{
enableLondonHF: true,
})
suite.Run(t, new(AnteTestSuite))
}
// CreateTestTx is a helper function to create a tx given multiple inputs.
func (suite *AnteTestSuite) CreateTestTx(
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
unsetExtensionOptions ...bool,
) authsigning.Tx {
return suite.CreateTestTxBuilder(msg, priv, accNum, signCosmosTx).GetTx()
}
@@ -130,22 +74,15 @@ func (suite *AnteTestSuite) CreateTestTx(
// CreateTestTxBuilder is a helper function to create a tx builder given multiple inputs.
func (suite *AnteTestSuite) CreateTestTxBuilder(
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
unsetExtensionOptions ...bool,
) client.TxBuilder {
var option *codectypes.Any
var err error
if len(unsetExtensionOptions) == 0 {
option, err = codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{})
suite.Require().NoError(err)
}
option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{})
suite.Require().NoError(err)
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
suite.Require().True(ok)
if len(unsetExtensionOptions) == 0 {
builder.SetExtensionOptions(option)
}
builder.SetExtensionOptions(option)
err = msg.Sign(suite.ethSigner, tests.NewSigner(priv))
suite.Require().NoError(err)
@@ -199,88 +136,6 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
return txBuilder
}
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build MsgSend
recipient := sdk.AccAddress(common.Address{}.Bytes())
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(1))))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
}
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build MsgSend
valEthAddr := tests.GenerateAddress()
valAddr := sdk.ValAddress(valEthAddr.Bytes())
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
}
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
) client.TxBuilder {
var err error
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, from)
suite.Require().NoError(err)
pc, err := types.ParseChainID(chainId)
suite.Require().NoError(err)
ethChainId := pc.Uint64()
// GenerateTypedData TypedData
var ethermintCodec codec.ProtoCodecMarshaler
fee := legacytx.NewStdFee(gas, gasAmount)
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil)
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
FeePayer: from,
})
suite.Require().NoError(err)
sigHash, err := eip712.ComputeTypedDataHash(typedData)
suite.Require().NoError(err)
// Sign typedData
keyringSigner := tests.NewSigner(priv)
signature, pubKey, err := keyringSigner.SignByAddress(from, sigHash)
suite.Require().NoError(err)
signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
// Add ExtensionOptionsWeb3Tx extension
var option *codectypes.Any
option, err = codectypes.NewAnyWithValue(&types.ExtensionOptionsWeb3Tx{
FeePayer: from.String(),
TypedDataChainID: ethChainId,
FeePayerSig: signature,
})
suite.Require().NoError(err)
suite.clientCtx.TxConfig.SignModeHandler()
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
suite.Require().True(ok)
builder.SetExtensionOptions(option)
builder.SetFeeAmount(gasAmount)
builder.SetGasLimit(gas)
sigsV2 := signing.SignatureV2{
PubKey: pubKey,
Data: &signing.SingleSignatureData{
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
},
Sequence: nonce,
}
err = builder.SetSignatures(sigsV2)
suite.Require().NoError(err)
err = builder.SetMsgs(msg)
suite.Require().NoError(err)
return builder
}
var _ sdk.Tx = &invalidTx{}
type invalidTx struct{}
+134 -251
View File
@@ -2,6 +2,7 @@ package app
import (
"encoding/json"
"io"
"net/http"
"os"
@@ -11,24 +12,22 @@ import (
"github.com/rakyll/statik/fs"
"github.com/spf13/cast"
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"
"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"
"github.com/cosmos/cosmos-sdk/db"
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/tharsis/ethermint/app/ante"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/v2alpha1"
"github.com/cosmos/cosmos-sdk/store/v2alpha1/multi"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
@@ -38,7 +37,6 @@ import (
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"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/cosmos/cosmos-sdk/x/authz"
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
@@ -64,10 +62,8 @@ import (
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/x/gov"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"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"
@@ -87,36 +83,22 @@ import (
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
"github.com/cosmos/ibc-go/v3/modules/apps/transfer"
ibctransferkeeper "github.com/cosmos/ibc-go/v3/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/v3/modules/core"
ibcclient "github.com/cosmos/ibc-go/v3/modules/core/02-client"
ibcclientclient "github.com/cosmos/ibc-go/v3/modules/core/02-client/client"
porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper"
"github.com/cosmos/ibc-go/modules/apps/transfer"
ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/modules/core"
ibcclient "github.com/cosmos/ibc-go/modules/core/02-client"
ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client"
porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper"
// unnamed import of statik for swagger UI support
_ "github.com/tharsis/ethermint/client/docs/statik"
"github.com/tharsis/ethermint/app/ante"
srvflags "github.com/tharsis/ethermint/server/flags"
ethermint "github.com/tharsis/ethermint/types"
"github.com/tharsis/ethermint/x/evm"
// evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
"github.com/tharsis/ethermint/x/feemarket"
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
// Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
"github.com/tharsis/ethermint/x/auction"
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
@@ -124,6 +106,15 @@ import (
"github.com/tharsis/ethermint/x/bond"
bondkeeper "github.com/tharsis/ethermint/x/bond/keeper"
bondtypes "github.com/tharsis/ethermint/x/bond/types"
"github.com/tharsis/ethermint/x/evm"
evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"github.com/tharsis/ethermint/x/feemarket"
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
"github.com/tharsis/ethermint/x/nameservice"
nameservicekeeper "github.com/tharsis/ethermint/x/nameservice/keeper"
nameservicetypes "github.com/tharsis/ethermint/x/nameservice/types"
@@ -135,10 +126,10 @@ func init() {
panic(err)
}
DefaultNodeHome = filepath.Join(userHomeDir, ".chibaclonkd")
DefaultNodeHome = filepath.Join(userHomeDir, ".ethermintd")
}
const appName = "chibaclonkd"
const appName = "ethermintd"
var (
// DefaultNodeHome default home directories for the application daemon
@@ -156,8 +147,8 @@ var (
mint.AppModuleBasic{},
distr.AppModuleBasic{},
gov.NewAppModuleBasic(
[]govclient.ProposalHandler{paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.LegacyProposalHandler, upgradeclient.LegacyCancelProposalHandler,
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler},
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler,
),
params.AppModuleBasic{},
crisis.AppModuleBasic{},
@@ -172,7 +163,7 @@ var (
// Ethermint modules
evm.AppModuleBasic{},
feemarket.AppModuleBasic{},
// Vulcanize chiba-clonk modules
// Vulcanize DXNS modules
auction.AppModuleBasic{},
bond.AppModuleBasic{},
nameservice.AppModuleBasic{},
@@ -180,14 +171,15 @@ var (
// module account permissions
maccPerms = map[string][]string{
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},
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
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},
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
auctiontypes.ModuleName: nil,
auctiontypes.AuctionBurnModuleAccountName: nil,
nameservicetypes.ModuleName: nil,
@@ -216,12 +208,13 @@ type EthermintApp struct {
cdc *codec.LegacyAmino
appCodec codec.Codec
interfaceRegistry types.InterfaceRegistry
invCheckPeriod uint
invCheckPeriod uint
// keys to access the substores
keys map[string]*storetypes.KVStoreKey
tkeys map[string]*storetypes.TransientStoreKey
memKeys map[string]*storetypes.MemoryStoreKey
keys map[string]*sdk.KVStoreKey
tkeys map[string]*sdk.TransientStoreKey
memKeys map[string]*sdk.MemoryStoreKey
// keepers
AccountKeeper authkeeper.AccountKeeper
@@ -249,7 +242,7 @@ type EthermintApp struct {
EvmKeeper *evmkeeper.Keeper
FeeMarketKeeper feemarketkeeper.Keeper
// chiba-clonk keepers
// DXNS keepers
AuctionKeeper auctionkeeper.Keeper
BondKeeper bondkeeper.Keeper
NameServiceKeeper nameservicekeeper.Keeper
@@ -268,7 +261,7 @@ type EthermintApp struct {
// NewEthermintApp returns a reference to a new initialized Ethermint application.
func NewEthermintApp(
logger log.Logger,
db db.DBConnection,
db dbm.DB,
traceStore io.Writer,
loadLatest bool,
skipUpgradeHeights map[int64]bool,
@@ -276,67 +269,12 @@ func NewEthermintApp(
invCheckPeriod uint,
encodingConfig simappparams.EncodingConfig,
appOpts servertypes.AppOptions,
baseAppOptions ...baseapp.AppOption,
baseAppOptions ...func(*baseapp.BaseApp),
) *EthermintApp {
appCodec := encodingConfig.Codec
appCodec := encodingConfig.Marshaler
cdc := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
keys := sdk.NewKVStoreKeys(
// SDK keys
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey,
evidencetypes.StoreKey, capabilitytypes.StoreKey,
authzkeeper.StoreKey,
// ibc keys
ibchost.StoreKey, ibctransfertypes.StoreKey,
// ethermint keys
evmtypes.StoreKey, feemarkettypes.StoreKey,
// chiba-clonk keys
auctiontypes.StoreKey,
bondtypes.StoreKey,
nameservicetypes.StoreKey,
)
// Add the EVM transient store key
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
// initialize stores
setNamespaces := func(config *multi.StoreParams, ver uint64) error {
for _, key := range keys {
typ, err := storetypes.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
for _, key := range memKeys {
typ, err := storetypes.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
for _, key := range tkeys {
typ, err := storetypes.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
return nil
}
baseAppOptions = append(baseAppOptions, baseapp.StoreOption(setNamespaces))
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
bApp := baseapp.NewBaseApp(
appName,
@@ -347,15 +285,28 @@ func NewEthermintApp(
)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
evmtypes.RegisterInterfaces(interfaceRegistry)
bApp.SetInterfaceRegistry(interfaceRegistry)
// configure state listening capabilities using AppOptions
// we are doing nothing with the returned streamingServices and waitGroup in this case
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, keys); err != nil {
tmos.Exit(err.Error())
}
keys := sdk.NewKVStoreKeys(
// SDK keys
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey,
evidencetypes.StoreKey, capabilitytypes.StoreKey,
feegrant.StoreKey, authzkeeper.StoreKey,
// ibc keys
ibchost.StoreKey, ibctransfertypes.StoreKey,
// ethermint keys
evmtypes.StoreKey, feemarkettypes.StoreKey,
// dxns keys
auctiontypes.StoreKey,
bondtypes.StoreKey,
nameservicetypes.StoreKey,
)
// Add the EVM transient store key
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
app := &EthermintApp{
BaseApp: bApp,
@@ -371,7 +322,7 @@ func NewEthermintApp(
// init params keeper and subspaces
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(paramstypes.ConsensusParamsKeyTable()))
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])
@@ -385,7 +336,7 @@ func NewEthermintApp(
// use custom Ethermint account for contracts
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms, sdk.Bech32MainPrefix,
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
)
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
@@ -399,7 +350,7 @@ func NewEthermintApp(
)
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, authtypes.FeeCollectorName,
&stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
)
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
@@ -408,7 +359,7 @@ func NewEthermintApp(
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
)
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp)
// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
@@ -416,16 +367,23 @@ func NewEthermintApp(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter())
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
// Create Ethermint keepers
app.EvmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
app.AccountKeeper, app.BankKeeper, app.StakingKeeper,
tracer, bApp.Trace(), // debug EVM based on Baseapp options
)
app.FeeMarketKeeper = feemarketkeeper.NewKeeper(
appCodec, keys[feemarkettypes.StoreKey], app.GetSubspace(feemarkettypes.ModuleName),
)
// Create Vulcanize chiba-clonk keepers
// Create Vulcanize dxns keepers
app.AuctionKeeper = auctionkeeper.NewKeeper(
app.AccountKeeper, app.BankKeeper, keys[auctiontypes.StoreKey],
appCodec, app.GetSubspace(auctiontypes.ModuleName),
@@ -446,34 +404,22 @@ func NewEthermintApp(
keys[nameservicetypes.StoreKey], app.GetSubspace(nameservicetypes.ModuleName),
)
app.EvmKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.FeeMarketKeeper,
tracer,
)
// Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)
// register the proposal types
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
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.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter, app.MsgServiceRouter(), govConfig,
&stakingKeeper, govRouter,
)
app.GovKeeper = *govKeeper.SetHooks(
@@ -485,15 +431,14 @@ func NewEthermintApp(
// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
)
transferModule := transfer.NewAppModule(app.TransferKeeper)
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
//Create static IBC router, add transfer route, then set and seal it
// Create static IBC router, add transfer route, then set and seal it
ibcRouter := porttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferIBCModule)
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule)
app.IBCKeeper.SetRouter(ibcRouter)
// create evidence keeper with router
@@ -523,7 +468,7 @@ func NewEthermintApp(
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, nil),
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),
@@ -532,13 +477,14 @@ func NewEthermintApp(
params.NewAppModule(app.ParamsKeeper),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
// ibc modules
ibc.NewAppModule(app.IBCKeeper),
transferModule,
// Ethermint app modules
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper),
feemarket.NewAppModule(app.FeeMarketKeeper),
// chiba-clonk modules
// DXNs modules
auction.NewAppModule(appCodec, app.AuctionKeeper),
bond.NewAppModule(appCodec, app.BondKeeper),
nameservice.NewAppModule(app.NameServiceKeeper),
@@ -553,58 +499,17 @@ func NewEthermintApp(
app.mm.SetOrderBeginBlockers(
upgradetypes.ModuleName,
capabilitytypes.ModuleName,
feemarkettypes.ModuleName,
evmtypes.ModuleName,
minttypes.ModuleName,
distrtypes.ModuleName,
slashingtypes.ModuleName,
evidencetypes.ModuleName,
stakingtypes.ModuleName,
ibchost.ModuleName,
// no-op modules
ibctransfertypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
govtypes.ModuleName,
crisistypes.ModuleName,
genutiltypes.ModuleName,
authz.ModuleName,
feegrant.ModuleName,
paramstypes.ModuleName,
vestingtypes.ModuleName,
// chiba-clonk modules
auctiontypes.ModuleName,
bondtypes.ModuleName,
nameservicetypes.ModuleName,
minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName,
)
// NOTE: fee market module must go last in order to retrieve the block gas used.
app.mm.SetOrderEndBlockers(
crisistypes.ModuleName,
govtypes.ModuleName,
stakingtypes.ModuleName,
evmtypes.ModuleName,
feemarkettypes.ModuleName,
// no-op modules
ibchost.ModuleName,
ibctransfertypes.ModuleName,
capabilitytypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
distrtypes.ModuleName,
slashingtypes.ModuleName,
minttypes.ModuleName,
genutiltypes.ModuleName,
evidencetypes.ModuleName,
authz.ModuleName,
feegrant.ModuleName,
paramstypes.ModuleName,
upgradetypes.ModuleName,
vestingtypes.ModuleName,
// chiba-clonk modules
auctiontypes.ModuleName,
bondtypes.ModuleName,
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
evmtypes.ModuleName, feemarkettypes.ModuleName,
nameservicetypes.ModuleName,
auctiontypes.ModuleName,
)
// NOTE: The genutils module must occur after staking so that pools are
@@ -614,27 +519,13 @@ func NewEthermintApp(
// can do so safely.
app.mm.SetOrderInitGenesis(
// 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,
authz.ModuleName,
feegrant.ModuleName,
paramstypes.ModuleName,
upgradetypes.ModuleName,
vestingtypes.ModuleName,
capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName,
slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName,
ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName,
authz.ModuleName, feegrant.ModuleName,
// Ethermint modules
evmtypes.ModuleName,
feemarkettypes.ModuleName,
// chiba-clonk modules
evmtypes.ModuleName, feemarkettypes.ModuleName,
// DXNS modules
auctiontypes.ModuleName,
bondtypes.ModuleName,
nameservicetypes.ModuleName,
@@ -660,7 +551,7 @@ func NewEthermintApp(
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, nil),
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),
@@ -670,38 +561,35 @@ func NewEthermintApp(
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
ibc.NewAppModule(app.IBCKeeper),
transferModule,
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper),
feemarket.NewAppModule(app.FeeMarketKeeper),
)
app.sm.RegisterStoreDecoders()
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)
// initialize BaseApp
app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker)
// use Ethermint's custom AnteHandler
app.SetAnteHandler(
ante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, app.EvmKeeper, app.FeeGrantKeeper, app.IBCKeeper.ChannelKeeper,
encodingConfig.TxConfig.SignModeHandler(),
),
)
maxGasWanted := cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted))
options := ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
EvmKeeper: app.EvmKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
IBCKeeper: app.IBCKeeper,
FeeMarketKeeper: app.FeeMarketKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
MaxTxGasWanted: maxGasWanted,
}
if err := options.Validate(); err != nil {
panic(err)
}
app.SetAnteHandler(ante.NewAnteHandler(options))
app.SetEndBlocker(app.EndBlocker)
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
tmos.Exit(err.Error())
}
}
app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
@@ -733,8 +621,7 @@ func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain)
// LoadHeight loads state at a particular height
func (app *EthermintApp) LoadHeight(height int64) error {
// return app.LoadVersion(height)
return nil
return app.LoadVersion(height)
}
// ModuleAccountAddrs returns all the app's module account addresses.
@@ -782,21 +669,21 @@ func (app *EthermintApp) InterfaceRegistry() types.InterfaceRegistry {
// GetKey returns the KVStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *EthermintApp) GetKey(storeKey string) *storetypes.KVStoreKey {
func (app *EthermintApp) GetKey(storeKey string) *sdk.KVStoreKey {
return app.keys[storeKey]
}
// GetTKey returns the TransientStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *EthermintApp) GetTKey(storeKey string) *storetypes.TransientStoreKey {
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) *storetypes.MemoryStoreKey {
func (app *EthermintApp) GetMemKey(storeKey string) *sdk.MemoryStoreKey {
return app.memKeys[storeKey]
}
@@ -817,16 +704,17 @@ func (app *EthermintApp) SimulationManager() *module.SimulationManager {
// API server.
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
clientCtx := apiSvr.ClientCtx
// NOTE: in v0.46 legacy routes are removed
// rpc.RegisterRoutes(clientCtx, apiSvr.Router)
// evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
rpc.RegisterRoutes(clientCtx, apiSvr.Router)
evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
// Register new tx routes from grpc-gateway.
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// Register new tendermint queries routes from grpc-gateway.
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// Register grpc-gateway routes for all modules.
// Register legacy and grpc-gateway routes for all modules.
ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router)
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// register swagger API from root so that other applications can override easily
@@ -840,12 +728,7 @@ func (app *EthermintApp) RegisterTxService(clientCtx client.Context) {
}
func (app *EthermintApp) RegisterTendermintService(clientCtx client.Context) {
tmservice.RegisterTendermintService(
clientCtx,
app.BaseApp.GRPCQueryRouter(),
app.interfaceRegistry,
app.Query,
)
tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry)
}
// RegisterSwaggerAPI registers swagger route with API Server
@@ -871,8 +754,7 @@ func GetMaccPerms() map[string][]string {
// initParamsKeeper init params keeper and its subspaces
func initParamsKeeper(
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey,
) paramskeeper.Keeper {
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper {
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
// SDK subspaces
@@ -882,16 +764,17 @@ func initParamsKeeper(
paramsKeeper.Subspace(minttypes.ModuleName)
paramsKeeper.Subspace(distrtypes.ModuleName)
paramsKeeper.Subspace(slashingtypes.ModuleName)
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable())
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)
paramsKeeper.Subspace(feemarkettypes.ModuleName)
// chiba-clonk subspaces
// dxns subspaces
paramsKeeper.Subspace(auctiontypes.ModuleName)
paramsKeeper.Subspace(bondtypes.ModuleName)
paramsKeeper.Subspace(nameservicetypes.ModuleName)
return paramsKeeper
}
+21 -25
View File
@@ -1,45 +1,41 @@
package app
import (
"encoding/json"
"os"
"testing"
memdb "github.com/cosmos/cosmos-sdk/db/memdb"
"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/tharsis/ethermint/encoding"
)
func TestEthermintAppExport(t *testing.T) {
encCfg := encoding.MakeConfig(ModuleBasics)
db := memdb.NewDB()
logger, _ := log.NewDefaultLogger("plain", "info", false)
app := NewTestAppWithCustomOptions(t, false, SetupOptions{
Logger: logger,
DB: db,
InvCheckPeriod: 0,
EncConfig: encCfg,
HomePath: DefaultNodeHome,
SkipUpgradeHeights: map[int64]bool{},
AppOpts: EmptyAppOptions{},
})
db := dbm.NewMemDB()
app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
for acc := range allowedReceivingModAcc {
// check module account is not blocked in bank
require.False(
t,
app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)),
"ensure that blocked addresses %s are properly set in bank keeper",
)
}
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)
// Initialize the chain
app.InitChain(
abci.RequestInitChain{
ChainId: "ethermint_9000-1",
Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes,
},
)
app.Commit()
logger2, _ := log.NewDefaultLogger("plain", "info", false)
// Making a new app object with the db, so that initchain hasn't been called
app2 := NewEthermintApp(logger2, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
require.NoError(t, app2.Init())
_, err := app2.ExportAppStateAndValidators(false, []string{})
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
_, err = app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}
+6 -6
View File
@@ -2,21 +2,21 @@ package app
import (
"encoding/json"
"io"
"testing"
"github.com/cosmos/cosmos-sdk/db/memdb"
"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/tharsis/ethermint/encoding"
)
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
db := memdb.NewDB()
logger, _ := log.NewDefaultLogger("plain", "info", false)
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
db := dbm.NewMemDB()
app := NewEthermintApp(log.NewTMLogger(io.Discard), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
genesisState := NewDefaultGenesisState(app.appCodec)
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
if err != nil {
b.Fatal(err)
@@ -36,7 +36,7 @@ func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
// Making a new app object with the db, so that initchain hasn't been called
app2 := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(io.Discard)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
b.Fatal(err)
}
+8 -6
View File
@@ -6,18 +6,20 @@ import (
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"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/tharsis/ethermint/encoding"
)
// NewDefaultGenesisState generates the default state for the application.
func NewDefaultGenesisState(cdc codec.JSONCodec) simapp.GenesisState {
return ModuleBasics.DefaultGenesis(cdc)
func NewDefaultGenesisState() simapp.GenesisState {
encCfg := encoding.MakeConfig(ModuleBasics)
return ModuleBasics.DefaultGenesis(encCfg.Marshaler)
}
// ExportAppStateAndValidators exports the state of the application for a genesis
@@ -168,6 +170,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAd
// update bond intra-tx counters.
store := ctx.KVStore(app.keys[stakingtypes.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
counter := int16(0)
for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key()))
@@ -182,11 +185,10 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAd
}
app.StakingKeeper.SetValidator(ctx, validator)
counter++
}
if err := iter.Close(); err != nil {
return err
}
iter.Close()
if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil {
return err
+338 -349
View File
@@ -1,351 +1,340 @@
package app
// TODO: COsmos SDK fix for the simulator issue for custom keys
import (
"encoding/json"
"fmt"
"math/rand"
"os"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/simapp/params"
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"
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"
"github.com/cosmos/cosmos-sdk/db/memdb"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
evmenc "github.com/tharsis/ethermint/encoding"
)
// MakeEncodingConfig creates the EncodingConfig
func MakeEncodingConfig() params.EncodingConfig {
return evmenc.MakeConfig(ModuleBasics)
}
func init() {
simapp.GetSimulatorFlags()
}
const SimAppChainID = "simulation_777-1"
type storeKeysPrefixes struct {
A storetypes.StoreKey
B storetypes.StoreKey
Prefixes [][]byte
}
// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
// an IAVLStore for faster simulation speed.
var fauxMerkleModeOpt = baseapp.AppOptionFunc(func(bapp *baseapp.BaseApp) {
bapp.SetFauxMerkleMode()
})
// interBlockCacheOpt returns a BaseApp option function that sets the persistent
// inter-block write-through cache.
// TODO: implement this cache as enhancement to v2 multistore
func interBlockCacheOpt() baseapp.AppOptionFunc {
return func(*baseapp.BaseApp) {}
}
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 = 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 := memdb.NewDB()
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,
)
}
}
}
}
// 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,
// )
// }
// }
// }
//}
+14 -223
View File
@@ -1,50 +1,25 @@
package app
import (
"context"
"encoding/json"
"testing"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
"time"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/mock"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/stretchr/testify/require"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/encoding"
ethermint "github.com/tharsis/ethermint/types"
"github.com/cosmos/cosmos-sdk/db/memdb"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
"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"
)
// GenesisState of the blockchain is represented here as a map of raw json
// messages key'd by a identifier string.
// The identifier is used to determine which module genesis information belongs
// to so it may be appropriately routed during init chain.
// Within this application default genesis information is retrieved from
// the ModuleBasicManager which populates json from each BasicModule
// object provided to it during init.
// DefaultConsensusParams defines the default Tendermint consensus params used in
// EthermintApp testing.
var DefaultConsensusParams = &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
var DefaultConsensusParams = &abci.ConsensusParams{
Block: &abci.BlockParams{
MaxBytes: 200000,
MaxGas: -1, // no limit
},
@@ -60,50 +35,17 @@ var DefaultConsensusParams = &tmproto.ConsensusParams{
},
}
// SetupOptions defines arguments that are passed into `Simapp` constructor.
type SetupOptions struct {
Logger log.Logger
DB *memdb.MemDB
InvCheckPeriod uint
HomePath string
SkipUpgradeHeights map[int64]bool
EncConfig params.EncodingConfig
AppOpts types.AppOptions
}
func NewTestAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions) *EthermintApp {
t.Helper()
privVal := mock.NewPV()
pubKey, err := privVal.GetPubKey(context.TODO())
require.NoError(t, err)
// create validator set with single validator
validator := tmtypes.NewValidator(pubKey, 1)
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
// generate genesis account
priv, err := ethsecp256k1.GenerateKey()
require.NoError(t, err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
acc := &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
}
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}
app := NewEthermintApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts)
genesisState := NewDefaultGenesisState(app.appCodec)
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
// 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{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
if !isCheckTx {
// init chain must be called to stop deliverState from being nil
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)
genesisState := NewDefaultGenesisState()
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
if err != nil {
panic(err)
}
// Initialize the chain
app.InitChain(
@@ -119,149 +61,6 @@ func NewTestAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOpti
return app
}
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
func Setup(t *testing.T, isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) *EthermintApp {
t.Helper()
privVal := mock.NewPV()
pubKey, err := privVal.GetPubKey(context.TODO())
require.NoError(t, err)
// create validator set with single validator
validator := tmtypes.NewValidator(pubKey, 1)
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
priv, err := ethsecp256k1.GenerateKey()
require.NoError(t, err)
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
acc := &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
}
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}
app := SetupWithGenesisValSet(t, valSet, patchGenesis, []authtypes.GenesisAccount{acc}, balance)
return app
}
func setup(withGenesis bool, invCheckPeriod uint, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) (*EthermintApp, simapp.GenesisState) {
encCdc := encoding.MakeConfig(ModuleBasics)
app := NewEthermintApp(log.NewNopLogger(), memdb.NewDB(), nil, true, map[int64]bool{}, DefaultNodeHome, invCheckPeriod, encCdc, EmptyAppOptions{})
if withGenesis {
genesisState := NewDefaultGenesisState(encCdc.Codec)
if patchGenesis != nil {
genesisState = patchGenesis(app, genesisState)
}
return app, genesisState
}
return app, simapp.GenesisState{}
}
// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts
// that also act as delegators. For simplicity, each validator is bonded with a delegation
// of one consensus engine unit in the default token of the simapp from first genesis
// account. A Nop logger is set in SimApp.
func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *EthermintApp {
t.Helper()
app, genesisState := setup(true, 5, patchGenesis)
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, genAccs, balances...)
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)
// init chain will set the validator set and initialize the genesis accounts
app.InitChain(
abci.RequestInitChain{
ChainId: "ethermint_9000-1",
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)
// commit genesis changes
// app.Commit()
// app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
// ChainID: "ethermint_9000-1",
// Height: app.LastBlockHeight() + 1,
// AppHash: app.LastCommitID().Hash,
// ValidatorsHash: valSet.Hash(),
// NextValidatorsHash: valSet.Hash(),
// }})
return app
}
func genesisStateWithValSet(t *testing.T, app *EthermintApp, genesisState simapp.GenesisState,
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) simapp.GenesisState {
// set genesis accounts
authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
bondAmt := sdk.DefaultPowerReduction
for _, val := range valSet.Validators {
pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
require.NoError(t, err)
pkAny, err := codectypes.NewAnyWithValue(pk)
require.NoError(t, err)
validator := stakingtypes.Validator{
OperatorAddress: sdk.ValAddress(val.Address).String(),
ConsensusPubkey: pkAny,
Jailed: false,
Status: stakingtypes.Bonded,
Tokens: bondAmt,
DelegatorShares: sdk.OneDec(),
Description: stakingtypes.Description{},
UnbondingHeight: int64(0),
UnbondingTime: time.Unix(0, 0).UTC(),
Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
MinSelfDelegation: sdk.ZeroInt(),
}
validators = append(validators, validator)
delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec()))
}
// set validators and delegations
stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations)
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
totalSupply := sdk.NewCoins()
for _, b := range balances {
// add genesis acc tokens to total supply
totalSupply = totalSupply.Add(b.Coins...)
}
for range delegations {
// add delegated tokens to total supply
totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))
}
// add bonded amount to bonded pool module account
balances = append(balances, banktypes.Balance{
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)},
})
// update total supply
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{})
genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
return genesisState
}
// CreateRandomAccounts will generate random accounts
func CreateRandomAccounts(accNum int) []sdk.AccAddress {
// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
@@ -273,11 +72,3 @@ func CreateRandomAccounts(accNum int) []sdk.AccAddress {
return testAddrs
}
// EmptyAppOptions is a stub implementing AppOptions
type EmptyAppOptions struct{}
// Get implements AppOptions
func (ao EmptyAppOptions) Get(o string) interface{} {
return nil
}
View File
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func TestInitConfigNonNotExistError(t *testing.T) {
tempDir := t.TempDir()
subDir := filepath.Join(tempDir, "nonPerms")
if err := os.Mkdir(subDir, 0o600); err != nil {
if err := os.Mkdir(subDir, 0600); err != nil {
t.Fatalf("Failed to create sub directory: %v", err)
}
cmd := &cobra.Command{}
File diff suppressed because one or more lines are too long
+221 -488
View File
@@ -1495,6 +1495,11 @@ paths:
title: >-
Berlin switch block (nil = no fork, 0 = already on
berlin)
catalyst_block:
type: string
title: >-
Catalyst switch block (nil = no fork, 0 = already on
catalyst)
london_block:
type: string
title: >-
@@ -1924,360 +1929,6 @@ paths:
type: string
tags:
- Query
/ethermint/evm/v1/trace_block:
get:
summary: >-
TraceBlock implements the `debug_traceBlockByNumber` and
`debug_traceBlockByHash` rpc api
operationId: TraceBlock
responses:
'200':
description: A successful response.
schema:
type: object
properties:
data:
type: string
format: byte
title: QueryTraceBlockResponse defines TraceBlock response
default:
description: An unexpected error response.
schema:
type: object
properties:
error:
type: string
code:
type: integer
format: int32
message:
type: string
details:
type: array
items:
type: object
properties:
type_url:
type: string
description: >-
A URL/resource name that uniquely identifies the type of
the serialized
protocol buffer message. This string must contain at
least
one "/" character. The last segment of the URL's path
must represent
the fully qualified name of the type (as in
`path/google.protobuf.Duration`). The name should be in
a canonical form
(e.g., leading "." is not accepted).
In practice, teams usually precompile into the binary
all types that they
expect it to use in the context of Any. However, for
URLs which use the
scheme `http`, `https`, or no scheme, one can optionally
set up a type
server that maps type URLs to message definitions as
follows:
* If no scheme is provided, `https` is assumed.
* An HTTP GET on the URL must yield a
[google.protobuf.Type][]
value in binary format, or produce an error.
* Applications are allowed to cache lookup results based
on the
URL, or have them precompiled into a binary to avoid any
lookup. Therefore, binary compatibility needs to be preserved
on changes to types. (Use versioned type names to manage
breaking changes.)
Note: this functionality is not currently available in
the official
protobuf release, and it is not used for type URLs
beginning with
type.googleapis.com.
Schemes other than `http`, `https` (or the empty scheme)
might be
used with implementation specific semantics.
value:
type: string
format: byte
description: >-
Must be a valid serialized protocol buffer of the above
specified type.
description: >-
`Any` contains an arbitrary serialized protocol buffer
message along with a
URL that describes the type of the serialized message.
Protobuf library provides support to pack/unpack Any values
in the form
of utility functions or additional generated methods of the
Any type.
Example 1: Pack and unpack a message in C++.
Foo foo = ...;
Any any;
any.PackFrom(foo);
...
if (any.UnpackTo(&foo)) {
...
}
Example 2: Pack and unpack a message in Java.
Foo foo = ...;
Any any = Any.pack(foo);
...
if (any.is(Foo.class)) {
foo = any.unpack(Foo.class);
}
Example 3: Pack and unpack a message in Python.
foo = Foo(...)
any = Any()
any.Pack(foo)
...
if any.Is(Foo.DESCRIPTOR):
any.Unpack(foo)
...
Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo)
...
foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil {
...
}
The pack methods provided by protobuf library will by
default use
'type.googleapis.com/full.type.name' as the type URL and the
unpack
methods only use the fully qualified type name after the
last '/'
in the type URL, for example "foo.bar.com/x/y.z" will yield
type
name "y.z".
JSON
====
The JSON representation of an `Any` value uses the regular
representation of the deserialized, embedded message, with
an
additional field `@type` which contains the type URL.
Example:
package google.profile;
message Person {
string first_name = 1;
string last_name = 2;
}
{
"@type": "type.googleapis.com/google.profile.Person",
"firstName": <string>,
"lastName": <string>
}
If the embedded message type is well-known and has a custom
JSON
representation, that representation will be embedded adding
a field
`value` which holds the custom JSON in addition to the
`@type`
field. Example (for message [google.protobuf.Duration][]):
{
"@type": "type.googleapis.com/google.protobuf.Duration",
"value": "1.212s"
}
parameters:
- name: trace_config.tracer
description: custom javascript tracer.
in: query
required: false
type: string
- name: trace_config.timeout
description: >-
overrides the default timeout of 5 seconds for JavaScript-based
tracing
calls.
in: query
required: false
type: string
- name: trace_config.reexec
description: number of blocks the tracer is willing to go back.
in: query
required: false
type: string
format: uint64
- name: trace_config.disable_stack
description: disable stack capture.
in: query
required: false
type: boolean
- name: trace_config.disable_storage
description: disable storage capture.
in: query
required: false
type: boolean
- name: trace_config.debug
description: print output during capture end.
in: query
required: false
type: boolean
- name: trace_config.limit
description: 'maximum length of output, but zero means unlimited.'
in: query
required: false
type: integer
format: int32
- name: trace_config.overrides.homestead_block
description: 'Homestead switch block (nil no fork, 0 = already homestead).'
in: query
required: false
type: string
- name: trace_config.overrides.dao_fork_block
description: TheDAO hard-fork switch block (nil no fork).
in: query
required: false
type: string
- name: trace_config.overrides.dao_fork_support
description: Whether the nodes supports or opposes the DAO hard-fork.
in: query
required: false
type: boolean
- name: trace_config.overrides.eip150_block
description: >-
EIP150 implements the Gas price changes
(https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil
no fork).
in: query
required: false
type: string
- name: trace_config.overrides.eip150_hash
description: >-
EIP150 HF hash (needed for header only clients as only gas pricing
changed).
in: query
required: false
type: string
- name: trace_config.overrides.eip155_block
description: EIP155Block HF block.
in: query
required: false
type: string
- name: trace_config.overrides.eip158_block
description: EIP158 HF block.
in: query
required: false
type: string
- name: trace_config.overrides.byzantium_block
description: 'Byzantium switch block (nil no fork, 0 = already on byzantium).'
in: query
required: false
type: string
- name: trace_config.overrides.constantinople_block
description: 'Constantinople switch block (nil no fork, 0 = already activated).'
in: query
required: false
type: string
- name: trace_config.overrides.petersburg_block
description: Petersburg switch block (nil same as Constantinople).
in: query
required: false
type: string
- name: trace_config.overrides.istanbul_block
description: 'Istanbul switch block (nil no fork, 0 = already on istanbul).'
in: query
required: false
type: string
- name: trace_config.overrides.muir_glacier_block
description: >-
Eip-2384 (bomb delay) switch block (nil no fork, 0 = already
activated).
in: query
required: false
type: string
- name: trace_config.overrides.berlin_block
description: 'Berlin switch block (nil = no fork, 0 = already on berlin).'
in: query
required: false
type: string
- name: trace_config.overrides.london_block
description: 'London switch block (nil = no fork, 0 = already on london).'
in: query
required: false
type: string
- name: trace_config.enable_memory
description: enable memory capture.
in: query
required: false
type: boolean
- name: trace_config.enable_return_data
description: enable return data capture.
in: query
required: false
type: boolean
- name: block_number
description: block number.
in: query
required: false
type: string
format: int64
- name: block_hash
description: block hex hash.
in: query
required: false
type: string
- name: block_time
description: block time.
in: query
required: false
type: string
format: date-time
tags:
- Query
/ethermint/evm/v1/trace_tx:
get:
summary: TraceTx implements the `debug_traceTransaction` rpc api
@@ -2566,8 +2217,8 @@ paths:
description: transaction index.
in: query
required: false
type: string
format: uint64
type: integer
format: int64
- name: trace_config.tracer
description: custom javascript tracer.
in: query
@@ -2576,9 +2227,7 @@ paths:
- name: trace_config.timeout
description: >-
overrides the default timeout of 5 seconds for JavaScript-based
tracing
calls.
tracing calls.
in: query
required: false
type: string
@@ -2588,43 +2237,53 @@ paths:
required: false
type: string
format: uint64
- name: trace_config.disable_stack
- name: trace_config.log_config.disable_memory
description: disable memory capture.
in: query
required: false
type: boolean
- name: trace_config.log_config.disable_stack
description: disable stack capture.
in: query
required: false
type: boolean
- name: trace_config.disable_storage
- name: trace_config.log_config.disable_storage
description: disable storage capture.
in: query
required: false
type: boolean
- name: trace_config.debug
- name: trace_config.log_config.disable_return_data
description: disable return data capture.
in: query
required: false
type: boolean
- name: trace_config.log_config.debug
description: print output during capture end.
in: query
required: false
type: boolean
- name: trace_config.limit
- name: trace_config.log_config.limit
description: 'maximum length of output, but zero means unlimited.'
in: query
required: false
type: integer
format: int32
- name: trace_config.overrides.homestead_block
- name: trace_config.log_config.overrides.homestead_block
description: 'Homestead switch block (nil no fork, 0 = already homestead).'
in: query
required: false
type: string
- name: trace_config.overrides.dao_fork_block
- name: trace_config.log_config.overrides.dao_fork_block
description: TheDAO hard-fork switch block (nil no fork).
in: query
required: false
type: string
- name: trace_config.overrides.dao_fork_support
- name: trace_config.log_config.overrides.dao_fork_support
description: Whether the nodes supports or opposes the DAO hard-fork.
in: query
required: false
type: boolean
- name: trace_config.overrides.eip150_block
- name: trace_config.log_config.overrides.eip150_block
description: >-
EIP150 implements the Gas price changes
@@ -2633,87 +2292,65 @@ paths:
in: query
required: false
type: string
- name: trace_config.overrides.eip150_hash
- name: trace_config.log_config.overrides.eip150_hash
description: >-
EIP150 HF hash (needed for header only clients as only gas pricing
changed).
in: query
required: false
type: string
- name: trace_config.overrides.eip155_block
- name: trace_config.log_config.overrides.eip155_block
description: EIP155Block HF block.
in: query
required: false
type: string
- name: trace_config.overrides.eip158_block
- name: trace_config.log_config.overrides.eip158_block
description: EIP158 HF block.
in: query
required: false
type: string
- name: trace_config.overrides.byzantium_block
- name: trace_config.log_config.overrides.byzantium_block
description: 'Byzantium switch block (nil no fork, 0 = already on byzantium).'
in: query
required: false
type: string
- name: trace_config.overrides.constantinople_block
- name: trace_config.log_config.overrides.constantinople_block
description: 'Constantinople switch block (nil no fork, 0 = already activated).'
in: query
required: false
type: string
- name: trace_config.overrides.petersburg_block
- name: trace_config.log_config.overrides.petersburg_block
description: Petersburg switch block (nil same as Constantinople).
in: query
required: false
type: string
- name: trace_config.overrides.istanbul_block
- name: trace_config.log_config.overrides.istanbul_block
description: 'Istanbul switch block (nil no fork, 0 = already on istanbul).'
in: query
required: false
type: string
- name: trace_config.overrides.muir_glacier_block
- name: trace_config.log_config.overrides.muir_glacier_block
description: >-
Eip-2384 (bomb delay) switch block (nil no fork, 0 = already
activated).
in: query
required: false
type: string
- name: trace_config.overrides.berlin_block
- name: trace_config.log_config.overrides.berlin_block
description: 'Berlin switch block (nil = no fork, 0 = already on berlin).'
in: query
required: false
type: string
- name: trace_config.overrides.london_block
- name: trace_config.log_config.overrides.catalyst_block
description: 'Catalyst switch block (nil = no fork, 0 = already on catalyst).'
in: query
required: false
type: string
- name: trace_config.log_config.overrides.london_block
description: 'London switch block (nil = no fork, 0 = already on london).'
in: query
required: false
type: string
- name: trace_config.enable_memory
description: enable memory capture.
in: query
required: false
type: boolean
- name: trace_config.enable_return_data
description: enable return data capture.
in: query
required: false
type: boolean
- name: block_number
description: block number of requested transaction.
in: query
required: false
type: string
format: int64
- name: block_hash
description: block hex hash of requested transaction.
in: query
required: false
type: string
- name: block_time
description: block time of requested transaction.
in: query
required: false
type: string
format: date-time
tags:
- Query
'/ethermint/evm/v1/validator_account/{cons_address}':
@@ -13856,6 +13493,9 @@ definitions:
berlin_block:
type: string
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
catalyst_block:
type: string
title: 'Catalyst switch block (nil = no fork, 0 = already on catalyst)'
london_block:
type: string
title: 'London switch block (nil = no fork, 0 = already on london)'
@@ -13921,6 +13561,93 @@ definitions:
by
the node.
ethermint.evm.v1.LogConfig:
type: object
properties:
disable_memory:
type: boolean
title: disable memory capture
disable_stack:
type: boolean
title: disable stack capture
disable_storage:
type: boolean
title: disable storage capture
disable_return_data:
type: boolean
title: disable return data capture
debug:
type: boolean
title: print output during capture end
limit:
type: integer
format: int32
title: 'maximum length of output, but zero means unlimited'
overrides:
title: >-
Chain overrides, can be used to execute a trace using future fork
rules
type: object
properties:
homestead_block:
type: string
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
dao_fork_block:
type: string
title: TheDAO hard-fork switch block (nil no fork)
dao_fork_support:
type: boolean
title: Whether the nodes supports or opposes the DAO hard-fork
eip150_block:
type: string
title: >-
EIP150 implements the Gas price changes
(https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil
no fork)
eip150_hash:
type: string
title: >-
EIP150 HF hash (needed for header only clients as only gas pricing
changed)
eip155_block:
type: string
title: EIP155Block HF block
eip158_block:
type: string
title: EIP158 HF block
byzantium_block:
type: string
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
constantinople_block:
type: string
title: 'Constantinople switch block (nil no fork, 0 = already activated)'
petersburg_block:
type: string
title: Petersburg switch block (nil same as Constantinople)
istanbul_block:
type: string
title: 'Istanbul switch block (nil no fork, 0 = already on istanbul)'
muir_glacier_block:
type: string
title: >-
Eip-2384 (bomb delay) switch block (nil no fork, 0 = already
activated)
berlin_block:
type: string
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
catalyst_block:
type: string
title: 'Catalyst switch block (nil = no fork, 0 = already on catalyst)'
london_block:
type: string
title: 'London switch block (nil = no fork, 0 = already on london)'
description: >-
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
values
instead of *big.Int.
title: LogConfig are the configuration options for structured logger the EVM
ethermint.evm.v1.MsgEthereumTx:
type: object
properties:
@@ -14250,6 +13977,9 @@ definitions:
berlin_block:
type: string
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
catalyst_block:
type: string
title: 'Catalyst switch block (nil = no fork, 0 = already on catalyst)'
london_block:
type: string
title: 'London switch block (nil = no fork, 0 = already on london)'
@@ -14396,6 +14126,9 @@ definitions:
berlin_block:
type: string
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
catalyst_block:
type: string
title: 'Catalyst switch block (nil = no fork, 0 = already on catalyst)'
london_block:
type: string
title: 'London switch block (nil = no fork, 0 = already on london)'
@@ -14419,13 +14152,6 @@ definitions:
description: |-
QueryStorageResponse is the response type for the Query/Storage RPC
method.
ethermint.evm.v1.QueryTraceBlockResponse:
type: object
properties:
data:
type: string
format: byte
title: QueryTraceBlockResponse defines TraceBlock response
ethermint.evm.v1.QueryTraceTxResponse:
type: object
properties:
@@ -14461,93 +14187,100 @@ definitions:
type: string
title: >-
overrides the default timeout of 5 seconds for JavaScript-based
tracing
calls
tracing calls
reexec:
type: string
format: uint64
title: number of blocks the tracer is willing to go back
disable_stack:
type: boolean
title: disable stack capture
disable_storage:
type: boolean
title: disable storage capture
debug:
type: boolean
title: print output during capture end
limit:
type: integer
format: int32
title: 'maximum length of output, but zero means unlimited'
overrides:
title: >-
Chain overrides, can be used to execute a trace using future fork
rules
log_config:
title: configuration options for structured logger the EVM
type: object
properties:
homestead_block:
type: string
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
dao_fork_block:
type: string
title: TheDAO hard-fork switch block (nil no fork)
dao_fork_support:
disable_memory:
type: boolean
title: Whether the nodes supports or opposes the DAO hard-fork
eip150_block:
type: string
title: disable memory capture
disable_stack:
type: boolean
title: disable stack capture
disable_storage:
type: boolean
title: disable storage capture
disable_return_data:
type: boolean
title: disable return data capture
debug:
type: boolean
title: print output during capture end
limit:
type: integer
format: int32
title: 'maximum length of output, but zero means unlimited'
overrides:
title: >-
EIP150 implements the Gas price changes
Chain overrides, can be used to execute a trace using future fork
rules
type: object
properties:
homestead_block:
type: string
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
dao_fork_block:
type: string
title: TheDAO hard-fork switch block (nil no fork)
dao_fork_support:
type: boolean
title: Whether the nodes supports or opposes the DAO hard-fork
eip150_block:
type: string
title: >-
EIP150 implements the Gas price changes
(https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil
no fork)
eip150_hash:
type: string
title: >-
EIP150 HF hash (needed for header only clients as only gas pricing
changed)
eip155_block:
type: string
title: EIP155Block HF block
eip158_block:
type: string
title: EIP158 HF block
byzantium_block:
type: string
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
constantinople_block:
type: string
title: 'Constantinople switch block (nil no fork, 0 = already activated)'
petersburg_block:
type: string
title: Petersburg switch block (nil same as Constantinople)
istanbul_block:
type: string
title: 'Istanbul switch block (nil no fork, 0 = already on istanbul)'
muir_glacier_block:
type: string
title: >-
Eip-2384 (bomb delay) switch block (nil no fork, 0 = already
activated)
berlin_block:
type: string
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
london_block:
type: string
title: 'London switch block (nil = no fork, 0 = already on london)'
description: >-
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
values
(https://github.com/ethereum/EIPs/issues/150) EIP150 HF block
(nil no fork)
eip150_hash:
type: string
title: >-
EIP150 HF hash (needed for header only clients as only gas
pricing changed)
eip155_block:
type: string
title: EIP155Block HF block
eip158_block:
type: string
title: EIP158 HF block
byzantium_block:
type: string
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
constantinople_block:
type: string
title: >-
Constantinople switch block (nil no fork, 0 = already
activated)
petersburg_block:
type: string
title: Petersburg switch block (nil same as Constantinople)
istanbul_block:
type: string
title: 'Istanbul switch block (nil no fork, 0 = already on istanbul)'
muir_glacier_block:
type: string
title: >-
Eip-2384 (bomb delay) switch block (nil no fork, 0 = already
activated)
berlin_block:
type: string
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
catalyst_block:
type: string
title: 'Catalyst switch block (nil = no fork, 0 = already on catalyst)'
london_block:
type: string
title: 'London switch block (nil = no fork, 0 = already on london)'
description: >-
ChainConfig defines the Ethereum ChainConfig parameters using
*sdk.Int values
instead of *big.Int.
enable_memory:
type: boolean
title: enable memory capture
enable_return_data:
type: boolean
title: enable return data capture
instead of *big.Int.
description: TraceConfig holds extra parameters to trace functions.
google.protobuf.Any:
type: object
+1 -3
View File
@@ -5,7 +5,6 @@ import (
"fmt"
"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/crypto"
@@ -31,13 +30,12 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
clientCtx := client.GetClientContextFromCmd(cmd)
kr, err := keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
rootDir,
inBuf,
clientCtx.Codec,
hd.EthSecp256k1Option(),
)
if err != nil {
-3
View File
@@ -5,7 +5,6 @@ import (
"github.com/spf13/cobra"
"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/crypto"
@@ -32,14 +31,12 @@ func runImportCmd(cmd *cobra.Command, args []string) error {
inBuf := bufio.NewReader(cmd.InOrStdin())
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
clientCtx := client.GetClientContextFromCmd(cmd)
kb, err := keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
rootDir,
inBuf,
clientCtx.Codec,
hd.EthSecp256k1Option(),
)
if err != nil {
+5 -3
View File
@@ -92,13 +92,15 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun)
if dryRun {
kr, err = keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, clientCtx.KeyringDir, buf, clientCtx.Codec, hd.EthSecp256k1Option())
clientCtx = clientCtx.WithKeyring(kr)
kr, err = keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, clientCtx.KeyringDir, buf, hd.EthSecp256k1Option())
} else {
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
kr, err = keyring.New(sdk.KeyringServiceName(), backend, clientCtx.KeyringDir, buf, hd.EthSecp256k1Option())
}
if err != nil {
return err
}
return clientkeys.RunAddCmd(clientCtx, cmd, args, buf)
return clientkeys.RunAddCmd(clientCtx.WithKeyring(kr), cmd, args, buf)
}
+4 -6
View File
@@ -122,7 +122,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun {
// use in memory keybase
kb = keyring.NewInMemory(ctx.Codec, etherminthd.EthSecp256k1Option())
kb = keyring.NewInMemory(etherminthd.EthSecp256k1Option())
} else {
_, err = kb.Key(name)
if err == nil {
@@ -156,9 +156,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}
if pks[i], err = k.GetPubKey(); err != nil {
return err
}
pks[i] = k.GetPubKey()
}
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
@@ -185,7 +183,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}
info, err := kb.SaveOfflineKey(name, pk)
info, err := kb.SavePubKey(name, pk, algo.Name())
if err != nil {
return err
}
@@ -291,7 +289,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return printCreate(cmd, info, showMnemonic, mnemonic, outputFormat)
}
func printCreate(cmd *cobra.Command, info *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemonic, outputFormat string) error {
switch outputFormat {
case OutputFormatText:
cmd.PrintErrln()
+13 -2
View File
@@ -3,6 +3,7 @@ package keys
import (
"fmt"
"io"
"path/filepath"
yaml "gopkg.in/yaml.v2"
@@ -19,9 +20,19 @@ const (
defaultKeyDBName = "keys"
)
type bechKeyOutFn func(keyInfo *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
type bechKeyOutFn func(keyInfo cryptokeyring.Info) (cryptokeyring.KeyOutput, error)
func printKeyInfo(w io.Writer, keyInfo *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) {
// 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)
+148 -240
View File
@@ -5,28 +5,29 @@ package client
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"os"
"path/filepath"
"time"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/ethereum/go-ethereum/common"
tmcfg "github.com/tendermint/tendermint/config"
"github.com/spf13/cobra"
tmconfig "github.com/tendermint/tendermint/config"
tmos "github.com/tendermint/tendermint/libs/os"
tmrand "github.com/tendermint/tendermint/libs/rand"
"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"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkserver "github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@@ -35,196 +36,124 @@ import (
"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"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/tharsis/ethermint/crypto/hd"
"github.com/tharsis/ethermint/server/config"
srvflags "github.com/tharsis/ethermint/server/flags"
ethermint "github.com/tharsis/ethermint/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"github.com/tharsis/ethermint/testutil/network"
)
var (
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v"
flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home"
flagStartingIPAddress = "starting-ip-address"
flagEnableLogging = "enable-logging"
flagRPCAddress = "rpc.address"
flagAPIAddress = "api.address"
flagPrintMnemonic = "print-mnemonic"
flagNodeDirPrefix = "node-dir-prefix"
flagNumValidators = "v"
flagOutputDir = "output-dir"
flagNodeDaemonHome = "node-daemon-home"
flagCoinDenom = "coin-denom"
flagIPAddrs = "ip-addresses"
)
type initArgs struct {
algo string
chainID string
keyringBackend string
minGasPrices string
nodeDaemonHome string
nodeDirPrefix string
numValidators int
outputDir string
startingIPAddress string
}
type startArgs struct {
algo string
apiAddress string
chainID string
grpcAddress string
minGasPrices string
outputDir string
rpcAddress string
jsonrpcAddress string
numValidators int
enableLogging bool
printMnemonic bool
}
func addTestnetFlagsToCmd(cmd *cobra.Command) {
cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with")
cmd.Flags().StringP(flagOutputDir, "o", "./localnet-setup", "Directory to store initialization data for the testnet")
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(sdkserver.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.01photino,0.001stake)")
cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.EthSecp256k1Type), "Key signing algorithm to generate keys for")
}
// NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize
// validator configuration files for running a multi-validator testnet in a separate process
func NewTestnetCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command {
testnetCmd := &cobra.Command{
Use: "testnet",
Short: "subcommands for starting or configuring local testnets",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
testnetCmd.AddCommand(testnetStartCmd())
testnetCmd.AddCommand(testnetInitFilesCmd(mbm, genBalIterator))
return testnetCmd
}
// get cmd to initialize all files for tendermint testnet and application
func testnetInitFilesCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command {
cmd := &cobra.Command{
Use: "init-files",
Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)",
Long: `init-files will setup "v" number of directories and populate each with
necessary files (private validator, genesis, config, etc.) for running "v" validator nodes.
Booting up a network with these validator folders is intended to be used with Docker Compose,
or a similar setup where each node has a manually configurable IP address.
Note, strict routability for addresses is turned off in the config file.
Example:
chibaclonkd testnet init-files --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
`,
RunE: func(cmd *cobra.Command, _ []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
serverCtx := sdkserver.GetServerContextFromCmd(cmd)
args := initArgs{}
args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
args.keyringBackend, _ = cmd.Flags().GetString(flags.FlagKeyringBackend)
args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
args.minGasPrices, _ = cmd.Flags().GetString(sdkserver.FlagMinGasPrices)
args.nodeDirPrefix, _ = cmd.Flags().GetString(flagNodeDirPrefix)
args.nodeDaemonHome, _ = cmd.Flags().GetString(flagNodeDaemonHome)
args.startingIPAddress, _ = cmd.Flags().GetString(flagStartingIPAddress)
args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators)
args.algo, _ = cmd.Flags().GetString(flags.FlagKeyAlgorithm)
return initTestnetFiles(clientCtx, cmd, serverCtx.Config, mbm, genBalIterator, args)
},
}
addTestnetFlagsToCmd(cmd)
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "chibaclonkd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagStartingIPAddress, "192.168.10.1", "Starting IP address (192.168.10.1 results in persistent peers list ID0@192.168.10.1:46656, ID1@192.168.10.2:46656, ...)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
return cmd
}
// get cmd to start multi validator in-process testnet
func testnetStartCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "start",
Short: "Launch an in-process multi-validator testnet",
Long: `testnet will launch an in-process multi-validator testnet,
and generate "v" directories, populated with necessary validator configuration files
(private validator, genesis, config, etc.).
Example:
chibaclonkd testnet --v 4 --output-dir ./.testnets
`,
RunE: func(cmd *cobra.Command, _ []string) error {
args := startArgs{}
args.outputDir, _ = cmd.Flags().GetString(flagOutputDir)
args.chainID, _ = cmd.Flags().GetString(flags.FlagChainID)
args.minGasPrices, _ = cmd.Flags().GetString(sdkserver.FlagMinGasPrices)
args.numValidators, _ = cmd.Flags().GetInt(flagNumValidators)
args.algo, _ = cmd.Flags().GetString(flags.FlagKeyAlgorithm)
args.enableLogging, _ = cmd.Flags().GetBool(flagEnableLogging)
args.rpcAddress, _ = cmd.Flags().GetString(flagRPCAddress)
args.apiAddress, _ = cmd.Flags().GetString(flagAPIAddress)
args.grpcAddress, _ = cmd.Flags().GetString(srvflags.GRPCAddress)
args.jsonrpcAddress, _ = cmd.Flags().GetString(srvflags.JSONRPCAddress)
args.printMnemonic, _ = cmd.Flags().GetBool(flagPrintMnemonic)
return startTestnet(cmd, args)
},
}
addTestnetFlagsToCmd(cmd)
cmd.Flags().Bool(flagEnableLogging, false, "Enable INFO logging of tendermint validator nodes")
cmd.Flags().String(flagRPCAddress, "tcp://0.0.0.0:26657", "the RPC address to listen on")
cmd.Flags().String(flagAPIAddress, "tcp://0.0.0.0:1317", "the address to listen on for REST API")
cmd.Flags().String(srvflags.GRPCAddress, config.DefaultGRPCAddress, "the gRPC server address to listen on")
cmd.Flags().String(srvflags.JSONRPCAddress, config.DefaultJSONRPCAddress, "the JSON-RPC server address to listen on")
cmd.Flags().Bool(flagPrintMnemonic, true, "print mnemonic of first validator to stdout for manual testing")
return cmd
}
const nodeDirPerm = 0o755
// initTestnetFiles initializes testnet files for a testnet to be run in a separate process
func initTestnetFiles(
// TestnetCmd initializes all files for tendermint testnet and application
func TestnetCmd(
mbm module.BasicManager, genBalancesIterator banktypes.GenesisBalancesIterator,
) *cobra.Command {
cmd := &cobra.Command{
Use: "testnet",
Short: "Initialize files for a Ethermint testnet",
Long: `testnet will create "v" number of directories and populate each with
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 --ip-addresses 192.168.10.2",
RunE: func(cmd *cobra.Command, _ []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
outputDir, _ := cmd.Flags().GetString(flagOutputDir)
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
chainID, _ := cmd.Flags().GetString(flags.FlagChainID)
minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices)
nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix)
nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome)
ipAddresses, _ := cmd.Flags().GetStringSlice(flagIPAddrs)
numValidators, _ := cmd.Flags().GetInt(flagNumValidators)
algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
coinDenom, _ := cmd.Flags().GetString(flagCoinDenom)
if len(ipAddresses) == 0 {
return errors.New("IP address list cannot be empty")
}
return InitTestnet(
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", "./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().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(server.FlagMinGasPrices, "", "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01inj,0.001stake)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
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,
nodeConfig *tmconfig.Config,
mbm module.BasicManager,
genBalIterator banktypes.GenesisBalancesIterator,
args initArgs,
outputDir,
chainID,
coinDenom,
minGasPrices,
nodeDirPrefix,
nodeDaemonHome,
keyringBackend,
algoStr string,
ipAddresses []string,
numValidators int,
) error {
if args.chainID == "" {
args.chainID = fmt.Sprintf("ethermint_%d-1", rand.Int63n(9999999999999)+1)
if chainID == "" {
chainID = fmt.Sprintf("ethermint_%d-1", tmrand.Int63n(9999999999999)+1)
}
nodeIDs := make([]string, args.numValidators)
valPubKeys := make([]cryptotypes.PubKey, args.numValidators)
if !ethermint.IsValidChainID(chainID) {
return fmt.Errorf("invalid chain-id: %s", chainID)
}
if err := sdk.ValidateDenom(coinDenom); err != nil {
return err
}
if len(ipAddresses) != 0 {
numValidators = len(ipAddresses)
}
nodeIDs := make([]string, numValidators)
valPubKeys := make([]cryptotypes.PubKey, numValidators)
appConfig := config.DefaultConfig()
appConfig.MinGasPrices = args.minGasPrices
appConfig.MinGasPrices = minGasPrices
appConfig.API.Enable = true
appConfig.Telemetry.Enabled = true
appConfig.Telemetry.PrometheusRetentionTime = 60
appConfig.Telemetry.EnableHostnameLabel = false
appConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", args.chainID}}
appConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", chainID}}
var (
genAccounts []authtypes.GenesisAccount
@@ -234,50 +163,65 @@ func initTestnetFiles(
inBuf := bufio.NewReader(cmd.InOrStdin())
// generate private keys, node IDs, and initial transactions
for i := 0; i < args.numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", args.nodeDirPrefix, i)
nodeDir := filepath.Join(args.outputDir, nodeDirName, args.nodeDaemonHome)
gentxsDir := filepath.Join(args.outputDir, "gentxs")
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
gentxsDir := filepath.Join(outputDir, "gentxs")
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(args.outputDir)
_ = os.RemoveAll(outputDir)
return err
}
nodeConfig.Moniker = nodeDirName
ip, err := getIP(i, args.startingIPAddress)
if err != nil {
_ = os.RemoveAll(args.outputDir)
return err
var (
ip string
err error
)
if len(ipAddresses) == 1 {
ip, err = getIP(i, ipAddresses[0])
if err != nil {
_ = os.RemoveAll(outputDir)
return err
}
} else {
ip = ipAddresses[i]
}
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig)
if err != nil {
_ = os.RemoveAll(args.outputDir)
_ = os.RemoveAll(outputDir)
return err
}
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
genFiles = append(genFiles, nodeConfig.GenesisFile())
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf, clientCtx.Codec, hd.EthSecp256k1Option())
kb, err := keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
nodeDir,
inBuf,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
keyringAlgos, _ := kb.SupportedAlgorithms()
algo, err := keyring.NewSigningAlgoFromString(args.algo, keyringAlgos)
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
if err != nil {
return err
}
addr, secret, err := testutil.GenerateSaveCoinKey(kb, nodeDirName, "", true, algo)
addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo)
if err != nil {
_ = os.RemoveAll(args.outputDir)
_ = os.RemoveAll(outputDir)
return err
}
@@ -289,16 +233,16 @@ func initTestnetFiles(
}
// save private key seed words
if err := network.WriteFile(fmt.Sprintf("%v.json", "key_seed"), nodeDir, cliPrint); err != nil {
if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), nodeDir, cliPrint); err != nil {
return err
}
accStakingTokens := sdk.TokensFromConsensusPower(5000, ethermint.PowerReduction)
coins := sdk.Coins{
sdk.NewCoin(ethermint.AttoPhoton, accStakingTokens),
}
coins := sdk.NewCoins(
sdk.NewCoin(coinDenom, accStakingTokens),
)
genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins.Sort()})
genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins})
genAccounts = append(genAccounts, &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0),
CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(),
@@ -308,7 +252,7 @@ func initTestnetFiles(
createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.ValAddress(addr),
valPubKeys[i],
sdk.NewCoin(ethermint.AttoPhoton, valTokens),
sdk.NewCoin(coinDenom, valTokens),
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
@@ -326,12 +270,12 @@ func initTestnetFiles(
txFactory := tx.Factory{}
txFactory = txFactory.
WithChainID(args.chainID).
WithChainID(chainID).
WithMemo(memo).
WithKeybase(kb).
WithTxConfig(clientCtx.TxConfig)
if err := tx.Sign(txFactory, nodeDirName, txBuilder, true); err != nil {
if err := tx.Sign(txFactory, nodeDirName, txBuilder, false); err != nil {
return err
}
@@ -340,33 +284,26 @@ func initTestnetFiles(
return err
}
if err := network.WriteFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
return err
}
customAppTemplate, customAppConfig := config.AppConfig(ethermint.AttoPhoton)
srvconfig.SetConfigTemplate(customAppTemplate)
customTmConfig := tmcfg.DefaultConfig()
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTmConfig); err != nil {
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil {
return err
}
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appConfig)
}
if err := initGenFiles(clientCtx, mbm, args.chainID, ethermint.AttoPhoton, genAccounts, genBalances, genFiles, args.numValidators); err != nil {
if err := initGenFiles(clientCtx, mbm, chainID, coinDenom, genAccounts, genBalances, genFiles, numValidators); err != nil {
return err
}
err := collectGenFiles(
clientCtx, nodeConfig, args.chainID, nodeIDs, valPubKeys, args.numValidators,
args.outputDir, args.nodeDirPrefix, args.nodeDaemonHome, genBalIterator,
clientCtx, nodeConfig, chainID, nodeIDs, valPubKeys, numValidators,
outputDir, nodeDirPrefix, nodeDaemonHome, genBalIterator,
)
if err != nil {
return err
}
cmd.PrintErrf("Successfully initialized %d node directories\n", args.numValidators)
cmd.PrintErrf("Successfully initialized %d node directories\n", numValidators)
return nil
}
@@ -381,6 +318,7 @@ func initGenFiles(
numValidators int,
) error {
appGenState := mbm.DefaultGenesis(clientCtx.Codec)
// set the accounts in the genesis state
var authGenState authtypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState)
@@ -406,7 +344,7 @@ func initGenFiles(
stakingGenState.Params.BondDenom = coinDenom
appGenState[stakingtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&stakingGenState)
var govGenState v1.GenesisState
var govGenState govtypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
@@ -456,7 +394,7 @@ func collectGenFiles(
outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator,
) error {
var appState json.RawMessage
genTime := time.Now()
genTime := tmtime.Now()
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
@@ -497,7 +435,7 @@ func collectGenFiles(
func getIP(i int, startingIPAddr string) (ip string, err error) {
if len(startingIPAddr) == 0 {
ip, err = sdkserver.ExternalIP()
ip, err = server.ExternalIP()
if err != nil {
return "", err
}
@@ -519,49 +457,19 @@ func calculateIP(ip string, i int) (string, error) {
return ipv4.String(), nil
}
// startTestnet starts an in-process testnet
func startTestnet(cmd *cobra.Command, args startArgs) error {
networkConfig := network.DefaultConfig()
func writeFile(name, dir string, contents []byte) error {
writePath := filepath.Join(dir)
file := filepath.Join(writePath, name)
// Default networkConfig.ChainID is random, and we should only override it if chainID provided
// is non-empty
if args.chainID != "" {
networkConfig.ChainID = args.chainID
}
networkConfig.SigningAlgo = args.algo
networkConfig.MinGasPrices = args.minGasPrices
networkConfig.NumValidators = args.numValidators
networkConfig.EnableTMLogging = args.enableLogging
networkConfig.RPCAddress = args.rpcAddress
networkConfig.APIAddress = args.apiAddress
networkConfig.GRPCAddress = args.grpcAddress
networkConfig.JSONRPCAddress = args.jsonrpcAddress
networkConfig.PrintMnemonic = args.printMnemonic
networkLogger := network.NewCLILogger(cmd)
baseDir := fmt.Sprintf("%s/%s", args.outputDir, networkConfig.ChainID)
if _, err := os.Stat(baseDir); !os.IsNotExist(err) {
return fmt.Errorf(
"testnests directory already exists for chain-id '%s': %s, please remove or select a new --chain-id",
networkConfig.ChainID, baseDir)
}
testnet, err := network.New(networkLogger, baseDir, networkConfig)
err := tmos.EnsureDir(writePath, 0o755)
if err != nil {
return err
}
_, err = testnet.WaitForHeight(1)
err = tmos.WriteFile(file, contents, 0o644)
if err != nil {
return err
}
cmd.Println("press the Enter Key to terminate")
_, err = fmt.Scanln() // wait for Enter Key
if err != nil {
return err
}
testnet.Cleanup()
return nil
}
-24
View File
@@ -1,24 +0,0 @@
package main
import (
"os"
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/tharsis/ethermint/app"
)
func main() {
rootCmd, _ := NewRootCmd()
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
switch e := err.(type) {
case server.ErrorCode:
os.Exit(e.Code)
default:
os.Exit(1)
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
const (
// Bech32Prefix defines the Bech32 prefix used for EthAccounts
Bech32Prefix = ethermint.Bech32MainPrefix
Bech32Prefix = "ethm"
// Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
Bech32PrefixAccAddr = Bech32Prefix
@@ -11,11 +11,11 @@ import (
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"github.com/tharsis/ethermint/app"
chibaclonkd "github.com/tharsis/ethermint/cmd/chibaclonkd"
ethermintd "github.com/tharsis/ethermint/cmd/ethermintd"
)
func TestInitCmd(t *testing.T) {
rootCmd, _ := chibaclonkd.NewRootCmd()
rootCmd, _ := ethermintd.NewRootCmd()
rootCmd.SetArgs([]string{
"init", // Test the init cmd
"etherminttest", // Moniker
@@ -23,6 +23,6 @@ func TestInitCmd(t *testing.T) {
fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint_9000-1"),
})
err := svrcmd.Execute(rootCmd, chibaclonkd.EnvPrefix, app.DefaultNodeHome)
err := svrcmd.Execute(rootCmd, app.DefaultNodeHome)
require.NoError(t, err)
}
@@ -11,7 +11,6 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@@ -20,6 +19,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/tharsis/ethermint/crypto/hd"
ethermint "github.com/tharsis/ethermint/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
@@ -44,44 +44,38 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
cdc := clientCtx.Codec
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
config.SetRoot(clientCtx.HomeDir)
var kr keyring.Keyring
addr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
inBuf := bufio.NewReader(cmd.InOrStdin())
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
if keyringBackend != "" && clientCtx.Keyring == nil {
var err error
kr, err = keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
clientCtx.HomeDir,
inBuf,
clientCtx.Codec,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
} else {
kr = clientCtx.Keyring
}
info, err := kr.Key(args[0])
keyringBackend, err := cmd.Flags().GetString(flags.FlagKeyringBackend)
if err != nil {
return fmt.Errorf("failed to get address from Keyring: %w", err)
return err
}
// attempt to lookup address from Keybase if no address was provided
kb, err := keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
clientCtx.HomeDir,
inBuf,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
addr, err = info.GetAddress()
info, err := kb.Key(args[0])
if err != nil {
return fmt.Errorf("failed to get address from Keyring: %w", err)
return fmt.Errorf("failed to get address from Keybase: %w", err)
}
addr = info.GetAddress()
}
coins, err := sdk.ParseCoinsNormalized(args[1])
@@ -148,7 +142,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
return fmt.Errorf("failed to unmarshal genesis state: %w", err)
}
authGenState := authtypes.GetGenesisStateFromAppState(clientCtx.Codec, appState)
authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState)
accs, err := authtypes.UnpackAccounts(authGenState.Accounts)
if err != nil {
@@ -170,19 +164,19 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
}
authGenState.Accounts = genAccs
authGenStateBz, err := clientCtx.Codec.MarshalJSON(&authGenState)
authGenStateBz, err := cdc.MarshalJSON(&authGenState)
if err != nil {
return fmt.Errorf("failed to marshal auth genesis state: %w", err)
}
appState[authtypes.ModuleName] = authGenStateBz
bankGenState := banktypes.GetGenesisStateFromAppState(clientCtx.Codec, appState)
bankGenState := banktypes.GetGenesisStateFromAppState(cdc, appState)
bankGenState.Balances = append(bankGenState.Balances, balances)
bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances)
bankGenState.Supply = bankGenState.Supply.Add(balances.Coins...)
bankGenStateBz, err := clientCtx.Codec.MarshalJSON(bankGenState)
bankGenStateBz, err := cdc.MarshalJSON(bankGenState)
if err != nil {
return fmt.Errorf("failed to marshal bank genesis state: %w", err)
}
@@ -200,7 +194,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
}
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(flags.FlagKeyringBackend, keyring.BackendFile, "Select keyring's backend (os|file|kwallet|pass|test)")
cmd.Flags().String(flagVestingAmt, "", "amount of coins 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")
+37
View File
@@ -0,0 +1,37 @@
package main
import (
"os"
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tharsis/ethermint/app"
cmdcfg "github.com/tharsis/ethermint/cmd/config"
)
func main() {
setupConfig()
cmdcfg.RegisterDenoms()
rootCmd, _ := NewRootCmd()
if err := svrcmd.Execute(rootCmd, app.DefaultNodeHome); err != nil {
switch e := err.(type) {
case server.ErrorCode:
os.Exit(e.Code)
default:
os.Exit(1)
}
}
}
func setupConfig() {
// set the address prefixes
config := sdk.GetConfig()
cmdcfg.SetBech32Prefixes(config)
cmdcfg.SetBip44CoinType(config)
config.Seal()
}
@@ -6,18 +6,22 @@ import (
"os"
"path/filepath"
"github.com/spf13/cast"
"github.com/spf13/cobra"
tmcli "github.com/tendermint/tendermint/libs/cli"
tmlog "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/config"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/rpc"
dbm "github.com/cosmos/cosmos-sdk/db"
"github.com/cosmos/cosmos-sdk/db/badgerdb"
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"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
@@ -25,11 +29,6 @@ import (
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/spf13/cast"
"github.com/spf13/cobra"
tmcfg "github.com/tendermint/tendermint/config"
tmcli "github.com/tendermint/tendermint/libs/cli"
tmlog "github.com/tendermint/tendermint/libs/log"
"github.com/tharsis/ethermint/app"
ethermintclient "github.com/tharsis/ethermint/client"
@@ -42,14 +41,14 @@ import (
ethermint "github.com/tharsis/ethermint/types"
)
const EnvPrefix = "CHIBACLONK"
const EnvPrefix = "ETHERMINT"
// NewRootCmd creates a new root command for simd. It is called once in the
// main function.
func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
initClientCtx := client.Context{}.
WithCodec(encodingConfig.Codec).
WithCodec(encodingConfig.Marshaler).
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithLegacyAmino(encodingConfig.Amino).
@@ -61,19 +60,16 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
WithViper(EnvPrefix)
rootCmd := &cobra.Command{
Use: "chibaclonkd",
Short: "Chiba-Clonk Daemon",
Use: "ethermintd",
Short: "Ethermint Daemon",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// set the default command outputs
cmd.SetOut(cmd.OutOrStdout())
cmd.SetErr(cmd.ErrOrStderr())
initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags())
if err != nil {
return err
}
initClientCtx = client.ReadHomeFlag(initClientCtx, cmd)
initClientCtx, err = config.ReadFromClientConfig(initClientCtx)
initClientCtx, err := config.ReadFromClientConfig(initClientCtx)
if err != nil {
return err
}
@@ -82,11 +78,9 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
return err
}
// FIXME: replace AttoPhoton with bond denom
customAppTemplate, customAppConfig := servercfg.AppConfig(ethermint.AttoPhoton)
customTMConfig := initTendermintConfig()
return sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTMConfig)
return sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig)
},
}
@@ -101,12 +95,12 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome),
),
genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome),
genutilcli.MigrateGenesisCmd(), // TODO: shouldn't this include the local app version instead of the SDK?
genutilcli.MigrateGenesisCmd(),
genutilcli.GenTxCmd(app.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome),
genutilcli.ValidateGenesisCmd(app.ModuleBasics),
AddGenesisAccountCmd(app.DefaultNodeHome),
tmcli.NewCompletionCmd(rootCmd, true),
ethermintclient.NewTestnetCmd(app.ModuleBasics, banktypes.GenesisBalancesIterator{}),
ethermintclient.TestnetCmd(app.ModuleBasics, banktypes.GenesisBalancesIterator{}),
debug.Cmd(),
config.Cmd(),
)
@@ -121,14 +115,10 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
txCommand(),
ethermintclient.KeyCommands(app.DefaultNodeHome),
)
rootCmd, err := srvflags.AddTxFlags(rootCmd)
if err != nil {
panic(err)
}
rootCmd = srvflags.AddTxFlags(rootCmd)
// add rosetta
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec))
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
// Add flags for GQL server.
rootCmd = srvflags.AddGQLFlags(rootCmd)
@@ -140,18 +130,6 @@ func addModuleInitFlags(startCmd *cobra.Command) {
crisis.AddModuleInitFlags(startCmd)
}
// initTendermintConfig helps to override default Tendermint Config values.
// return tmcfg.DefaultConfig if no custom configuration is required for the application.
func initTendermintConfig() *tmcfg.Config {
cfg := tmcfg.DefaultConfig()
// these values put a higher strain on node memory
// cfg.P2P.MaxNumInboundPeers = 100
// cfg.P2P.MaxNumOutboundPeers = 40
return cfg
}
func queryCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
@@ -207,7 +185,7 @@ type appCreator struct {
}
// newApp is an appCreator
func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
var cache sdk.MultiStorePersistentCache
if cast.ToBool(appOpts.Get(sdkserver.FlagInterBlockCache)) {
@@ -225,7 +203,7 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore
}
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")
snapshotDB, err := badgerdb.NewDB(filepath.Join(snapshotDir, "metadata"))
snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDir)
if err != nil {
panic(err)
}
@@ -233,10 +211,6 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore
if err != nil {
panic(err)
}
snapshotOptions := snapshottypes.NewSnapshotOptions(
cast.ToUint64(appOpts.Get(sdkserver.FlagStateSyncSnapshotInterval)),
cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent)),
)
ethermintApp := app.NewEthermintApp(
logger, db, traceStore, true, skipUpgradeHeights,
@@ -252,16 +226,20 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore
baseapp.SetInterBlockCache(cache),
baseapp.SetTrace(cast.ToBool(appOpts.Get(sdkserver.FlagTrace))),
baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))),
baseapp.SetSnapshot(snapshotStore, snapshotOptions),
baseapp.SetSnapshotStore(snapshotStore),
baseapp.SetSnapshotInterval(cast.ToUint64(appOpts.Get(sdkserver.FlagStateSyncSnapshotInterval))),
baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent))),
)
// Start
//go gql.Server(ethermintApp.BaseApp, ethermintApp.AppCodec(), ethermintApp.AccountKeeper, ethermintApp.BondKeeper)
return ethermintApp
}
// appExport creates a new simapp (optionally at a given height)
// and exports state.
func (a appCreator) appExport(
logger tmlog.Logger, db dbm.DBConnection, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
logger tmlog.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
appOpts servertypes.AppOptions,
) (servertypes.ExportedApp, error) {
var ethermintApp *app.EthermintApp
-1
View File
@@ -10,5 +10,4 @@ import (
// RegisterInterfaces register the Ethermint key concrete types.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &ethsecp256k1.PubKey{})
registry.RegisterImplementations((*cryptotypes.PrivKey)(nil), &ethsecp256k1.PrivKey{})
}
+4 -6
View File
@@ -4,7 +4,6 @@ import (
"strings"
"testing"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
@@ -13,14 +12,12 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptocodec "github.com/tharsis/ethermint/crypto/codec"
ethermint "github.com/tharsis/ethermint/types"
)
var protoCodec codec.Codec
func init() {
protoCodec = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
amino := codec.NewLegacyAmino()
cryptocodec.RegisterCrypto(amino)
}
@@ -31,7 +28,7 @@ func TestKeyring(t *testing.T) {
dir := t.TempDir()
mockIn := strings.NewReader("")
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, protoCodec, EthSecp256k1Option())
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, EthSecp256k1Option())
require.NoError(t, err)
// fail in retrieving key
@@ -43,8 +40,9 @@ func TestKeyring(t *testing.T) {
info, mnemonic, err := kr.NewMnemonic("foo", keyring.English, ethermint.BIP44HDPath, keyring.DefaultBIP39Passphrase, EthSecp256k1)
require.NoError(t, err)
require.NotEmpty(t, mnemonic)
require.Equal(t, "foo", info.Name)
require.Equal(t, "foo", info.GetName())
require.Equal(t, "local", info.GetType().String())
require.Equal(t, EthSecp256k1Type, info.GetAlgo())
hdPath := ethermint.BIP44HDPath
+33 -47
View File
@@ -1,87 +1,73 @@
version: "3"
services:
chibaclonkdnode0:
container_name: chibaclonkdnode0
image: "chibaclonkd/node"
ethermintdnode0:
container_name: ethermintdnode0
image: "ethermintd/node"
ports:
- "26656-26657:26656-26657"
- "1317:1317"
- "9090:9090"
- "26657:26657"
- "8545:8545"
- "8546:8546"
- "8125:8125"
environment:
- ID=0
- LOG=${LOG:-chibaclonkd.log}
- LOG=${LOG:-ethermintd.log}
volumes:
- ./localnet-setup/node0/chibaclonkd:/chibaclonk:Z
- ./localnet-setup/node0/ethermintd:/ethermint:Z
networks:
localnet:
ipv4_address: 192.168.10.1
- localnet
entrypoint: "bash start-docker.sh"
chibaclonkdnode1:
container_name: chibaclonkdnode1
image: "chibaclonkd/node"
ethermintdnode1:
container_name: ethermintdnode1
image: "ethermintd/node"
ports:
- "26666-26667:26656-26657"
- "1318:1317"
- "9091:9090"
- "26658:26657"
- "8555:8545"
- "8556:8546"
- "8126:8125"
environment:
- ID=1
- LOG=${LOG:-chibaclonkd.log}
- LOG=${LOG:-ethermintd.log}
volumes:
- ./localnet-setup/node1/chibaclonkd:/chibaclonk:Z
- ./localnet-setup/node1/ethermintd:/ethermint:Z
networks:
localnet:
ipv4_address: 192.168.10.2
- localnet
entrypoint: "bash start-docker.sh"
chibaclonkdnode2:
container_name: chibaclonkdnode2
image: "chibaclonkd/node"
ethermintdnode2:
container_name: ethermintdnode2
image: "ethermintd/node"
environment:
- ID=2
- LOG=${LOG:-chibaclonkd.log}
- LOG=${LOG:-ethermintd.log}
ports:
- "26676-26677:26656-26657"
- "1319:1317"
- "9092:9090"
- "26659:26657"
- "8565:8545"
- "8566:8546"
- "8127:8125"
volumes:
- ./localnet-setup/node2/chibaclonkd:/chibaclonk:Z
- ./localnet-setup/node2/ethermintd:/ethermint:Z
networks:
localnet:
ipv4_address: 192.168.10.3
- localnet
entrypoint: "bash start-docker.sh"
chibaclonkdnode3:
container_name: chibaclonkdnode3
image: "chibaclonkd/node"
ethermintdnode3:
container_name: ethermintdnode3
image: "ethermintd/node"
environment:
- ID=3
- LOG=${LOG:-chibaclonkd.log}
- LOG=${LOG:-ethermintd.log}
ports:
- "26686-26687:26656-26657"
- "1320:1317"
- "9093:9090"
- "26660:26657"
- "8575:8545"
- "8576:8546"
- "8128:8125"
volumes:
- ./localnet-setup/node3/chibaclonkd:/chibaclonk:Z
- ./localnet-setup/node3/ethermintd:/ethermint:Z
networks:
localnet:
ipv4_address: 192.168.10.4
# entrypoint: "sh scripts/start-docker.sh"
- localnet
entrypoint: "bash start-docker.sh"
networks:
localnet:
driver: bridge
ipam:
driver: default
config:
- subnet: 192.168.10.0/16
+512
View File
@@ -0,0 +1,512 @@
<template lang="pug">
div
.search__container
.search(@click="$emit('search', true)")
.search__icon
icon-search
.search__text Search
.h1 {{$frontmatter.title}}
.intro
.p {{$frontmatter.description}}
.h2 Getting Started
.p__alt Read all about Ethermint or dive straight into the code with guides.
.features
router-link(to="/quickstart").features__item.features__item__light
.features__item__image
icon-rocket.features__item__image__img
.features__item__text
.features__item__text__h2 read
.features__item__text__h1 Quick start
.features__item__text__p Deploy your own node, setup your testnet and more.
router-link(to="/guides").features__item.features__item__dark
.features__item__image
icon-code.features__item__image__img
.features__item__text
.features__item__text__h2 use
.features__item__text__h1 Guides
.features__item__text__p Follow guides to using polular Ethereum tools with Ethermint.
.sections__wrapper
.h2 Explore Ethermint
.p__alt Get familiar with Ethermint and explore its main concepts.
.sections
router-link.sections__item(tag="a" :to="section.url" v-for="section in $frontmatter.sections")
component(:is="`tm-icon-${section.icon}`").sections__item__icon
.sections__item__wrapper
.sections__item__title {{section.title}}
.sections__item__desc {{section.desc}}
.h2 Explore the stack
.p__alt Check out the docs for the various parts of the Ethermint stack.
.stack
a.stack__item(:href="item.url" v-for="item in $frontmatter.stack" :style="{'--accent': item.color, '--opacity': '5%'}")
.stack__item__wrapper
component(:is="`tm-logo-${item.label}`" :color="item.color" height="100px").stack__item__logo
svg(width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg").stack__item__icon
path(d="M1.07239 14.4697C0.779499 14.7626 0.779499 15.2374 1.07239 15.5303C1.36529 15.8232 1.84016 15.8232 2.13305 15.5303L1.07239 14.4697ZM15.7088 1.95457C16.0017 1.66168 16.0017 1.18681 15.7088 0.893912C15.4159 0.601019 14.941 0.601019 14.6482 0.893912L15.7088 1.95457ZM15.6027 1H16.3527C16.3527 0.585786 16.0169 0.25 15.6027 0.25V1ZM5.4209 0.25C5.00669 0.25 4.6709 0.585786 4.6709 1C4.6709 1.41421 5.00669 1.75 5.4209 1.75V0.25ZM14.8527 11.1818C14.8527 11.596 15.1885 11.9318 15.6027 11.9318C16.0169 11.9318 16.3527 11.596 16.3527 11.1818H14.8527ZM2.13305 15.5303L15.7088 1.95457L14.6482 0.893912L1.07239 14.4697L2.13305 15.5303ZM15.6027 0.25H5.4209V1.75H15.6027V0.25ZM16.3527 11.1818V1H14.8527V11.1818H16.3527Z" fill="#DADCE6")
div
.stack__item__h1 {{item.title}}
.stack__item__p {{item.desc}}
tm-help-support
</template>
<style lang="stylus" scoped>
/deep/ {
.container h1 {
margin-bottom: 1.5rem;
}
}
.search {
display: flex;
align-items: center;
color: rgba(22, 25, 49, 0.65);
padding-top: 1rem;
width: calc(var(--aside-width) - 6rem);
cursor: pointer;
transition: color 0.15s ease-out;
&:hover {
color: var(--color-text, black);
}
&__container {
display: flex;
justify-content: flex-end;
margin-top: 1rem;
margin-bottom: 1rem;
}
&__icon {
width: 1.5rem;
height: 1.5rem;
fill: #aaa;
margin-right: 0.5rem;
transition: fill 0.15s ease-out;
}
&:hover &__icon {
fill: var(--color-text, black);
}
}
.intro {
width: 100%;
max-width: 800px;
}
.h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 1.5rem;
line-height: 3.25rem;
letter-spacing: -0.02em;
padding-top: 2.5rem;
}
.h2 {
font-size: 2rem;
font-weight: 700;
margin-top: 4.5rem;
margin-bottom: 1rem;
line-height: 2.25rem;
letter-spacing: -0.01em;
}
.p {
font-size: 1.5rem;
line-height: 2.25rem;
&__alt {
margin-top: 0.75rem;
margin-bottom: 2rem;
font-size: 1.25rem;
line-height: 1.75rem;
}
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
margin-bottom: 5rem;
margin-top: 2.25rem;
&__item {
cursor: pointer;
display: grid;
grid-auto-flow: column;
grid-template-columns: minmax(6rem, 1fr) 2fr;
box-shadow: 0px 2px 4px rgba(22, 25, 49, 0.05), 0px 0px 1px rgba(22, 25, 49, 0.2), 0px 0.5px 0px rgba(22, 25, 49, 0.05);
position: relative;
border-radius: 0.5rem;
background: linear-gradient(281.08deg, #FFFFFF 48.96%, #E8F3FF 100%);
outline: none;
transition: box-shadow 0.25s ease-out, transform 0.25s ease-out, opacity 0.4s ease-out;
&:hover:not(:active), &:focus {
box-shadow: 0px 12px 24px rgba(22, 25, 49, 0.07), 0px 4px 8px rgba(22, 25, 49, 0.05), 0px 1px 0px rgba(22, 25, 49, 0.05);
transform: translateY(-2px);
transition-duration: 0.1s;
}
&:active {
opacity: 0.7;
transition-duration: 0s;
}
&__dark {
background: linear-gradient(112.22deg, #161831 0%, #2E3148 100%);
}
&__dark &__text__h2 {
color: white;
opacity: 0.5;
}
&__dark &__text__h1 {
color: white;
}
&__dark &__text__p {
color: white;
opacity: 0.8;
}
&__icon {
position: absolute;
top: 0;
right: 0;
padding: 0.75rem;
width: 1rem;
height: 1rem;
fill: white;
opacity: 0.35;
}
&:hover &__icon {
opacity: 0.6;
}
&__image {
display: flex;
align-items: center;
justify-content: center;
align-self: center;
max-height: 10rem;
transition: transform 0.2s ease-out;
&__img {
max-height: 14rem;
max-width: 10rem;
min-width: 8rem;
}
}
&:hover:not(:active) &__image {
transform: translateY(-0.25rem) scale(1.02);
transition-duration: 0.1s;
}
&__text {
padding: 1.75rem 2rem 2rem;
display: flex;
flex-direction: column;
&__h2 {
font-size: 0.75rem;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--color-text-dim, inherit);
margin-bottom: 0.25rem;
}
&__h1 {
font-size: 1.25rem;
color: var(--color-text, black);
line-height: 1.75rem;
letter-spacing: 0.01em;
font-weight: 600;
margin-top: 0.25rem;
margin-bottom: 0.75rem;
}
&__p {
color: var(--color-text-dim, inherit);
font-size: 0.875rem;
letter-spacing: 0.03em;
line-height: 1.25rem;
margin-bottom: 1.5rem;
}
}
}
}
.sections {
display: grid;
margin-top: 3rem;
margin-bottom: 5rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
&__item {
position: relative;
color: initial;
border-radius: 0.5rem;
padding: 1.5rem 1.5rem 1.5rem 5.5rem;
box-shadow: 0px 2px 4px rgba(22, 25, 49, 0.05), 0px 0px 1px rgba(22, 25, 49, 0.2), 0px 0.5px 0px rgba(22, 25, 49, 0.05);
transition: box-shadow 0.25s ease-out, transform 0.25s ease-out, opacity 0.4s ease-out;
&:hover:not(:active) {
box-shadow: 0px 12px 24px rgba(22, 25, 49, 0.07), 0px 4px 8px rgba(22, 25, 49, 0.05), 0px 1px 0px rgba(22, 25, 49, 0.05);
transform: translateY(-2px);
transition-duration: 0.1s;
}
&:active {
transition-duration: 0s;
opacity: 0.7;
}
&__icon {
position: absolute;
left: 1.25rem;
font-size: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
}
&__title {
font-weight: 600;
margin-bottom: 0.5rem;
}
&__desc {
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--color-text-dim, inherit);
}
}
}
.stack {
display: grid;
gap: 1.5rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
margin-bottom: 4rem;
&__item {
position: relative;
min-height: 120px;
display: flex;
align-items: center;
padding: 2rem 1.25rem;
border-radius: 0.5rem;
box-shadow: 0px 2px 4px rgba(22, 25, 49, 0.05), 0px 0px 1px rgba(22, 25, 49, 0.2), 0px 0.5px 0px rgba(22, 25, 49, 0.05);
color: var(--color-text, black);
background: white;
transition: box-shadow 0.25s ease-out, transform 0.25s ease-out, opacity 0.4s ease-out;
&:hover:not(:active) {
box-shadow: 0px 12px 24px rgba(22, 25, 49, 0.07), 0px 4px 8px rgba(22, 25, 49, 0.05), 0px 1px 0px rgba(22, 25, 49, 0.05);
transform: translateY(-2px);
transition-duration: 0.1s;
}
&:active {
opacity: 0.7;
transition-duration: 0s;
}
&__icon {
position: absolute;
top: 0;
right: 0;
padding: 1rem;
opacity: 0.35;
}
&:hover &__icon {
opacity: 0.6;
}
&__h1 {
font-size: 1.25rem;
line-height: 1.5rem;
margin-bottom: 0.75rem;
font-weight: 600;
}
&__p {
font-size: 0.875rem;
color: rgba(22, 25, 49, 0.65);
line-height: 1.25rem;
}
&__wrapper {
display: grid;
grid-auto-flow: row;
gap: 1.25rem;
text-align: center;
}
&:before {
position: absolute;
top: 0;
left: 0;
content: '';
width: 50%;
height: 100%;
background: linear-gradient(to right, var(--accent), rgba(255, 255, 255, 0));
border-radius: 0.5rem;
opacity: 0.1;
}
&__logo {
height: 72px;
width: auto;
}
}
}
@media screen and (max-width: 1136px) {
.p {
font-size: 1.25rem;
line-height: 1.75rem;
}
}
@media screen and (max-width: 832px) {
.h1 {
padding-top: 3.5rem;
}
.search__container {
display: none;
}
}
@media screen and (max-width: 752px) {
.search {
display: none;
}
}
@media screen and (max-width: 500px) {
.h1 {
font-size: 2rem;
line-height: 2.25rem;
margin-bottom: 1rem;
}
.h2 {
font-size: 1.5rem;
line-height: 2rem;
margin-top: 3rem;
margin-bottom: 0.75rem;
}
.p__alt {
font-size: 1rem;
line-height: 1.5rem;
}
.features {
margin-bottom: 1.5rem;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
&__item {
display: block;
&:not(:active) {
box-shadow: 0px 24px 40px rgba(0, 0, 0, 0.1), 0px 10px 16px rgba(0, 0, 0, 0.08), 0px 1px 0px rgba(0, 0, 0, 0.05);
}
&__image {
max-height: 9rem;
padding-top: 1rem;
}
&__text {
padding: 1.5rem;
}
}
}
.sections {
gap: 0;
margin-bottom: 0;
margin-top: 2rem;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
margin-left: -1rem;
margin-right: -1rem;
&__item {
margin-bottom: 0;
padding: 1.25rem 1rem 0 5.5rem;
&, &:hover:not(:active) {
box-shadow: none;
}
&__icon {
top: 1rem;
left: 1.25rem;
}
&__wrapper {
padding-bottom: 1.25rem;
border-bottom: 1px solid rgba(140, 145, 177, 0.32);
}
&:last-child .sections__item__wrapper {
border-bottom: none;
}
}
&__wrapper {
position: relative;
padding: 0.1px 1rem 1rem;
background: white;
border-radius: 0.5rem;
&:before {
position: absolute;
content: '';
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 0.5rem;
box-shadow: 0px 24px 40px rgba(0, 0, 0, 0.1), 0px 10px 16px rgba(0, 0, 0, 0.08), 0px 1px 0px rgba(0, 0, 0, 0.05);
}
}
}
.stack {
gap: 0.75rem;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
margin-bottom: 3rem;
&__item {
padding: 1.25rem;
&:not(:active) {
box-shadow: 0px 24px 40px rgba(22, 25, 49, 0.1), 0px 10px 16px rgba(22, 25, 49, 0.08), 0px 1px 0px rgba(22, 25, 49, 0.05);
}
&__wrapper {
grid-template-columns: 3rem 1fr;
text-align: start;
}
&__h1 {
font-size: inherit;
line-height: inherit;
margin-bottom: 0.5rem;
}
}
}
}
</style>
+31
View File
@@ -0,0 +1,31 @@
<template>
<svg width="100%" height="100%" viewBox="0 0 165 140" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="15.2" y="0.399879" width="135.6" height="115.2" rx="4.8" stroke="url(#paint0_linear)" stroke-width="0.6"/>
<rect x="0.199982" y="46.5999" width="145.2" height="94.8" transform="rotate(-15 0.199982 46.5999)" fill="url(#paint1_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M87.4269 40.4409C88.0849 40.5195 88.5547 41.1167 88.4761 41.7747L81.1977 102.735C81.1192 103.393 80.522 103.863 79.8639 103.784C79.2059 103.706 78.7361 103.109 78.8147 102.451L86.0931 41.4902C86.1716 40.8321 86.7688 40.3624 87.4269 40.4409ZM60.8853 56.9452C61.4443 57.3012 61.6089 58.0429 61.253 58.6019L46.1657 82.2944L71.0008 95.0057C71.5907 95.3076 71.8242 96.0307 71.5223 96.6206C71.2203 97.2106 70.4973 97.4441 69.9073 97.1421L43.8986 83.8301L42.7249 83.2294L43.4331 82.1173L59.2286 57.3128C59.5846 56.7538 60.3263 56.5892 60.8853 56.9452ZM94.2871 47.9121C93.6966 47.6112 92.9739 47.8459 92.673 48.4364C92.3721 49.0269 92.6068 49.7495 93.1973 50.0504L118.014 62.6977L102.942 86.455C102.587 87.0146 102.753 87.7561 103.313 88.1111C103.872 88.4661 104.614 88.3003 104.969 87.7406L120.747 62.8701L121.453 61.7568L120.278 61.1581L94.2871 47.9121Z" fill="#8CA9C6"/>
<path d="M34.1 14.7999C34.1 17.2852 32.0853 19.2999 29.6 19.2999V19.8999C32.4167 19.8999 34.7 17.6165 34.7 14.7999H34.1ZM29.6 10.2999C32.0853 10.2999 34.1 12.3146 34.1 14.7999H34.7C34.7 11.9832 32.4167 9.69988 29.6 9.69988V10.2999ZM25.1 14.7999C25.1 12.3146 27.1147 10.2999 29.6 10.2999V9.69988C26.7834 9.69988 24.5 11.9832 24.5 14.7999H25.1ZM29.6 19.2999C27.1147 19.2999 25.1 17.2852 25.1 14.7999H24.5C24.5 17.6165 26.7834 19.8999 29.6 19.8999V19.2999ZM48.4999 14.7999C48.4999 17.2852 46.4852 19.2999 43.9999 19.2999V19.8999C46.8166 19.8999 49.0999 17.6165 49.0999 14.7999H48.4999ZM43.9999 10.2999C46.4852 10.2999 48.4999 12.3146 48.4999 14.7999H49.0999C49.0999 11.9832 46.8166 9.69988 43.9999 9.69988V10.2999ZM39.4999 14.7999C39.4999 12.3146 41.5147 10.2999 43.9999 10.2999V9.69988C41.1833 9.69988 38.8999 11.9832 38.8999 14.7999H39.4999ZM43.9999 19.2999C41.5147 19.2999 39.4999 17.2852 39.4999 14.7999H38.8999C38.8999 17.6165 41.1833 19.8999 43.9999 19.8999V19.2999ZM58.4 19.8999C61.2167 19.8999 63.5 17.6165 63.5 14.7999H62.9C62.9 17.2852 60.8853 19.2999 58.4 19.2999V19.8999ZM53.3 14.7999C53.3 17.6165 55.5834 19.8999 58.4 19.8999V19.2999C55.9147 19.2999 53.9 17.2852 53.9 14.7999H53.3ZM58.4 9.69988C55.5834 9.69988 53.3 11.9832 53.3 14.7999H53.9C53.9 12.3146 55.9147 10.2999 58.4 10.2999V9.69988ZM63.5 14.7999C63.5 11.9832 61.2167 9.69988 58.4 9.69988V10.2999C60.8853 10.2999 62.9 12.3146 62.9 14.7999H63.5Z" fill="url(#paint3_linear)"/>
<path d="M15.2 29.1999H150.8" stroke="url(#paint4_linear)" stroke-width="0.6"/>
<defs>
<linearGradient id="paint0_linear" x1="120.998" y1="62.4" x2="120.998" y2="177.6" gradientUnits="userSpaceOnUse">
<stop stop-color="#8CA9C6"/>
<stop offset="1" stop-color="#336699"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="127.715" y1="148.887" x2="147.74" y2="281.816" gradientUnits="userSpaceOnUse">
<stop stop-color="#336699"/>
<stop offset="1" stop-color="#8CA9C6"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="125.577" y1="107.749" x2="125.258" y2="229.399" gradientUnits="userSpaceOnUse">
<stop stop-color="#8CA9C6"/>
<stop offset="1" stop-color="#336699"/>
</linearGradient>
<linearGradient id="paint3_linear" x1="81.9981" y1="72" x2="81.9981" y2="97.2" gradientUnits="userSpaceOnUse">
<stop stop-color="#8CA9C6"/>
<stop offset="1" stop-color="#336699"/>
</linearGradient>
<linearGradient id="paint4_linear" x1="120.998" y1="67.2" x2="120.998" y2="163.2" gradientUnits="userSpaceOnUse">
<stop stop-color="#8CA9C6"/>
<stop offset="1" stop-color="#336699"/>
</linearGradient>
</defs>
</svg>
</template>
+41
View File
@@ -0,0 +1,41 @@
<template>
<svg width="100%" height="100%" viewBox="0 0 150 230" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M129.04 81.9366L135.681 58.78L125.153 20.3152L95.8426 47.3566L89.2025 70.5132L105.801 87.8034L129.04 81.9366Z" fill="url(#paint0_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M122.412 105.051L129.028 81.9786L112.418 64.7302L89.1905 70.5552L82.5745 93.6277L99.1854 110.876L122.412 105.051Z" fill="url(#paint1_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M96.9404 193.882L115.64 128.671L98.9611 111.437L75.6844 117.214L56.5251 182.294L76.9628 188.154L96.9404 193.882Z" fill="url(#paint2_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.0642 201.869L93.0233 133.456L51.5928 127.542L12.0095 178.467L42.0642 201.869Z" fill="url(#paint3_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M98.6275 218.088L92.8579 134.032L131.018 150.902L135.385 214.524L98.6275 218.088Z" fill="url(#paint4_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M35.4626 196.23L99.4743 110.96L58.1472 105.081L5.50019 172.841L35.4626 196.23Z" stroke="url(#paint5_linear)" stroke-width="0.7"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M106.575 217.245L99.4741 110.959L137.392 127.801L143.167 213.533L106.575 217.245Z" stroke="url(#paint6_linear)" stroke-width="0.7"/>
<defs>
<linearGradient id="paint0_linear" x1="171.808" y1="70.3402" x2="210.702" y2="119.532" gradientUnits="userSpaceOnUse">
<stop stop-color="#336699" stop-opacity="0.91"/>
<stop offset="1" stop-color="#8CAAC6"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="161.105" y1="107.665" x2="185.783" y2="154.845" gradientUnits="userSpaceOnUse">
<stop stop-color="#336699" stop-opacity="0.91"/>
<stop offset="1" stop-color="#8CAAC6"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="144.638" y1="164.499" x2="188.211" y2="213.994" gradientUnits="userSpaceOnUse">
<stop stop-color="#336699" stop-opacity="0.91"/>
<stop offset="1" stop-color="#8CAAC6"/>
</linearGradient>
<linearGradient id="paint3_linear" x1="112.6" y1="179.034" x2="154.555" y2="254.491" gradientUnits="userSpaceOnUse">
<stop stop-color="#336699" stop-opacity="0.91"/>
<stop offset="1" stop-color="#8CAAC6"/>
</linearGradient>
<linearGradient id="paint4_linear" x1="173.74" y1="196.982" x2="215.848" y2="270.124" gradientUnits="userSpaceOnUse">
<stop stop-color="#336699" stop-opacity="0.91"/>
<stop offset="1" stop-color="#8CAAC6"/>
</linearGradient>
<linearGradient id="paint5_linear" x1="108.253" y1="125.86" x2="80.7963" y2="221.613" gradientUnits="userSpaceOnUse">
<stop stop-color="#8CA9C6"/>
<stop offset="1" stop-color="#336699"/>
</linearGradient>
<linearGradient id="paint6_linear" x1="177.248" y1="145.644" x2="149.626" y2="241.973" gradientUnits="userSpaceOnUse">
<stop stop-color="#8CA9C6"/>
<stop offset="1" stop-color="#336699"/>
</linearGradient>
</defs>
</svg>
</template>
@@ -0,0 +1,6 @@
<template>
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="48" height="48" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.2612 1.52098L45.3579 24.8028L24.2611 47.4575L2.62622 24.8029L24.2612 1.52098ZM5.63765 24.5003L23.2519 33.396V5.54515L5.63765 24.5003ZM25.2519 5.59283V33.3772L42.3871 24.5028L25.2519 5.59283ZM39.3349 28.3358L25.2519 35.6295V43.4588L39.3349 28.3358ZM23.2519 43.5049V35.6365L8.73749 28.3064L23.2519 43.5049Z" fill="#7499BF"/>
</svg>
</template>
@@ -0,0 +1,11 @@
<template>
<div>
<svg width="100%" height="100%" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.6" d="M39.9917 30.4542L17.5 40.6792L39.9917 53.975L62.4875 40.6792L39.9917 30.4542Z" fill="black"/>
<path opacity="0.45" d="M17.5083 40.6791L40 53.975V30.4541V3.35828L17.5083 40.6791Z" fill="black"/>
<path opacity="0.8" d="M40 3.35828V30.4541V53.975L62.4917 40.6791L40 3.35828Z" fill="black"/>
<path opacity="0.45" d="M17.5 44.9458L39.9917 76.6416V58.2333L17.5 44.9458Z" fill="black"/>
<path opacity="0.8" d="M39.9917 58.2333V76.6416L62.5 44.9458L39.9917 58.2333Z" fill="black"/>
</svg>
</div>
</template>
@@ -0,0 +1,7 @@
<template>
<div>
<svg width="100%" height="100%" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M63.3188 38.6786L40.0002 52.4512L16.6724 38.6786L40.0002 0L63.3188 38.6786ZM40.0001 75.9369L16.6724 43.0953L40.0001 56.8679L63.3371 43.0953L40.0001 75.9369ZM40.0106 22.5689C41.8663 22.5689 43.7036 22.9206 45.4097 23.5941C45.495 24.2572 45.5265 24.9236 45.5046 25.5884C43.8027 24.7855 41.9183 24.3629 40.0106 24.3629C33.1513 24.3629 27.5045 29.8641 27.1843 36.7318C30.4764 38.4276 34.3665 38.5945 37.7989 37.2405C38.3645 37.6723 38.9596 38.064 39.5805 38.4118C37.6113 39.3875 35.4391 39.9162 33.2435 39.9478C33.1741 39.9489 33.1043 39.9494 33.035 39.9494C30.5163 39.9494 28.0306 39.2905 25.8327 38.0383L25.3766 37.7786L25.3799 37.253C25.4044 33.3394 26.9318 29.6577 29.6808 26.886C32.4418 24.1021 36.1104 22.5689 40.0106 22.5689ZM54.6886 37.139C54.6364 32.2612 52.2708 27.8109 48.3276 25.1C48.3305 25.8137 48.283 26.5271 48.1854 27.2362C50.9873 29.5334 52.6955 32.916 52.8824 36.622C46.8383 39.7491 39.3006 37.5591 35.8671 31.5834C34.9397 29.9693 34.3711 28.1645 34.204 26.3205C33.6206 26.6399 33.0635 27.0074 32.5375 27.4194C32.8149 29.194 33.4176 30.9174 34.317 32.4827C36.2701 35.8819 39.4102 38.319 43.1585 39.3447C44.4302 39.6928 45.7232 39.865 47.0091 39.865C49.5145 39.865 51.9931 39.2113 54.2359 37.9305L54.6941 37.6687L54.6886 37.139ZM40.0878 12.1068L40.5393 12.3722C47.4822 16.4532 49.8515 25.4683 45.8206 32.4686C44.9135 34.0439 43.7216 35.4371 42.3214 36.5745C41.7042 36.3236 41.1102 36.0235 40.5445 35.6779C42.0591 34.6 43.3375 33.1961 44.2724 31.5723C47.7249 25.5767 45.8347 17.8993 40.0869 14.1965C36.9575 16.2106 34.8408 19.5066 34.274 23.1534C33.6161 23.4268 32.9798 23.7466 32.369 24.1104C32.5218 21.8982 33.1735 19.7309 34.2753 17.7961C35.5512 15.5558 37.4049 13.6801 39.6361 12.3718L40.0878 12.1068Z" fill="white"/>
</svg>
</div>
</template>
+278
View File
@@ -0,0 +1,278 @@
module.exports = {
theme: 'cosmos',
title: 'Ethermint Documentation',
locales: {
'/': {
lang: 'en-US'
},
},
markdown: {
extendMarkdown: (md) => {
md.use(require("markdown-it-katex"));
},
},
head: [
[
"link",
{
rel: "stylesheet",
href:
"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css",
},
],
[
"link",
{
rel: "stylesheet",
href:
"https://cdn.jsdelivr.net/github-markdown-css/2.2.1/github-markdown.css",
},
],
],
base: process.env.VUEPRESS_BASE || '/',
plugins: [
'vuepress-plugin-element-tabs'
],
themeConfig: {
repo: 'tharsis/ethermint',
docsRepo: 'tharsis/ethermint',
docsBranch: 'main',
docsDir: 'docs',
editLinks: true,
custom: true,
project: {
name: 'Ethermint',
denom: 'PHOTON',
ticker: 'ETHM',
rpc_url: '',
rpc_url_local: 'http://localhost:8545/',
chain_id: '9000',
block_explorer_url: '',
},
logo: {
src: '/ethermint-logo-horizontal-alpha.svg',
},
algolia: {
id: 'BH4D9OD16A',
key: 'c5da4dd3636828292e3c908a0db39688',
index: 'ethermint'
},
topbar: {
banner: false
},
sidebar: {
auto: false,
nav: [
{
title: 'Reference',
children: [
{
title: 'Introduction',
directory: true,
path: '/intro'
},
{
title: 'Quick Start',
directory: true,
path: '/quickstart'
},
{
title: 'Basics',
directory: true,
path: '/basics'
},
{
title: 'Core Concepts',
directory: true,
path: '/core'
},
]
},
{
title: 'Guides',
children: [
{
title: 'Localnet',
directory: true,
path: '/guides/localnet'
},
{
title: 'Keys and Wallets',
directory: true,
path: '/guides/keys-wallets'
},
{
title: 'Ethereum Tooling',
directory: true,
path: '/guides/tools'
},
{
title: 'Validators',
directory: true,
path: '/guides/validators'
},
{
title: 'Key Management System',
directory: true,
path: '/guides/kms'
},
]
},
{
title: 'APIs',
children: [
{
title: 'JSON-RPC',
directory: true,
path: '/api/json-rpc'
},
{
title: 'Protobuf Reference',
directory: false,
path: '/api/proto-docs'
},
]
},
{
title: 'Testnet',
children: [
{
title: 'Join Testnet',
directory: false,
path: '/testnet/join'
},
{
title: 'Token Faucet',
directory: false,
path: '/testnet/faucet'
},
{
title: 'Deploy Node on Cloud',
directory: false,
path: '/testnet/cloud_providers'
}
]
},
{
title: 'Specifications',
children: [{
title: 'Modules',
directory: true,
path: '/modules'
}]
}, {
title: 'Resources',
children: [
{
title: 'Ethermint API Reference',
path: 'https://pkg.go.dev/github.com/tharsis/ethermint'
},
{
title: 'Cosmos REST API Spec',
path: 'https://cosmos.network/rpc/'
},
{
title: 'JSON-RPC API Reference',
path: '/api/json-rpc/endpoints'
}
]
}
]
},
gutter: {
title: 'Help & Support',
chat: {
title: 'Developer Chat',
text: 'Chat with Ethermint developers on Discord.',
url: 'https://discord.gg/trje9XuAmy',
bg: 'linear-gradient(103.75deg, #1B1E36 0%, #22253F 100%)'
},
forum: {
title: 'Ethermint Developer Forum',
text: 'Join the Ethermint Developer Forum to learn more.',
url: 'https://forum.cosmos.network/c/ethermint',
bg: 'linear-gradient(221.79deg, #3D6B99 -1.08%, #336699 95.88%)',
logo: 'ethereum-white'
},
github: {
title: 'Found an Issue?',
text: 'Help us improve this page by suggesting edits on GitHub.',
bg: '#F8F9FC'
}
},
footer: {
logo: '/logo-bw.svg',
textLink: {
text: 'ethermint.dev',
url: 'https://ethermint.dev'
},
services: [
{
service: 'github',
url: 'https://github.com/tharsis/ethermint'
},
{
service: "twitter",
url: "https://twitter.com/ethermint",
},
{
service: "linkedin",
url: "https://www.linkedin.com/company/tharsis-finance/",
},
{
service: "medium",
url: "https://medium.com/@tharsis_labs",
},
],
smallprint: 'This website is maintained by Tharsis Labs Ltd.',
links: [{
title: 'Documentation',
children: [{
title: 'Cosmos SDK Docs',
url: 'https://docs.cosmos.network/master/'
},
{
title: 'Ethereum Docs',
url: 'https://ethereum.org/developers'
},
{
title: 'Tendermint Core Docs',
url: 'https://docs.tendermint.com'
}
]
},
{
title: 'Community',
children: [{
title: 'Ethermint Community',
url: 'https://discord.gg/trje9XuAmy'
},
{
title: 'Ethermint Forum',
url: 'https://forum.cosmos.network/c/ethermint'
}
]
},
{
title: 'Tharsis',
children: [
{
title: 'Jobs at Tharsis',
url: 'https://tharsis.notion.site/Jobs-at-Tharsis-5a1642eb89b34747ae6f2db2d356fc0d'
}
]
}
]
},
versions: [
{
"label": "main",
"key": "main"
},
{
"label": "v0.5",
"key": "v0.5"
}
],
}
};
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 526 192" style="enable-background:new 0 0 526 192;" xml:space="preserve">
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_2_);}
.st2{fill:url(#SVGID_3_);}
.st3{fill:url(#SVGID_4_);}
.st4{fill:#B3C9F4;}
.st5{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st6{fill:#717BBF;}
.st7{opacity:0.5;fill:url(#SVGID_5_);enable-background:new ;}
.st8{opacity:0.5;fill:url(#SVGID_6_);enable-background:new ;}
.st9{fill:#131516;}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="96.4904" y1="115.7662" x2="80.8316" y2="187.581" gradientTransform="matrix(1 0 0 -1 0 194)">
<stop offset="0" style="stop-color:#8D8DE4"/>
<stop offset="1" style="stop-color:#89A2E5;stop-opacity:0"/>
<stop offset="1" style="stop-color:#BBD9FF;stop-opacity:0"/>
</linearGradient>
<path class="st0" d="M76.9,7v123.2l54.8-32.3L76.9,7z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="85.6408" y1="131.291" x2="28.6749" y2="93.2238" gradientTransform="matrix(1 0 0 -1 0 194)">
<stop offset="0" style="stop-color:#8D8DE4"/>
<stop offset="1" style="stop-color:#89A2E5;stop-opacity:0"/>
<stop offset="1" style="stop-color:#BBD9FF;stop-opacity:0"/>
</linearGradient>
<path class="st1" d="M22.1,97.8l54.8,32.3V7L22.1,97.8z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="22.1" y1="47.25" x2="76.9" y2="47.25" gradientTransform="matrix(1 0 0 -1 0 194)">
<stop offset="0" style="stop-color:#E3FFFF"/>
<stop offset="1" style="stop-color:#89A2E5"/>
<stop offset="1" style="stop-color:#BBF9FF;stop-opacity:0"/>
</linearGradient>
<path class="st2" d="M22.1,108.2l54.8,77.1v-44.8L22.1,108.2z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-52.6532" y1="253.8875" x2="422.5458" y2="-79.853">
<stop offset="6.489749e-03" style="stop-color:#DC614D"/>
<stop offset="0.3603" style="stop-color:#8D8DE4"/>
<stop offset="1" style="stop-color:#89A2E5"/>
</linearGradient>
<path class="st3" d="M76.9,140.5v44.8l54.8-77.1L76.9,140.5z"/>
<g>
<path class="st4" d="M76.9,72.9L22.1,97.8l54.8,32.3l54.8-32.3L76.9,72.9z"/>
</g>
<path class="st5" d="M89.6,62.4c-4-1.6-8.3-2.4-12.7-2.4c-9.2,0-17.8,3.6-24.3,10.1s-10,15.2-10.1,24.3v1.2l1.1,0.6
c5.2,2.9,11,4.5,16.9,4.5c0.2,0,0.3,0,0.5,0c5.2-0.1,10.3-1.3,14.9-3.6c-1.5-0.8-2.9-1.7-4.2-2.8c-8.1,3.2-17.2,2.8-24.9-1.2
c0.8-16.1,14-29,30.1-29c4.5,0,8.9,1,12.9,2.9C89.8,65.5,89.8,64,89.6,62.4"/>
<path class="st5" d="M111.3,94.2c-0.1-11.5-5.7-21.9-14.9-28.3c0,1.7-0.1,3.4-0.3,5c6.6,5.4,10.6,13.3,11,22
c-14.2,7.3-31.9,2.2-40-11.8c-2.2-3.8-3.5-8-3.9-12.4c-1.4,0.8-2.7,1.6-3.9,2.6c0.7,4.2,2.1,8.2,4.2,11.9c4.6,8,12,13.7,20.8,16.1
c3,0.8,6,1.2,9,1.2c5.9,0,11.7-1.5,17-4.5l1.1-0.6L111.3,94.2z"/>
<path class="st5" d="M78.1,36L77,35.4L76,36c-5.2,3.1-9.6,7.5-12.6,12.7c-2.6,4.5-4.1,9.6-4.5,14.8c1.4-0.9,2.9-1.6,4.5-2.2
c1.3-8.6,6.3-16.3,13.7-21C90.6,49,95,67.1,86.9,81.1c-2.2,3.8-5.2,7.1-8.8,9.6c1.3,0.8,2.7,1.5,4.2,2.1c3.3-2.7,6.1-5.9,8.2-9.6
C100,66.8,94.4,45.6,78.1,36"/>
<polygon class="st6" points="76.9,146.5 131.7,108.2 131.7,108.2 76.9,140.5 22.1,108.2 22.1,108.2 "/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="75.5332" y1="186.2992" x2="42.3256" y2="50.7691" gradientTransform="matrix(1 0 0 -1 0 194)">
<stop offset="0" style="stop-color:#E3FFFF"/>
<stop offset="1" style="stop-color:#BBF9FF;stop-opacity:0"/>
</linearGradient>
<path class="st7" d="M22.1,97.8l54.8,32.3V7L22.1,97.8z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="117.958" y1="89.2972" x2="55.3226" y2="144.3732" gradientTransform="matrix(1 0 0 -1 0 194)">
<stop offset="1.975860e-02" style="stop-color:#DD5C47"/>
<stop offset="1" style="stop-color:#BBF9FF;stop-opacity:0"/>
</linearGradient>
<path class="st8" d="M76.9,7v123.2l54.8-32.3L76.9,7z"/>
<g>
<path class="st9" d="M182.2,76.1h34.4v8.4h-24.7V97h19.8v8.4h-19.8v13.8h25.5v8.5h-35.2L182.2,76.1L182.2,76.1z"/>
<path class="st9" d="M235.6,79.3v11.2h10.3v7.6h-10.3v16.2c0,3.8,2,5.7,5.4,5.7h4.9v7.7h-6c-8.1,0-13.4-4.7-13.4-13V98.2h-7.3v-7.6
h7.3V79.3H235.6z"/>
<path class="st9" d="M252.8,74.6h9v21.7c2.1-4.1,6.4-6.4,11.7-6.4c8.3,0,13.8,6.1,13.8,14.8v23h-9v-21.1c0-5.1-3.2-8.6-7.8-8.6
c-5,0-8.6,4-8.6,9.5v20.3h-9L252.8,74.6L252.8,74.6z"/>
<path class="st9" d="M328.9,115.4c-1.4,7.9-8.3,13-17.5,13c-12.2,0-19-9.6-19-19.4s6.1-19.1,18.2-19.1c12.5,0,18.1,9.1,18.1,17.9
c0,1.3-0.1,2.4-0.1,3.1h-27.5c0.7,6,4.5,9.8,10.3,9.8c4.7,0,7.7-1.9,8.6-5.5h8.9V115.4z M301.4,105h18.3c-0.4-4.7-3.6-8.3-9-8.3
C305.6,96.7,302.3,99.4,301.4,105z"/>
<path class="st9" d="M351.2,98.2c-5.8,0-8.1,4.9-8.1,12v17.6H334V90.5h9.1v6.6c1.8-4.7,4.7-6.6,9.5-6.6h4.4v7.6L351.2,98.2
L351.2,98.2z"/>
<path class="st9" d="M361.2,90.5h9.1v5.8c1.8-3.8,5.5-6.4,10.8-6.4c5.9,0,10,2.5,11.6,7.1c1.7-3.8,6.4-7.1,12.3-7.1
c8.1,0,13.2,5.8,13.2,13.7v24.1h-9v-21.3c0-5.2-2.7-8.7-7.1-8.7c-4.9,0-7.9,3.5-7.9,8.7v21.3h-9v-21.3c0-5.2-2.7-8.7-7.1-8.7
c-4.8,0-7.8,3.5-7.8,8.7v21.3h-9.1V90.5z"/>
<path class="st9" d="M434.7,74.6v10.1h-9.8V74.6H434.7z M425.3,90.5h9.1v37.2h-9.1V90.5z"/>
<path class="st9" d="M441.5,90.5h9.1v5.8c2.1-4.1,6.3-6.4,11.6-6.4c8.4,0,13.9,6.1,13.9,14.8v23H467v-21.1c0-5.1-3.1-8.6-7.8-8.6
c-5.1,0-8.6,4-8.6,9.5v20.3h-9.1V90.5z"/>
<path class="st9" d="M495.6,79.3v11.2h10.3v7.6h-10.3v16.2c0,3.8,2,5.7,5.4,5.7h4.9v7.7h-6c-8.1,0-13.4-4.7-13.4-13V98.2h-7.3v-7.6
h7.3V79.3H495.6z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

+94
View File
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg width="240" height="96" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 526 192" style="enable-background:new 0 0 526 192;" xml:space="preserve">
<style type="text/css">
.st0{fill:#131516;}
.st1{fill:url(#SVGID_1_);}
.st2{fill:url(#SVGID_2_);}
.st3{fill:url(#SVGID_3_);}
.st4{fill:url(#SVGID_4_);}
.st5{fill:#B3C9F4;}
.st6{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st7{fill:#717BBF;}
.st8{opacity:0.5;fill:url(#SVGID_5_);enable-background:new ;}
.st9{opacity:0.5;fill:url(#SVGID_6_);enable-background:new ;}
</style>
<g>
<path class="st0" d="M180.9,75.3l35,0v8.6l-25.1,0v12.8l20.1,0v8.6l-20.1,0v14l25.9,0l0,8.6l-35.8,0L180.9,75.3z"/>
<path class="st0" d="M247.7,73.8l9.2,0v22.1c2.1-4.1,6.5-6.5,11.9-6.5c8.5,0,14,6.2,14,15v23.4l-9.2,0l0-21.5c0-5.2-3.2-8.8-8-8.8
c-5.1,0-8.8,4.1-8.8,9.6l0,20.6l-9.2,0L247.7,73.8z"/>
<path class="st0" d="M324.3,115.2c-1.4,8-8.5,13.2-17.8,13.2c-12.4,0-19.3-9.8-19.3-19.7c0-10,6.2-19.4,18.5-19.4
c12.7,0,18.4,9.2,18.4,18.2c0,1.3-0.1,2.4-0.1,3.2l-27.9,0c0.7,6.1,4.6,10,10.4,10c4.7,0,7.8-2,8.8-5.6L324.3,115.2z M296.3,104.7
l18.6,0c-0.4-4.8-3.7-8.4-9.2-8.4C300.6,96.3,297.2,99,296.3,104.7z"/>
<path class="st0" d="M345.3,97.7c-5.9,0-8.2,5-8.2,12.2v17.9l-9.2,0l0-37.8l9.2,0v6.7c1.9-4.8,4.8-6.7,9.7-6.7h4.4v7.7L345.3,97.7z
"/>
<path class="st0" d="M355.9,90l9.2,0v5.9c1.9-3.8,5.6-6.5,11-6.5c6,0,10.1,2.6,11.8,7.2c1.7-3.9,6.5-7.2,12.5-7.2
c8.2,0,13.4,5.9,13.4,14l0,24.5l-9.2,0l0-21.7c0-5.3-2.8-8.9-7.2-8.9c-5,0-8,3.5-8,8.9v21.7l-9.2,0v-21.7c0-5.3-2.8-8.9-7.2-8.9
c-4.9,0-8,3.5-8,8.9l0,21.7l-9.2,0L355.9,90z"/>
<path class="st0" d="M429.1,73.8v10.3l-9.9,0l0-10.3L429.1,73.8z M419.5,90l9.2,0l0,37.8l-9.2,0L419.5,90z"/>
<path class="st0" d="M435,90l9.2,0v5.9c2.1-4.1,6.4-6.5,11.8-6.5c8.6,0,14.1,6.2,14.1,15v23.4l-9.2,0v-21.5c0-5.2-3.2-8.8-7.9-8.8
c-5.2,0-8.8,4.1-8.8,9.6l0,20.6l-9.2,0L435,90z"/>
<path class="st0" d="M489.4,78.4v11.5h10.6v7.8h-10.6v16.6c0,3.8,2,5.8,5.5,5.8h5.1v7.8h-6.1c-8.3,0-13.7-4.8-13.7-13.3v-17h-7.5
v-7.8h7.5V78.4H489.4z"/>
<path class="st0" d="M233.4,78.4v11.5h10.6v7.8h-10.6v16.6c0,3.8,2,5.8,5.5,5.8h5.1v7.8h-6.1c-8.3,0-13.7-4.8-13.7-13.3v-17h-7.5
v-7.8h7.5V78.4H233.4z"/>
</g>
<g>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-624.5055" y1="-406.1891" x2="-639.7977" y2="-476.3224" gradientTransform="matrix(1 0 0 1 720.2893 484.6111)">
<stop offset="0" style="stop-color:#8D8DE4"/>
<stop offset="1" style="stop-color:#89A2E5;stop-opacity:0"/>
<stop offset="1" style="stop-color:#BBD9FF;stop-opacity:0"/>
</linearGradient>
<path class="st1" d="M76.7,8.8v120.3l53.5-31.6L76.7,8.8z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-635.0693" y1="-421.3597" x2="-690.7014" y2="-384.1838" gradientTransform="matrix(1 0 0 1 720.2893 484.6111)">
<stop offset="0" style="stop-color:#8D8DE4"/>
<stop offset="1" style="stop-color:#89A2E5;stop-opacity:0"/>
<stop offset="1" style="stop-color:#BBD9FF;stop-opacity:0"/>
</linearGradient>
<path class="st2" d="M23.1,97.5l53.5,31.6V8.8L23.1,97.5z"/>
</g>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="23.0618" y1="-1965.4794" x2="76.6382" y2="-1965.4794" gradientTransform="matrix(1 0 0 -1 0 -1820)">
<stop offset="0" style="stop-color:#E3FFFF"/>
<stop offset="1" style="stop-color:#89A2E5"/>
<stop offset="1" style="stop-color:#BBF9FF;stop-opacity:0"/>
</linearGradient>
<path class="st3" d="M23.1,107.8l53.6,75.4v-43.8L23.1,107.8z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-50.0858" y1="1004.2726" x2="414.7754" y2="677.7925" gradientTransform="matrix(1 0 0 1 0 -754)">
<stop offset="6.489749e-03" style="stop-color:#DC614D"/>
<stop offset="0.3603" style="stop-color:#8D8DE4"/>
<stop offset="1" style="stop-color:#89A2E5"/>
</linearGradient>
<path class="st4" d="M76.6,139.4v43.8l53.6-75.4L76.6,139.4z"/>
<g>
<path class="st5" d="M76.6,73.2L23.1,97.6l53.6,31.6l53.6-31.6L76.6,73.2z"/>
</g>
<path class="st6" d="M89.1,63c-3.9-1.5-8.1-2.4-12.4-2.4c-9,0-17.4,3.5-23.7,9.9c-6.3,6.4-9.8,14.8-9.9,23.7v1.2l1.1,0.6
c5.1,2.9,10.8,4.4,16.5,4.4c0.2,0,0.3,0,0.5,0c5.1-0.1,10.1-1.3,14.6-3.5c-1.5-0.8-2.9-1.7-4.1-2.7c-7.9,3.2-16.8,2.7-24.4-1.2
C48,77.2,61,64.6,76.6,64.6c4.4,0,8.7,1,12.6,2.9C89.3,66,89.3,64.6,89.1,63"/>
<path class="st6" d="M110.3,94.1c-0.1-11.3-5.6-21.4-14.6-27.7c0,1.7-0.1,3.3-0.3,4.9c6.4,5.3,10.4,13,10.8,21.5
C92.4,100,75,95,67.1,81.3c-2.2-3.7-3.4-7.8-3.8-12.1c-1.4,0.8-2.7,1.5-3.8,2.5c0.7,4.1,2,8.1,4.1,11.6
c4.5,7.8,11.8,13.4,20.4,15.8c2.9,0.8,5.9,1.2,8.8,1.2c5.7,0,11.4-1.5,16.6-4.4l1.1-0.6L110.3,94.1z"/>
<path class="st6" d="M77.8,37.2l-1.1-0.6l-1,0.6c-5.1,3-9.4,7.4-12.3,12.4c-2.5,4.4-4,9.4-4.4,14.5c1.4-0.9,2.9-1.5,4.4-2.2
c1.3-8.4,6.2-16,13.4-20.5c13.2,8.5,17.5,26.2,9.6,39.9c-2.2,3.7-5.1,6.9-8.6,9.4c1.3,0.8,2.7,1.5,4.1,2c3.2-2.7,6-5.7,8.1-9.4
C99.3,67.3,93.8,46.6,77.8,37.2"/>
<polygon class="st7" points="76.6,145.2 130.3,107.8 130.3,107.8 76.6,139.4 23.1,107.8 23.1,107.8 "/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="75.316" y1="-1829.4694" x2="42.8308" y2="-1962.051" gradientTransform="matrix(1 0 0 -1 0 -1820)">
<stop offset="0" style="stop-color:#E3FFFF"/>
<stop offset="1" style="stop-color:#BBF9FF;stop-opacity:0"/>
</linearGradient>
<path class="st8" d="M23.1,97.6l53.6,31.6V8.8L23.1,97.6z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="116.8103" y1="-1924.3955" x2="55.5375" y2="-1870.5176" gradientTransform="matrix(1 0 0 -1 0 -1820)">
<stop offset="1.975860e-02" style="stop-color:#DD5C47"/>
<stop offset="1" style="stop-color:#BBF9FF;stop-opacity:0"/>
</linearGradient>
<path class="st9" d="M76.6,8.8v120.5l53.6-31.6L76.6,8.8z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

+3
View File
@@ -0,0 +1,3 @@
:root
--color-link #3171B0
--color-primary #7499BF
+111
View File
@@ -0,0 +1,111 @@
# Updating the docs
If you want to open a PR on the Cosmos SDK to update the documentation, please follow the guidelines in the [`CONTRIBUTING.md`](https://github.com/tharsis/ethermint/tree/main/CONTRIBUTING.md#updating-documentation)
## Translating
- Docs translations live in a `docs/country-code/` folder, where `country-code` stands for the country code of the language used (`cn` for Chinese, `kr` for Korea, `fr` for France, ...).
- Always translate content living on `main`.
- Only content under `/docs/intro/`, `/docs/basics/`, `/docs/core/`, `/docs/building-modules/` and `docs/interfaces` needs to be translated, as well as `docs/README.md`. It is also nice (but not mandatory) to translate `/docs/spec/`.
- Specify the release/tag of the translation in the README of your translation folder. Update the release/tag each time you update the translation.
## Docs Build Workflow
The documentation for Ethermint is hosted at https://ethermint.dev/
built from the files in this (`/docs`) directory for
[master](https://github.com/tharsis/ethermint/tree/main/docs).
### How It Works
There is a CircleCI job listening for changes in the `/docs` directory, on
the `main` branch. Any updates to files in this directory
on that branch will automatically trigger a website deployment. Under the hood,
the private website repository has a `make build-docs` target consumed by a CircleCI job in that repo.
## README
The [README.md](./README.md) is also the landing page for the documentation
on the website. During the Jenkins build, the current commit is added to the bottom
of the README.
## Config.js
The [config.js](./.vuepress/config.js) generates the sidebar and Table of Contents
on the website docs. Note the use of relative links and the omission of
file extensions. Additional features are available to improve the look
of the sidebar.
## Links
**NOTE:** Strongly consider the existing links - both within this directory
and to the website docs - when moving or deleting files.
Relative links should be used nearly everywhere, having discovered and weighed the following:
### Relative
Where is the other file, relative to the current one?
- works both on GitHub and for the VuePress build
- confusing / annoying to have things like: `../../../../myfile.md`
- requires more updates when files are re-shuffled
### Absolute
Where is the other file, given the root of the repo?
- works on GitHub, doesn't work for the VuePress build
- this is much nicer: `/docs/hereitis/myfile.md`
- if you move that file around, the links inside it are preserved (but not to it, of course)
### Full
The full GitHub URL to a file or directory. Used occasionally when it makes sense
to send users to the GitHub.
## Building Locally
Make sure you are in the `docs` directory and run the following commands:
```bash
rm -rf node_modules
```
This command will remove old version of the visual theme and required packages. This step is optional.
```bash
yarn install
```
Install the theme and all dependencies.
```bash
yarn run serve
```
Run `pre` and `post` hooks and start a hot-reloading web-server. See output of this command for the URL (it is often [https://localhost:8080](https://localhost:8080)).
To build documentation as a static website run `yarn run build`. You will find the website in `.vuepress/dist` directory.
## Search
We are using [Algolia](https://www.algolia.com) to power full-text search. This uses a public API search-only key in the `config.js` as well as a [cosmos_network.json](https://github.com/algolia/docsearch-configs/blob/main/configs/cosmos_network.json) configuration file that we can update with PRs.
### Update and Build the RPC docs
1. Execute the following command at the root directory to install the swagger-ui generate tool.
```bash
make tools
```
2. Edit API docs
1. Directly Edit API docs manually: `client/lcd/swagger-ui/swagger.yaml`.
2. Edit API docs within the [Swagger Editor](https://editor.swagger.io/). Please refer to this [document](https://swagger.io/docs/specification/2-0/basic-structure/) for the correct structure in `.yaml`.
3. Download `swagger.yaml` and replace the old `swagger.yaml` under fold `client/lcd/swagger-ui`.
4. Compile ethermintd
```bash
make install
```
+60
View File
@@ -0,0 +1,60 @@
<!--
layout: home
title: Ethermint Documentation
description: Ethermint is a scalable and interoperable Ethereum, built on Proof-of-Stake with fast-finality.
sections:
- title: Introduction
desc: Read a high-level overview of Ethermint and its architecture.
url: /intro
icon: ethereum-intro
- title: Basics
desc: Start with the basic concepts of Ethermint, like accounts and transactions.
url: /basics
icon: basics
- title: Core Concepts
desc: Read about the core concepts like encoding and events.
url: /core
icon: core
stack:
- title: Cosmos SDK
desc: The SDK is the worlds most popular framework for building application-specific blockchains.
color: "#5064FB"
label: sdk
url: http://docs.cosmos.network
- title: Ethereum
desc: Ethereum is a global, open-source platform for decentralized applications.
color: "#1A1F36"
label: ethereum-black
url: https://eth.wiki
- title: Tendermint Core
desc: The leading BFT engine for building blockchains, powering Ethermint.
color: "#00BB00"
label: core
url: http://docs.tendermint.com
footer:
newsletter: false
aside: false
-->
# Ethermint Documentation
## Get Started
- **[Introduction](./intro/overview.md)**: High-level overview of Ethermint.
## Reference
- **[Basics](./basics/)**: Documentation on the basic concepts of Ethermint, like the standard anatomy of an application, the transaction lifecycle and accounts management.
- **[Core](./core/)**: Documentation on the core concepts of Ethermint, like `encoding`, and `events`.
- **[Building Modules](./building-modules/)**: Important concepts for module developers like `message`s, `keeper`s, `handler`s and `querier`s.
- **[Interfaces](./interfaces/)**: Documentation on building interfaces for Ethermint applications.
## Other Resources
- **[Module Directory](../x/)**: Module implementations and their respective documentation.
- **[Ethermint API Reference](https://godoc.org/github.com/tharsis/ethermint)**: Godocs of Ethermint.
- **[REST API spec](https://cosmos.network/rpc/)**: List of REST endpoints to interact with an full-node through REST.
## Contribute
See [this file](https://github.com/tharsis/ethermint/blob/main/docs/DOCS_README.md) for details of the build process and considerations when making changes.
+12
View File
@@ -0,0 +1,12 @@
<!--
order: false
parent:
order: 1
-->
# API
This section contains different client and API reference document.
1. [JSON-RPC](./json-rpc.md)
1. [Protobuf Docs](./proto-docs.md)
File diff suppressed because it is too large Load Diff
+130
View File
@@ -0,0 +1,130 @@
<!--
order: 5
-->
# Events
`Event`s are objects that contain information about the execution of the application. They are
mainly used by service providers like block explorers and wallet to track the execution of various
messages and index transactions. {synopsis}
## Pre-requisite Readings
- [Cosmos SDK Events](https://docs.cosmos.network/master/core/events.html) {prereq}
- [Ethereum's PubSub JSON-RPC API](https://geth.ethereum.org/docs/rpc/pubsub) {prereq}
## Subscribing to Events
### SDK and Tendermint Events
It is possible to subscribe to `Events` via Tendermint's [Websocket](https://tendermint.com/docs/app-dev/subscribing-to-events-via-websocket.html#subscribing-to-events-via-websocket).
This is done by calling the `subscribe` RPC method via Websocket:
```json
{
"jsonrpc": "2.0",
"method": "subscribe",
"id": "0",
"params": {
"query": "tm.event='eventCategory' AND eventType.eventAttribute='attributeValue'"
}
}
```
The main `eventCategory` you can subscribe to are:
- `NewBlock`: Contains `events` triggered during `BeginBlock` and `EndBlock`.
- `Tx`: Contains `events` triggered during `DeliverTx` (i.e. transaction processing).
- `ValidatorSetUpdates`: Contains validator set updates for the block.
These events are triggered from the `state` package after a block is committed. You can get the full
list of `event` categories
[here](https://godoc.org/github.com/tendermint/tendermint/types#pkg-constants).
The `type` and `attribute` value of the `query` allow you to filter the specific `event` you are
looking for. For example, a `MsgEthereumTx` transaction triggers an `event` of type `ethermint` and
has `sender` and `recipient` as `attributes`. Subscribing to this `event` would be done like so:
```json
{
"jsonrpc": "2.0",
"method": "subscribe",
"id": "0",
"params": {
"query": "tm.event='Tx' AND ethereum.recipient='hexAddress'"
}
}
```
where `hexAddress` is an Ethereum hex address (eg: `0x1122334455667788990011223344556677889900`).
### Ethereum JSON-RPC Events
Ethermint also supports the Ethereum [JSON-RPC](https://eth.wiki/json-rpc/API) filters calls to
subscribe to [state logs](https://eth.wiki/json-rpc/API#eth_newfilter),
[blocks](https://eth.wiki/json-rpc/API#eth_newblockfilter) or [pending
transactions](https://eth.wiki/json-rpc/API#eth_newpendingtransactionfilter) changes.
Under the hood, it uses the Tendermint RPC client's event system to process subscriptions that are
then formatted to Ethereum-compatible events.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newBlockFilter","params":[],"id":1}' -H "Content-Type: application/json" http://localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x3503de5f0c766c68f78a03a3b05036a5"}
```
Then you can check if the state changes with the [`eth_getFilterChanges`](https://eth.wiki/json-rpc/API#eth_getfilterchanges) call:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x3503de5f0c766c68f78a03a3b05036a5"],"id":1}' -H "Content-Type: application/json" http://localhost:8545
{"jsonrpc":"2.0","id":1,"result":["0x7d44dceff05d5963b5bc81df7e9f79b27e777b0a03a6feca09f3447b99c6fa71","0x3961e4050c27ce0145d375255b3cb829a5b4e795ac475c05a219b3733723d376","0xd7a497f95167d63e6feca70f344d9f6e843d097b62729b8f43bdcd5febf142ab","0x55d80a4ba6ef54f2a8c0b99589d017b810ed13a1fda6a111e1b87725bc8ceb0e","0x9e8b92c17280dd05f2562af6eea3285181c562ebf41fc758527d4c30364bcbc4","0x7353a4b9d6b35c9eafeccaf9722dd293c46ae2ffd4093b2367165c3620a0c7c9","0x026d91bda61c8789c59632c349b38fd7e7557e6b598b94879654a644cfa75f30","0x73e3245d4ddc3bba48fa67633f9993c6e11728a36401fa1206437f8be94ef1d3"]}
```
## Websocket Connection
### Tendermint Websocket
To start a connection with the Tendermint websocket you need to define the address with the `--rpc.laddr`
flag when starting the node (default `tcp://127.0.0.1:26657`):
```bash
ethermintd start --rpc.laddr="tcp://127.0.0.1:26657"
```
Then, start a websocket subscription with [ws](https://github.com/hashrocket/ws)
```bash
# connect to tendermint websocket at port 8080 as defined above
ws ws://localhost:8080/websocket
# subscribe to new Tendermint block headers
> { "jsonrpc": "2.0", "method": "subscribe", "params": ["tm.event='NewBlockHeader'"], "id": 1 }
```
### Ethereum Websocket
Since Ethermint runs uses Tendermint Core as it's consensus Engine and it's built with the Cosmos
SDK framework, it inherits the event format from them. However, in order to support the native Web3
compatibility for websockets of the [Ethereum's
PubSubAPI](https://geth.ethereum.org/docs/rpc/pubsub), Ethermint needs to cast the Tendermint
responses retrieved into the Ethereum types.
You can start a connection with the Ethereum websocket using the `--json-rpc.ws-address` flag when starting
the node (default `"0.0.0.0:8546"`):
```bash
ethermintd start --json-rpc.address"0.0.0.0:8545" --json-rpc.ws-address="0.0.0.0:8546" --evm.rpc.api="eth,web3,net,txpool,debug" --json-rpc.enable
```
Then, start a websocket subscription with [`ws`](https://github.com/hashrocket/ws)
```bash
# connect to tendermint websocet at port 8546 as defined above
ws ws://localhost:8546/
# subscribe to new Ethereum-formatted block Headers
> {"id": 1, "method": "eth_subscribe", "params": ["newHeads", {}]}
< {"jsonrpc":"2.0","result":"0x44e010cb2c3161e9c02207ff172166ef","id":1}
```
+26
View File
@@ -0,0 +1,26 @@
<!--
order: 3
-->
# Namespaces
Check the JSON-RPC namespaces supported on Ethermint. {synopsis}
## Pre-requisite Readings
- [Geth JSON-RPC Namespaces](https://geth.ethereum.org/docs/rpc/server) {prereq}
## Ethereum Namespaces
| Namespace | Description | Supported | Enabled by Default |
|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|--------------------|
| [`eth`](./endpoints.md#eth-methods) | Ethermint provides several extensions to the standard `eth` JSON-RPC namespace. | ✔ | ✔ |
| [`web3`](./endpoints.md#web3-methods) | The `web3` API provides utility functions for the web3 client. | ✔ | ✔ |
| [`net`](./endpoints.md#net-methods) | The `net` API provides access to network information of the node | ✔ | ✔ |
| `clique` | The `clique` API provides access to the state of the clique consensus engine. You can use this API to manage signer votes and to check the health of a private network. | ❌ | |
| `debug` | The `debug` API gives you access to several non-standard RPC methods, which will allow you to inspect, debug and set certain debugging flags during runtime. | ✔ | |
| `les` | The `les` API allows you to manage LES server settings, including client parameters and payment settings for prioritized clients. It also provides functions to query checkpoint information in both server and client mode. | ❌ | |
| [`miner`](./endpoints.md#miner-methods) | The `miner` API allows you to remote control the nodes mining operation and set various mining specific settings. | ✔ | ❌ |
| [`txpool`](./endpoints.md#txpool-methods) | The `txpool` API gives you access to several non-standard RPC methods to inspect the contents of the transaction pool containing all the currently pending transactions as well as the ones queued for future processing. | ✔ | ❌ |
| `admin` | The `admin` API gives you access to several non-standard RPC methods, which will allow you to have a fine grained control over your nodeinstance, including but not limited to network peer and RPC endpoint management. | ❌ | |
| [`personal`](./endpoints.md#personal-methods) | The `personal` API manages private keys in the key store. | ✔ | ❌ |
+54
View File
@@ -0,0 +1,54 @@
<!--
order: 2
-->
# Running the Server
Learn how to run and setup the JSON-RPC server on Ethermint. {synopsis}
## Enable Server
To enable RPC server use the following flag (set to true by default).
```bash
ethermintd start --json-rpc.enable
```
## Defining Namespaces
`Eth`,`Net` and `Web3` [namespaces](./namespaces) are enabled by default. In order to enable other namespaces use flag `--json-rpc.api`.
```bash
ethermintd start --json-rpc.api eth,txpool,personal,net,debug,web3,miner
```
## Set a Gas Cap
`eth_call` and `eth_estimateGas` define a global gas cap over rpc for DoS protection. You can override the default gas cap value of 25,000,000 by passing a custom value when starting the node:
```bash
# set gas cap to 85M
ethermintd start --json-rpc.gas-cap 85000000000
# set gas cap to infinite (=0)
ethermintd start --json-rpc.gas-cap 0
```
## CORS
If accessing the RPC from a browser, CORS will need to be enabled with the appropriate domain set. Otherwise, JavaScript calls are limit by the same-origin policy and requests will fail.
The CORS setting can be updated from the `app.toml`
```toml
###############################################################################
### API Configuration ###
###############################################################################
[api]
# ...
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
enabled-unsafe-cors = true # default false
```
+73
View File
@@ -0,0 +1,73 @@
<!--
order: 1
-->
# JSON-RPC Server
Learn about the JSON-RPC server to interact with the EVM. {synopsis}
## Pre-requisite Readings
- [EthWiki JSON-RPC API](https://eth.wiki/json-rpc/API) {prereq}
- [Geth JSON-RPC Server](https://geth.ethereum.org/docs/rpc/server) {prereq}
## JSON-RPC API
[JSON](https://json.org/) is a lightweight data-interchange format. It can represent numbers, strings, ordered sequences of values, and collections of name/value pairs.
[JSON-RPC](http://www.jsonrpc.org/specification) is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this specification defines several data structures and the rules around their processing. It is transport agnostic in that the concepts can be used within the same process, over sockets, over HTTP, or in many various message passing environments. It uses JSON ([RFC 4627](https://www.ietf.org/rfc/rfc4627.txt)) as data format.
## JSON-RPC Support
Ethermint supports all standard web3 JSON-RPC APIs. You can find documentation for these APIs on the [`JSON-RPC Methods`](./endpoints.md) page.
JSON-RPC is provided on multiple transports. Ethermint supports JSON-RPC over HTTP and WebSocket. Transports must be enabled through command-line flags or through the `app.toml` configuration file. For more details see the []
Ethereum JSON-RPC APIs use a name-space system. RPC methods are grouped into several categories depending on their purpose. All method names are composed of the namespace, an underscore, and the actual method name within the namespace. For example, the eth_call method resides in the eth namespace.
Access to RPC methods can be enabled on a per-namespace basis. Find documentation for individual namespaces in the [Namespaces](./namespaces.md) page.
## HEX value encoding
At present there are two key datatypes that are passed over JSON: unformatted byte arrays and quantities. Both are passed with a hex encoding, however with different requirements to formatting:
When encoding **QUANTITIES** (integers, numbers): encode as hex, prefix with `"0x"`, the most compact representation (slight exception: zero should be represented as `"0x0"`). Examples:
- `0x41` (65 in decimal)
- `0x400` (1024 in decimal)
- WRONG: `0x` (should always have at least one digit - zero is `"0x0"`)
- WRONG: `0x0400` (no leading zeroes allowed)
- WRONG: `ff` (must be prefixed `0x`)
When encoding **UNFORMATTED DATA** (byte arrays, account addresses, hashes, bytecode arrays): encode as hex, prefix with `"0x"`, two hex digits per byte. Examples:
- `0x41` (size 1, `"A"`)
- `0x004200` (size 3, `"\0B\0"`)
- `0x` (size 0, `""`)
- WRONG: `0xf0f0f` (must be even number of digits)
- WRONG: `004200` (must be prefixed `0x`)
## Default block parameter
The following methods have an extra default block parameter:
- [`eth_getBalance`](./endpoints.md#eth-getbalance)
- [`eth_getCode`](./endpoints.md#eth-getcode)
- [`eth_getTransactionCount`](./endpoints.md#eth-gettransactioncount)
- [`eth_getStorageAt`](./endpoints.md#eth-getstorageat)
- [`eth_call`](./endpoints.md#eth-call)
When requests are made that act on the state of Ethermint, the last default block parameter determines the height of the block.
The following options are possible for the `defaultBlock` parameter:
- `HEX String` - an integer block number
- `String "earliest"` for the earliest/genesis block
- `String "latest"` - for the latest mined block
- `String "pending"` - for the pending state/transactions
## Curl Examples Explained
The curl options below might return a response where the node complains about the content type, this is because the `--data` option sets the content type to `application/x-www-form-urlencoded`. If your node does complain, manually set the header by placing `-H "Content-Type: application/json"` at the start of the call.
The examples also do not include the URL/IP & port combination which must be the last argument given to curl e.x. `127.0.0.1:8545`
+206 -687
View File
File diff suppressed because it is too large Load Diff
-56
View File
@@ -1,56 +0,0 @@
# ADR Creation Process
1. Copy the `adr-template.md` file. Use the following filename pattern: `adr-next_number-title.md`
2. Create a draft Pull Request if you want to get an early feedback.
3. Make sure the context and a solution is clear and well documented.
4. Add an entry to a list in the [README](./README.md) file.
5. Create a Pull Request to propose a new ADR.
## ADR life cycle
ADR creation is an **iterative** process. Instead of trying to solve all decisions in a single ADR pull request, we MUST firstly understand the problem and collect feedback through a GitHub Issue.
1. Every proposal SHOULD start with a new GitHub Issue or be a result of existing Issues. The Issue should contain just a brief proposal summary.
2. Once the motivation is validated, a GitHub Pull Request (PR) is created with a new document based on the `adr-template.md`.
3. An ADR doesn't have to arrive to `master` with an _accepted_ status in a single PR. If the motivation is clear and the solution is sound, we SHOULD be able to merge it and keep a _proposed_ status. It's preferable to have an iterative approach rather than long, not merged Pull Requests.
4. If a _proposed_ ADR is merged, then it should clearly document outstanding issues either in ADR document notes or in a GitHub Issue.
5. The PR SHOULD always be merged. In the case of a faulty ADR, we still prefer to merge it with a _rejected_ status. The only time the ADR SHOULD NOT be merged is if the author abandons it.
6. Merged ADRs SHOULD NOT be pruned.
### ADR status
Status has two components:
```
{CONSENSUS STATUS} {IMPLEMENTATION STATUS}
```
IMPLEMENTATION STATUS is either `Implemented` or `Not Implemented`.
#### Consensus Status
```
DRAFT -> PROPOSED -> LAST CALL yyyy-mm-dd -> ACCEPTED | REJECTED -> SUPERSEDED by ADR-xxx
\ |
\ |
v v
ABANDONED
```
+ `DRAFT`: [optional] an ADR which is work in progress, not being ready for a general review. This is to present an early work and get an early feedback in a Draft Pull Request form.
+ `PROPOSED`: an ADR covering a full solution architecture and still in the review - project stakeholders haven't reached an agreed yet.
+ `LAST CALL <date for the last call>`: [optional] clear notify that we are close to accept updates. Changing a status to `LAST CALL` means that social consensus (of Cosmos SDK maintainers) has been reached and we still want to give it a time to let the community react or analyze.
+ `ACCEPTED`: ADR which will represent a currently implemented or to be implemented architecture design.
+ `REJECTED`: ADR can go from PROPOSED or ACCEPTED to rejected if the consensus among project stakeholders will decide so.
+ `SUPERSEEDED by ADR-xxx`: ADR which has been superseded by a new ADR.
+ `ABANDONED`: the ADR is no longer pursued by the original authors.
## Language used in ADR
+ The context/background should be written in the present tense.
+ Avoid using a first, personal form.
+1 -1
View File
@@ -210,4 +210,4 @@ Later, this section can optionally list ideas or improvements the author or revi
<!-- - {reference link} -->
- [Hooks in staking module](https://docs.cosmos.network/master/modules/staking/06_hooks.html)
- [Hooks in staking module](https://docs.cosmos.network/v0.43/modules/staking/06_hooks.html)
+17
View File
@@ -0,0 +1,17 @@
<!--
order: false
parent:
order: 3
-->
# Basics
This repository contains reference documentation on the basic concepts of Ethermint.
1. [Chain ID](./chain_id.md)
1. [Accounts](./accounts.md)
1. [Gas and Fees](./gas.md)
1. [Lifecycle of a transaction](./transactions.md)
1. [Tokens](./tokens.md)
After reading the basics, head on to the [Core Reference](../core/README.md) for more advanced material.
+168
View File
@@ -0,0 +1,168 @@
<!--
order: 2
-->
# Accounts
This document describes the in-built accounts system of Ethermint. {synopsis}
## Pre-requisite Readings
- [Cosmos SDK Accounts](https://docs.cosmos.network/master/basics/accounts.html) {prereq}
- [Ethereum Accounts](https://ethereum.org/en/whitepaper/#ethereum-accounts) {prereq}
## Ethermint Accounts
Ethermint defines its own custom `Account` type that uses Ethereum's ECDSA secp256k1 curve for keys. This
satisfies the [EIP84](https://github.com/ethereum/EIPs/issues/84) for full [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) paths.
The root HD path for Ethermint-based accounts is `m/44'/60'/0'/0`.
+++ https://github.com/tharsis/ethermint/blob/main/types/account.pb.go#L28-L33
## Addresses and Public Keys
[BIP-0173](https://github.com/satoshilabs/slips/blob/master/slip-0173.md) defines a new format for segregated witness output addresses that contains a human-readable part that identifies the Bech32 usage. Ethermint uses the following HRP (human readable prefix) as the base HRP:
| Network | Mainnet | Testnet | Regtest |
|-----------|---------|---------|---------|
| Ethermint | `ethm` | `ethm` | |
There are 3 main types of HRP for the `Addresses`/`PubKeys` available by default on Ethermint:
- Addresses and Keys for **accounts**, which identify users (e.g. the sender of a `message`). They are derived using the **`eth_secp256k1`** curve.
- Addresses and Keys for **validator operators**, which identify the operators of validators. They are derived using the **`eth_secp256k1`** curve.
- Addresses and Keys for **consensus nodes**, which identify the validator nodes participating in consensus. They are derived using the **`ed25519`** curve.
| | Address bech32 Prefix | Pubkey bech32 Prefix | Curve | Address byte length | Pubkey byte length |
|--------------------|-----------------------|----------------------|-----------------|---------------------|--------------------|
| Accounts | `ethm` | `ethmpub` | `eth_secp256k1` | `20` | `33` (compressed) |
| Validator Operator | `ethmvaloper` | `ethmvaloperpub` | `eth_secp256k1` | `20` | `33` (compressed) |
| Consensus Nodes | `ethmvalcons` | `ethmvalconspub` | `ed25519` | `20` | `32` |
## Address formats for clients
`EthAccount` can be represented in both [Bech32](https://en.bitcoin.it/wiki/Bech32) (`ethm1...`) and hex (`0x...`) formats for Ethereum's Web3 tooling compatibility.
The Bech32 format is the default format for Cosmos-SDK queries and transactions through CLI and REST
clients. The hex format on the other hand, is the Ethereum `common.Address` representation of a
Cosmos `sdk.AccAddress`.
- **Address (Bech32)**: `ethm1j800cll9vq7l4rxfke2u74mjgkdlzrr0r5mu97`
- **Address ([EIP55](https://eips.ethereum.org/EIPS/eip-55) Hex)**: `0x91defC7fE5603DFA8CC9B655cF5772459BF10c6f`
- **Compressed Public Key**: `{"@type":"/ethermint.crypto.v1.ethsecp256k1.PubKey","key":"Aq9WtHGKtvX523b2ptvimGVfp3hZ1GDxVdINYWBM9+Gy"}`
### Address conversion
The `ethermintd debug addr <address>` can be used to convert an address between hex and bech32 formats. For example:
:::: tabs
::: tab Bech32
```bash
ethermintd debug addr ethm10jmp6sgh4cc6zt3e8gw05wavvejgr5pwtu750w
Address bytes: [124 182 29 65 23 174 49 161 46 57 58 28 250 59 172 102 100 129 208 46]
Address (hex): 7CB61D4117AE31A12E393A1CFA3BAC666481D02E
Address (EIP-55): 0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E
Bech32 Acc: ethm10jmp6sgh4cc6zt3e8gw05wavvejgr5pwtu750w
Bech32 Val: ethmvaloper10jmp6sgh4cc6zt3e8gw05wavvejgr5pwyv5chn
```
:::
::: tab Hex
```bash
ethermintd debug addr 0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E
Address bytes: [124 182 29 65 23 174 49 161 46 57 58 28 250 59 172 102 100 129 208 46]
Address (hex): 7CB61D4117AE31A12E393A1CFA3BAC666481D02E
Address (EIP-55): 0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E
Bech32 Acc: ethm10jmp6sgh4cc6zt3e8gw05wavvejgr5pwtu750w
Bech32 Val: ethmvaloper10jmp6sgh4cc6zt3e8gw05wavvejgr5pwyv5chn
```
:::
::::
### Key output
::: tip
The Cosmos SDK Keyring output (i.e `ethermintd keys`) only supports addresses and public keys in Bech32 format.
:::
We can use the `keys show` command of `ethermintd` with the flag `--bech <type> (acc|val|cons)` to
obtain the addresses and keys as mentioned above,
:::: tabs
::: tab Account
```bash
ethermintd keys show mykey --bech acc
- name: mykey
type: local
address: ethm1qsklxwt77qrxur494uvw07zjynu03dq9alwh37
pubkey: '{"@type":"/ethermint.crypto.v1.ethsecp256k1.PubKey","key":"A8nbJ3eW9oAb2RNZoS8L71jFMfjk6zVa1UISYgKK9HPm"}'
mnemonic: ""
```
:::
::: tab Validator
```bash
ethermintd keys show test --bech val
- name: mykey
type: local
address: ethmvaloper1qsklxwt77qrxur494uvw07zjynu03dq9rdsrlq
pubkey: '{"@type":"/ethermint.crypto.v1.ethsecp256k1.PubKey","key":"A8nbJ3eW9oAb2RNZoS8L71jFMfjk6zVa1UISYgKK9HPm"}'
mnemonic: ""
```
:::
::: tab Consensus
```bash
ethermintd keys show test --bech cons
- name: mykey
type: local
address: ethmvalcons1qsklxwt77qrxur494uvw07zjynu03dq9h7rlnp
pubkey: '{"@type":"/ethermint.crypto.v1.ethsecp256k1.PubKey","key":"A8nbJ3eW9oAb2RNZoS8L71jFMfjk6zVa1UISYgKK9HPm"}'
mnemonic: ""
```
:::
::::
## Querying an Account
You can query an account address using the CLI, gRPC or
### Command Line Interface
```bash
# NOTE: the --output (-o) flag will define the output format in JSON or YAML (text)
ethermintd q auth account $(ethermintd keys show <MYKEY> -a) -o text
|
'@type': /ethermint.types.v1beta1.EthAccount
base_account:
account_number: "3"
address: inj14au322k9munkmx5wrchz9q30juf5wjgz2cfqku
pub_key: null
sequence: "0"
code_hash: xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=
```
### Cosmos gRPC and REST
``` bash
# GET /cosmos/auth/v1beta1/accounts/{address}
curl -X GET "http://localhost:10337/cosmos/auth/v1beta1/accounts/ethm14au322k9munkmx5wrchz9q30juf5wjgz2cfqku" -H "accept: application/json"
```
### JSON-RPC
To retrieve the Ethereum hex address using Web3, use the JSON-RPC [`eth_accounts`](./../api/json-rpc/endpoints.md#eth-accounts) or [`personal_listAccounts`](./../api/json-rpc/endpoints#personal-listAccounts.md) endpoints:
```bash
# query against a local node
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params":[],"id":1}' -H "Content-Type: application/json" http://localhost:8545
curl -X POST --data '{"jsonrpc":"2.0","method":"personal_listAccounts","params":[],"id":1}' -H "Content-Type: application/json" http://localhost:8545
```
+38
View File
@@ -0,0 +1,38 @@
<!--
order: 1
-->
# Chain ID
Learn about the Ethermint chain-id format {synopsis}
## The Chain Identifier
Every chain must have a unique identifier or `chain-id`. Tendermint requires each application to
define its own `chain-id` in the [genesis.json fields](https://docs.tendermint.com/master/spec/core/genesis.html#genesis-fields). However, in order to comply with both EIP155 and Cosmos standard for chain upgrades, Ethermint-compatible chains must implement a special structure for their chain identifiers.
## Structure
The Ethermint Chain ID contains 3 main components
- **Identifier**: Unstructured string that defines the name of the application.
- **EIP155 Number**: Immutable [EIP155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) `CHAIN_ID` that defines the replay attack protection number.
- **Version Number**: Is the version number (always positive) that the chain is currently running.
This number **MUST** be incremented every time the chain is upgraded or forked in order to avoid network or consensus errors.
### Format
The format for specifying and Ethermint compatible chain-id in genesis is the following:
```bash
{identifier}_{EIP155}-{version}
```
The following table provides an example where the second row corresponds to an upgrade from the first one:
| ChainID | Identifier | EIP155 Number | Version Number |
|--------------------|------------|---------------|----------------|
| `ethermint_9000-1` | ethermint | 9000 | 1 |
| `ethermint_9000-2` | ethermint | 9000 | 2 |
| `...` | ... | ... | ... |
| `ethermint_9000-N` | ethermint | 9000 | N |
+96
View File
@@ -0,0 +1,96 @@
<!--
order: 4
-->
# Gas and Fees
Learn about the differences between `Gas` and `Fees` in Ethereum and Cosmos. {synopsis}
## Pre-requisite Readings
- [Cosmos SDK Gas](https://docs.cosmos.network/master/basics/gas-fees.html) {prereq}
- [Ethereum Gas](https://ethereum.org/en/developers/docs/gas/) {prereq}
The concept of Gas represents the amount of computational effort required to execute specific operations on the state machine.
Gas was created on Ethereum to disallow the EVM (Ethereum Virtual Machine) from running infinite
loops by allocating a small amount of monetary value into the system. A unit of gas, usually in a
form as a fraction of the native coin, is consumed for every operation on the EVM and requires a
user to pay for these operations. These operations consist in state transitions such as sending a
transaction or calling a contract.
Exactly like Ethereum, Cosmos utilizes the concept of gas and this is how Cosmos tracks the resource
usage of operations during execution. Operations on Cosmos are represented as read or writes done to the chain's store.
In Cosmos, a fee is calculated and charged to the user during a message execution. This fee is
calculated from the sum of all gas consumed in an message execution:
$$fee = gas ~ * ~ gasPrice$$
In both networks, gas is used to make sure that operations do not require an excess amount of
computational power to complete and as a way to deter bad-acting users from spamming the network.
## Cosmos SDK `Gas`
In the Cosmos SDK, gas is tracked in the main `GasMeter` and the `BlockGasMeter`:
- `GasMeter`: keeps track of the gas consumed during executions that lead to state transitions. It is reset on every transaction execution.
- `BlockGasMeter`: keeps track of the gas consumed in a block and enforces that the gas does not go over a predefined limit. This limit is defined in the Tendermint consensus parameters and can be changed via governance parameter change proposals.
More information regarding gas in Cosmos SDK can be found [here](https://docs.cosmos.network/master/basics/gas-fees.html).
## Matching EVM Gas consumption
Ethermint is an EVM-compatible chain that supports Ethereum Web3 tooling. For this reason, gas
consumption must be equitable with other EVMs, most importantly Ethereum.
The main difference between EVM and Cosmos state transitions, is that the EVM uses a [gas table](https://github.com/ethereum/go-ethereum/blob/master/params/protocol_params.go) for each OPCODE, whereas Cosmos uses a `GasConfig` that charges gas for each CRUD operation by setting a flat and per-byte cost for accessing the database.
+++ https://github.com/cosmos/cosmos-sdk/blob/3fd376bd5659f076a4dc79b644573299fd1ec1bf/store/types/gas.go#L187-L196
In order to match the the gas consumed by the EVM, the gas consumption logic from the SDK is ignored, and instead the gas consumed is calculated by subtracting the state transition leftover gas plus refund from the gas limit defined on the message.
To ignore the SDK gas consumption, we reset the transaction `GasMeter` count to 0 and manually set it to the `gasUsed` value computed by the EVM module at the end of the execution.
+++ https://github.com/tharsis/ethermint/blob/098da6d0cc0e0c4cefbddf632df1057383973e4a/x/evm/keeper/state_transition.go#L188
### `AnteHandler`
The Cosmos SDK [`AnteHandler`](https://docs.cosmos.network/master/basics/gas-fees.html#antehandler)
performs basic checks prior to transaction execution. These checks are usually signature
verification, transaction field validation, transaction fees, etc.
Regarding gas consumption and fees, the `AnteHandler` checks that the user has enough balance to
cover for the tx cost (amount plus fees) as well as checking that the gas limit defined in the
message is greater or equal than the computed intrinsic gas for the message.
## Gas Refunds
In the EVM, gas can be specified prior to execution. The totality of the gas specified is consumed at the beginning of the execution (during the `AnteHandler` step) and the remaining gas is refunded back to
the user if any gas is left over after the execution. Additionally the EVM can also define gas to be refunded back to the user but those will be capped to a fraction of the used gas depending on the fork/version being used.
## 0 Fee Transactions
In Cosmos, a minimum gas price is not enforced by the `AnteHandler` as the `min-gas-prices` is
checked against the local node/validator. In other words, the minimum fees accepted are determined
by the validators of the network, and each validator can specify a different minimum value for their fees.
This potentially allows end users to submit 0 fee transactions if there is at least one single
validator that is willing to include transactions with `0` gas price in their blocks proposed.
For this same reason, in Ethermint it is possible to send transactions with `0` fees for transaction
types other than the ones defined by the `evm` module. EVM module transactions cannot have `0` fees
as gas is required inherently by the EVM. This check is done by the EVM transactions stateless validation
(i.e `ValidateBasic`) function as well as on the custom `AnteHandler` defined by Ethermint.
## Gas estimation
Ethereum provides a JSON-RPC endpoint `eth_estimateGas` to help users set up a correct gas limit in their transactions.
Unfortunately, we cannot make use of the SDK `tx simulation` for gas estimation because the pre-check in the Ante Handlers would require a valid signature, and the sender balance to be enough to pay for the gas. But in Ethereum, this endpoint can be called without specifying any sender address.
For that reason, a specific query API `EstimateGas` is implemented in Ethermint. It will apply the transaction against the current block/state and perform a binary search in order to find the optimal gas value to return to the user (the same transaction will be applied over and over until we find the minimum gas needed before it fails). The reason we need to use a binary search is that the gas required for the
transaction might be higher than the value returned by the EVM after applying the transaction, so we need to try until we find the optimal value.
A cache context will be used during the whole execution to avoid changes be persisted in the state.
+++ https://github.com/tharsis/ethermint/blob/098da6d0cc0e0c4cefbddf632df1057383973e4a/x/evm/keeper/grpc_query.go#L100
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+32
View File
@@ -0,0 +1,32 @@
<!--
order: 5
-->
# Tokens
Learn about the the different types of tokens available in Ethermint. {synopsis}
## Introduction
Ethermint is a Cosmos SDK-based chain with full EVM support. Because of this architecture, tokens and assets in the network may come from different independent sources: the `bank` module and the `evm` module.
## Cosmos Coins
Accounts can own SDK coins in their balance, which are used for operations with other Cosmos modules and transactions. Examples of these are using the coins for staking, IBC transfers, governance deposits and EVM
### Photon
The denomination used for staking, governance and gas consumption on the EVM is the Photon. The Photon provides the utility of: securing the Proof-of-Stake chain, token used for governance proposals, fee distribution and as a mean of gas for running smart contracts on the EVM.
Ethermint uses [Atto](https://en.wikipedia.org/wiki/Atto-) Photon as the base denomination to maintain parity with Ethereum.
$$1 photon = 1 ~ * ~ 10^{18} aphoton$$
This matches Ethereum denomination of:
$$1 ETH = 1 ~ * ~ 10^{18} wei$$
### EVM Tokens
Ethermint is compatible with ERC20 tokens and other non-fungible token standards (EIP721, EIP1155)
that are natively supported by the EVM.
+40
View File
@@ -0,0 +1,40 @@
<!--
order: 3
-->
# Transaction Lifecycle
This document describes the lifecycle of a transaction from creation to committed state changes on the EVM. {synopsis}
## Pre-requisite Readings
- [SDK transaction lifecycle](https://docs.cosmos.network/master/basics/tx-lifecycle.html) {prereq}
<!-- TODO: rewrite. This is not a lifecycle doc -->
## Routing
Ethermint needs to parse and handle transactions routed for both the EVM and for Cosmos SDK modules. We
attempt to achieve this by mimicking [geth's](https://github.com/ethereum/go-ethereum) `Transaction`
structure and treat it as a unique Cosmos SDK message type. An Ethereum transaction is a single
[`sdk.Msg`](https://godoc.org/github.com/cosmos/cosmos-sdk/types#Msg). All relevant Ethereum
transaction information is contained in this message. This includes the signature, gas, payload,
amount, etc.
Being that Ethermint implements the Tendermint ABCI application interface, as transactions are
consumed, they are passed through a series of handlers. Once such handler, the `AnteHandler`, is
responsible for performing preliminary message execution business logic such as fee payment,
signature verification, etc. This is particular to Cosmos SDK routed transactions. Ethereum routed
transactions will bypass this as the EVM handles the same business logic.
All EVM transactions are [RLP](./../core/encoding.md#rlp) encoded using a custom tx encoder.
## Signers
The signature processing and verification in Ethereum is performed by the `Signer` interface. The
protocol supports different signer types based on the chain configuration params and the block number.
+++ https://github.com/ethereum/go-ethereum/blob/v1.10.3/core/types/transaction_signing.go#L145-L166
Ethermint supports all Ethereum `Signer`s up to the latest go-ethereum version (London, Berlin,
EIP155, Homestead and Frontier). The chain will generate the latest `Signer` type depending on the
`ChainConfig`.
+14
View File
@@ -0,0 +1,14 @@
<!--
order: false
parent:
order: 4
-->
# Core Concepts
This repository contains reference documentation on the core concepts of Ethermint.
1. [Encoding](./encoding.md)
2. [Pending State](./pending_state.md)
After reading the core concepts, head on to the [guides](../guides/README.md) to learn how to use Ethereum tooling with Ethermint.
+69
View File
@@ -0,0 +1,69 @@
<!--
order: 1
-->
# Encoding
Learn about the encoding formats used on Ethermint. {synopsis}
## Pre-requisite Readings
- [Cosmos SDK Encoding](https://docs.cosmos.network/master/core/encoding.html) {prereq}
- [Ethereum RLP](https://eth.wiki/en/fundamentals/rlp) {prereq}
## Encoding Formats
### Protocol Buffers
The Cosmos [Stargate](https://stargate.cosmos.network/) release introduces
[protobuf](https://developers.google.com/protocol-buffers) as the main encoding format for both
client and state serialization. All the EVM module types that are used for state and clients
(transaction messages, genesis, query services, etc) will be implemented as protocol buffer messages.
### Amino
The Cosmos SDK also supports the legacy Amino encoding format for backwards compatibility with
previous versions, specially for client encoding and signing with Ledger devices. Ethermint does not
support Amino in the EVM module, but it is supported for all other Cosmos SDK modules that enable it.
### RLP
Recursive Length Prefix ([RLP](https://eth.wiki/en/fundamentals/rlp)), is an encoding/decoding algorithm that serializes a message and
allows for quick reconstruction of encoded data. Ethermint uses RLP to encode/decode Ethereum
messages for JSON-RPC handling to conform messages to the proper Ethereum format. This allows
messages to be encoded and decoded in the exact format as Ethereum's.
The `x/evm` transactions (`MsgEthereumTx`) encoding is performed by casting the message to a go-ethereum's `Transaction` and then marshaling the transaction data using RLP:
```go
// TxEncoder overwrites sdk.TxEncoder to support MsgEthereumTx
func (g txConfig) TxEncoder() sdk.TxEncoder {
return func(tx sdk.Tx) ([]byte, error) {
msg, ok := tx.(*evmtypes.MsgEthereumTx)
if ok {
return msg.AsTransaction().MarshalBinary()
}
return g.TxConfig.TxEncoder()(tx)
}
}
// TxDecoder overwrites sdk.TxDecoder to support MsgEthereumTx
func (g txConfig) TxDecoder() sdk.TxDecoder {
return func(txBytes []byte) (sdk.Tx, error) {
tx := &ethtypes.Transaction{}
err := tx.UnmarshalBinary(txBytes)
if err == nil {
msg := &evmtypes.MsgEthereumTx{}
msg.FromEthereumTx(tx)
return msg, nil
}
return g.TxConfig.TxDecoder()(txBytes)
}
}
```
## Next {hide}
Learn how [pending state](./pending_state.md) is handled on Ethermint. {hide}
+49
View File
@@ -0,0 +1,49 @@
<!--
order: 2
-->
# Pending State
Learn how Ethermint handles pending state queries. {synopsis}
## Pre-requisite Readings
- [Tendermint Mempool](https://docs.tendermint.com/master/tendermint-core/mempool.htm) {prereq}
## Ethermint vs Ethereum
In Ethereum, pending blocks are generated as they are queued for production by miners. These pending
blocks include pending transactions that are picked out by miners, based on the highest reward paid
in gas. This mechanism exists as block finality is not possible on the Ethereum network. Blocks are
committed with probabilistic finality, which means that transactions and blocks become less likely
to become reverted as more time (and blocks) passes.
Ethermint is designed quite differently on this front as there is no concept of a "pending state".
Ethermint uses [Tendermint Core](https://docs.tendermint.com/) BFT consensus which provides instant
finality for transaction. For this reason, Etheremint does not require a pending state mechanism, as
all (if not most) of the transactions will be committed to the next block (avg. block time on Cosmos chains is ~8s). However, this causes a
few hiccups in terms of the Ethereum Web3-compatible queries that can be made to pending state.
Another significant difference with Ethereum, is that blocks are produced by validators or block producers, who include transactions from their local mempool into blocks in a
first-in-first-out (FIFO) fashion. Transactions on Ethermint cannot be ordered or cherry picked out from the Tendermint node [mempool](https://docs.tendermint.com/master/tendermint-core/mempool.html#transaction-ordering).
## Pending State Queries
Ethermint will make queries which will account for any unconfirmed transactions present in a node's
transaction mempool. A pending state query made will be subjective and the query will be made on the
target node's mempool. Thus, the pending state will not be the same for the same query to two
different nodes.
### JSON-RPC Calls on Pending Transactions
- [`eth_getBalance`](./../api/json-rpc/endpoints.md#eth_getbalance)
- [`eth_getTransactionCount`](./../api/json-rpc/endpoints.md#eth-gettransactioncount)
- [`eth_getBlockTransactionCountByNumber`](./../api/json-rpc/endpoints.md#eth-getblocktransactioncountbynumber)
- [`eth_getBlockByNumber`](./../api/json-rpc/endpoints.md#eth-getblockbynumber)
- [`eth_getTransactionByHash`](./../api/json-rpc/endpoints.md#eth-gettransactionbyhash)
- [`eth_getTransactionByBlockNumberAndIndex`](./../api/json-rpc/endpoints.html#eth-gettransactionbyblockhashandindex)
- [`eth_sendTransaction`](./../api/json-rpc/endpoints.md#eth-sendtransaction)
## Next {hide}
Learn how to deploy a Solidity smart contract on Ethermint using [Truffle](./../guides/truffle.md) {hide}
+59
View File
@@ -0,0 +1,59 @@
# Snapshot and Revert in Ethermint
EVM uses state-reverting exceptions to handle errors. Such an exception will undo all changes made to the state in the current call (and all its sub-calls), and the caller could handle the error and don't propagate. We need to implement the `Snapshot` and `RevertToSnapshot` apis in `StateDB` interfaces to support this feature.
[go-ethereum implementation](https://github.com/ethereum/go-ethereum/blob/master/core/state/journal.go#L39) manages transient states in memory, and uses a list of journal logs to record all the state modification operations done so far, snapshot is an index in the log list, and to revert to a snapshot it just undo the journal logs after the snapshot index in reversed order.
Ethermint uses cosmos-sdk's storage api to manage states, fortunately the storage api supports creating cached overlays, it works like this:
```golang
// create a cached overlay storage on top of ctx storage.
overlayCtx, commit := ctx.CacheContext()
// Modify states using the overlayed storage
err := doCall(overlayCtx)
if err != nil {
return err
}
// commit will write the dirty states into the underlying storage
commit()
// Now, just drop the overlayCtx and keep using ctx
```
And it can be used in a nested way, like this:
```golang
overlayCtx1, commit1 := ctx.CacheContext()
doCall1(overlayCtx1)
{
overlayCtx2, commit2 := overlayCtx1.CacheContext()
doCall2(overlayCtx2)
commit2()
}
commit1()
```
With this feature, we can use a stake of overlayed contexts to implement nested `Snapshot` and `RevertToSnapshot` calls.
```golang
type cachedContext struct {
ctx sdk.Context
commit func()
}
var contextStack []cachedContext
func Snapshot() int {
ctx, commit := contextStack.Top().CacheContext()
contextStack.Push(cachedContext{ctx, commit})
return len(contextStack) - 1
}
func RevertToSnapshot(int snapshot) {
contextStack = contextStack[:snapshot]
}
func Commit() {
for i := len(contextStack) - 1; i >= 0; i-- {
contextStack[i].commit()
}
contextStack = {}
}
```
+20
View File
@@ -0,0 +1,20 @@
<!--
order: false
parent:
order: 5
-->
# Guides
1. Localnet
* [Single Node Localnet](./localnet/single_node)
* [Multi Node Localnet](./localnet/multi_node)
2. Keys and Wallets
* [Keyring](./keys-wallets/keyring)
* [MetaMask](./keys-wallets/metamask)
3. Ethereum Tooling
* [Remix](./tools/remix)
* [Hardhat](./tools/hardhat)
* [Truffle](./tools/truffle)
4. [Validators](./validators/overview)
5. [Key Management System](./kms/kms)

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