Merge remote-tracking branch 'origin' into murali/attribute-typing
This commit is contained in:
commit
a7aa9dae16
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
id: git_diff
|
||||
with:
|
||||
|
28
.github/workflows/docker-image.yml
vendored
Normal file
28
.github/workflows/docker-image.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: Publish onn release
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
jobs:
|
||||
build:
|
||||
name: Run docker build and publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run docker build
|
||||
run: docker build -t cerc-io/laconicd -f Dockerfile .
|
||||
- name: Get the version
|
||||
id: vars
|
||||
run: |
|
||||
echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
|
||||
echo ::set-output name=tag::$(echo ${GITHUB_REF#refs/tags/})
|
||||
- name: Tag docker image
|
||||
run: docker tag cerc-io/laconicd git.vdb.to/cerc-io/laconicd/laconicd:${{steps.vars.outputs.sha}}
|
||||
- name: Tag docker image
|
||||
run: docker tag git.vdb.to/cerc-io/laconicd/laconicd:${{steps.vars.outputs.sha}} git.vdb.to/cerc-io/laconicd/laconicd:${{steps.vars.outputs.tag}}
|
||||
- name: Docker Login
|
||||
run: echo ${{ secrets.GITEA_TOKEN }} | docker login https://git.vdb.to -u cerccicd --password-stdin
|
||||
- name: Docker Push
|
||||
run: docker push git.vdb.to/cerc-io/laconicd/laconicd:${{steps.vars.outputs.sha}}
|
||||
- name: Docker Push TAGGED
|
||||
run: docker push git.vdb.to/cerc-io/laconicd/laconicd:${{steps.vars.outputs.tag}}
|
||||
|
4
.github/workflows/goreleaser.yml
vendored
4
.github/workflows/goreleaser.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
- name: release dry run
|
||||
run: make release-dry-run
|
||||
- name: setup release environment
|
||||
@ -24,4 +24,4 @@ jobs:
|
||||
run: |-
|
||||
echo 'GITHUB_TOKEN=${{secrets.GITHUB_TOKEN}}' > .release-env
|
||||
- name: release publish
|
||||
run: make release
|
||||
run: make release
|
||||
|
18
.github/workflows/lint.yml
vendored
18
.github/workflows/lint.yml
vendored
@ -13,17 +13,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
- uses: technote-space/get-diff-action@v6.1.0
|
||||
with:
|
||||
SUFFIX_FILTER: |
|
||||
.go
|
||||
.mod
|
||||
.sum
|
||||
- uses: golangci/golangci-lint-action@v2.5.2
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- uses: golangci/golangci-lint-action@v3
|
||||
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.48.0
|
||||
args: --timeout 10m
|
||||
github-token: ${{ secrets.github_token }}
|
||||
# Check only if there are differences in the source code
|
||||
|
4
.github/workflows/security.yml
vendored
4
.github/workflows/security.yml
vendored
@ -21,10 +21,10 @@ jobs:
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Run Gosec Security Scanner
|
||||
uses: informalsystems/gosec@master
|
||||
uses: cosmos/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 ./...'
|
||||
args: '-no-fail -fmt sarif -out results.sarif -exclude=G701,G703 ./...'
|
||||
if: "env.GIT_DIFF_FILTERED != ''"
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
|
238
.github/workflows/test.yml
vendored
238
.github/workflows/test.yml
vendored
@ -15,33 +15,17 @@ jobs:
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'"
|
||||
|
||||
install-tparse:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v2.1.4
|
||||
with:
|
||||
go-version: 1.17
|
||||
- name: Display Go Version
|
||||
run: go version
|
||||
- name: Install tparse
|
||||
run: |
|
||||
export GO111MODULE="on" && go get github.com/mfridman/tparse@latest
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/go/bin
|
||||
key: ${{ runner.os }}-go-tparse-binary
|
||||
|
||||
test-unit-cover:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v2.1.4
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
@ -49,7 +33,7 @@ jobs:
|
||||
run: |
|
||||
make test-unit-cover
|
||||
if: env.GIT_DIFF
|
||||
- uses: codecov/codecov-action@v2.1.0
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage.txt
|
||||
fail_ci_if_error: true
|
||||
@ -59,87 +43,33 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/setup-go@v2.1.4
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
id: git_diff
|
||||
with:
|
||||
SUFFIX_FILTER: |
|
||||
.go
|
||||
.mod
|
||||
.sum
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.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']
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.17
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
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
|
||||
|
||||
liveness-test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v2.1.4
|
||||
with:
|
||||
go-version: 1.17
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
id: git_diff
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Install Starport
|
||||
run: |
|
||||
curl https://get.starport.network/starport! | bash
|
||||
if: env.GIT_DIFF
|
||||
- name: Start Local Network via Starport
|
||||
run: |
|
||||
starport chain serve --reset-once -v -c ./starport.yml > starport.out 2>&1 &
|
||||
if: env.GIT_DIFF
|
||||
- name: Test Local Network Liveness
|
||||
run: |
|
||||
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
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
@ -155,11 +85,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/setup-go@v2.1.4
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.17
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
@ -169,4 +100,131 @@ jobs:
|
||||
- name: Test e2e
|
||||
run: |
|
||||
make test-integration
|
||||
if: env.GIT_DIFF
|
||||
|
||||
integration_tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v18
|
||||
- uses: cachix/cachix-action@v11
|
||||
with:
|
||||
name: ethermint
|
||||
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
tests/integration_tests/**
|
||||
- name: Run integration tests
|
||||
run: make run-integration-tests
|
||||
if: env.GIT_DIFF
|
||||
- name: 'Tar debug files'
|
||||
if: failure()
|
||||
run: tar cfz debug_files.tar.gz -C /tmp/pytest-of-runner .
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: debug-files
|
||||
path: debug_files.tar.gz
|
||||
if-no-files-found: ignore
|
||||
|
||||
upload-cache:
|
||||
if: github.event_name == 'push'
|
||||
needs: ["integration_tests"]
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: cachix/install-nix-action@v18
|
||||
- uses: cachix/cachix-action@v11
|
||||
with:
|
||||
name: ethermint
|
||||
signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
||||
- name: 'instantiate integration test env'
|
||||
run: nix-store -r $(nix-instantiate tests/integration_tests/shell.nix)
|
||||
|
||||
test-sim-nondeterminism:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation nondeterminism
|
||||
run: |
|
||||
make test-sim-nondeterminism
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-random-genesis-fast:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation with random genesis
|
||||
run: |
|
||||
make test-sim-random-genesis-fast
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-import-export:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Simulation of import and export genesis
|
||||
run: |
|
||||
make test-sim-import-export
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-after-import:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation after import
|
||||
run: |
|
||||
make test-sim-after-import
|
||||
if: env.GIT_DIFF
|
@ -45,6 +45,8 @@ linters:
|
||||
- rowserrcheck
|
||||
# - whitespace
|
||||
# - wsl
|
||||
disable:
|
||||
- typecheck
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
|
549
CHANGELOG.md
549
CHANGELOG.md
@ -36,317 +36,534 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (deps) [#1361](https://github.com/evmos/ethermint/pull/1361) Bump ibc-go to [`v5.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v5.0.0)
|
||||
* (evm) [\#1272](https://github.com/evmos/ethermint/pull/1272) Implement modular interface for the EVM.
|
||||
* (deps) [#1168](https://github.com/evmos/ethermint/pull/1168) Upgrade Cosmos SDK to `v0.46`.
|
||||
* (feemarket) [#1194](https://github.com/evmos/ethermint/pull/1194) Apply feemarket to native cosmos tx.
|
||||
* (eth) [#1346](https://github.com/evmos/ethermint/pull/1346) Added support for `sdk.Dec` and `ed25519` type on eip712.
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (ante) [#1214](https://github.com/evmos/ethermint/pull/1214) Set mempool priority to EVM transactions.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (lint) [#1298](https://github.com/evmos/ethermint/pull/1298) 150 character line length limit, `gofumpt`, and linting
|
||||
* (feemarket) [\#1165](https://github.com/evmos/ethermint/pull/1165) Add hint in specs about different gas terminology in Cosmos and Ethereum.
|
||||
* (cli) [#1226](https://github.com/evmos/ethermint/pull/1226) Add custom app db backend flag.
|
||||
* (ante) [#1289](https://github.com/evmos/ethermint/pull/1289) Change the fallback tx priority mechanism to be based on gas price.
|
||||
* (test) [#1311](https://github.com/evmos/ethermint/pull/1311) Add integration test for the `rollback` cmd
|
||||
* (ledger) [#1277](https://github.com/evmos/ethermint/pull/1277) Add Ledger preprocessing transaction hook for EIP-712-signed Cosmos payloads.
|
||||
* (rpc) [#1296](https://github.com/evmos/ethermint/pull/1296) Add RPC Backend unit tests.
|
||||
* (rpc) [#1352](https://github.com/evmos/ethermint/pull/1352) Make the grpc queries run concurrently, don't block the consensus state machine.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [#1179](https://github.com/evmos/ethermint/pull/1179) Fix gas used in traceTransaction response.
|
||||
* (rpc) [#1284](https://github.com/evmos/ethermint/pull/1284) Fix internal trace response upon incomplete `eth_sendTransaction` call.
|
||||
* (rpc) [#1340](https://github.com/evmos/ethermint/pull/1340) Fix error response when `eth_estimateGas` height provided is not found.
|
||||
* (rpc) [#1354](https://github.com/evmos/ethermint/pull/1354) Fix grpc query failure(`BaseFee` and `EthCall`) on legacy block states.
|
||||
* (cli) [#1362](https://github.com/evmos/ethermint/pull/1362) Fix `index-eth-tx` error when the indexer db is empty.
|
||||
|
||||
## [v0.19.2] - 2022-08-29
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [1301](https://github.com/evmos/ethermint/pull/1301) Bump Cosmos SDK to `v0.45.8`, Tendermint to `v0.34.21`, IAVL to `v0.19.1` & store options
|
||||
|
||||
## [v0.19.1] - 2022-08-26
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (eth) [#1305](https://github.com/evmos/ethermint/pull/1305) Added support for optional params, basic types arrays and `time` type on eip712.
|
||||
|
||||
## [v0.19.0] - 2022-08-15
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (deps) [#1159](https://github.com/evmos/ethermint/pull/1159) Bump Geth version to `v1.10.19`.
|
||||
* (ante) [#1176](https://github.com/evmos/ethermint/pull/1176) Fix invalid tx hashes; Remove `Size_` field and validate `Hash`/`From` fields in ante handler,
|
||||
recompute eth tx hashes in JSON-RPC APIs to fix old blocks.
|
||||
* (ante) [#1173](https://github.com/evmos/ethermint/pull/1173) Make `NewAnteHandler` return error if input is invalid
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (rpc) [#1121](https://github.com/tharsis/ethermint/pull/1121) Implement Ethereum tx indexer
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [#1179](https://github.com/evmos/ethermint/pull/1179) Fix gas used in `debug_traceTransaction` response.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (test) [#1196](https://github.com/evmos/ethermint/pull/1196) Integration tests setup
|
||||
* (test) [#1199](https://github.com/evmos/ethermint/pull/1199) Add backend test suite with mock gRPC query client
|
||||
* (test) [#1189](https://github.com/evmos/ethermint/pull/1189) JSON-RPC unit tests
|
||||
* (test) [#1212](https://github.com/evmos/ethermint/pull/1212) Prune node integration tests
|
||||
* (test) [#1207](https://github.com/evmos/ethermint/pull/1207) JSON-RPC types integration tests
|
||||
* (test) [#1218](https://github.com/evmos/ethermint/pull/1218) Restructure JSON-RPC API
|
||||
* (rpc) [#1229](https://github.com/evmos/ethermint/pull/1229) Add support for configuring RPC `MaxOpenConnections`
|
||||
* (cli) [#1230](https://github.com/evmos/ethermint/pull/1230) Remove redundant positional height parameter from feemarket's query cli.
|
||||
* (test)[#1233](https://github.com/evmos/ethermint/pull/1233) Add filters integration tests
|
||||
|
||||
## [v0.18.0] - 2022-08-04
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (evm) [\#1234](https://github.com/evmos/ethermint/pull/1234) Fix [CVE-2022-35936](https://github.com/evmos/ethermint/security/advisories/GHSA-f92v-grc2-w2fg) security vulnerability.
|
||||
* (evm) [\#1174](https://github.com/evmos/ethermint/pull/1174) Don't allow eth txs with 0 in mempool.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (ante) [\#1208](https://github.com/evmos/ethermint/pull/1208) Change default `MaxGasWanted` value.
|
||||
|
||||
## [v0.17.2] - 2022-07-26
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [\#1190](https://github.com/evmos/ethermint/issues/1190) Fix `UnmarshalJSON` panic of breaking EVM and fee market `Params`.
|
||||
* (evm) [\#1187](https://github.com/evmos/ethermint/pull/1187) Fix `TxIndex` value (expected 0, actual 1) when trace the first tx of a block via `debug_traceTransaction` API.
|
||||
|
||||
## [v0.17.1] - 2022-07-13
|
||||
|
||||
### Improvements
|
||||
|
||||
* (rpc) [\#1169](https://github.com/evmos/ethermint/pull/1169) Remove unnecessary queries from `getBlockNumber` function
|
||||
|
||||
## [v0.17.0] - 2022-06-27
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (evm) [\#1128](https://github.com/evmos/ethermint/pull/1128) Clear tx logs if tx failed in post processing hooks
|
||||
* (evm) [\#1124](https://github.com/evmos/ethermint/pull/1124) Reject non-replay-protected tx in `AnteHandler` to prevent replay attack
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (rpc) [\#1126](https://github.com/evmos/ethermint/pull/1126) Make some JSON-RPC APIS work for pruned nodes.
|
||||
* (rpc) [\#1143](https://github.com/evmos/ethermint/pull/1143) Restrict unprotected txs on the node JSON-RPC configuration.
|
||||
* (all) [\#1137](https://github.com/evmos/ethermint/pull/1137) Rename go module to `evmos/ethermint`
|
||||
|
||||
### API Breaking
|
||||
|
||||
- (json-rpc) [tharsis#1121](https://github.com/tharsis/ethermint/pull/1121) Store eth tx index separately
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [\#1147](https://github.com/evmos/ethermint/pull/1147) Bump Go version to `1.18`.
|
||||
* (feemarket) [\#1135](https://github.com/evmos/ethermint/pull/1135) Set lower bound of base fee to min gas price param
|
||||
* (evm) [\#1142](https://github.com/evmos/ethermint/pull/1142) Rename `RejectUnprotectedTx` to `AllowUnprotectedTxs` for consistency with go-ethereum.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [\#1138](https://github.com/evmos/ethermint/pull/1138) Fix GasPrice calculation with relation to `MinGasPrice`
|
||||
|
||||
## [v0.16.1] - 2022-06-09
|
||||
|
||||
### Improvements
|
||||
|
||||
* (feemarket) [\#1120](https://github.com/evmos/ethermint/pull/1120) Make `min-gas-multiplier` parameter accept zero value
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (evm) [\#1118](https://github.com/evmos/ethermint/pull/1118) Fix `Type()` `Account` method `EmptyCodeHash` comparison
|
||||
|
||||
## [v0.16.0] - 2022-06-06
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (feemarket) [tharsis#1105](https://github.com/evmos/ethermint/pull/1105) Update `BaseFee` calculation based on `GasWanted` instead of `GasUsed`.
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (feemarket) [tharsis#1104](https://github.com/evmos/ethermint/pull/1104) Enforce a minimum gas price for Cosmos and EVM transactions through the `MinGasPrice` parameter.
|
||||
* (rpc) [tharsis#1081](https://github.com/evmos/ethermint/pull/1081) Deduplicate some json-rpc logic codes, cleanup several dead functions.
|
||||
* (ante) [tharsis#1062](https://github.com/evmos/ethermint/pull/1062) Emit event of eth tx hash in ante handler to support query failed transactions.
|
||||
* (analytics) [tharsis#1106](https://github.com/evmos/ethermint/pull/1106) Update telemetry to Ethermint modules.
|
||||
* (rpc) [tharsis#1108](https://github.com/evmos/ethermint/pull/1108) Update GetGasPrice RPC endpoint with global `MinGasPrice`
|
||||
|
||||
### Improvements
|
||||
|
||||
* (cli) [tharsis#1086](https://github.com/evmos/ethermint/pull/1086) Add rollback command.
|
||||
* (specs) [tharsis#1095](https://github.com/evmos/ethermint/pull/1095) Add more evm specs concepts.
|
||||
* (evm) [tharsis#1101](https://github.com/evmos/ethermint/pull/1101) Add tx_type, gas and counter telemetry for ethereum txs.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [tharsis#1082](https://github.com/evmos/ethermint/pull/1082) fix gas price returned in getTransaction api.
|
||||
* (evm) [tharsis#1088](https://github.com/evmos/ethermint/pull/1088) Fix ability to append log in tx post processing.
|
||||
* (rpc) [tharsis#1081](https://github.com/evmos/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
|
||||
* (ante) [tharsis#1111](https://github.com/evmos/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
|
||||
* (types) [tharsis#1112](https://github.com/cosmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account.
|
||||
|
||||
## [v0.15.0] - 2022-05-09
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (ante) [tharsis#1060](https://github.com/evmos/ethermint/pull/1060) Check `EnableCreate`/`EnableCall` in `AnteHandler` to short-circuit EVM transactions.
|
||||
* (evm) [tharsis#1087](https://github.com/evmos/ethermint/pull/1087) Minimum GasUsed proportional to GasLimit and `MinGasDenominator` EVM module param.
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (rpc) [tharsis#1070](https://github.com/evmos/ethermint/pull/1070) Refactor `rpc/` package:
|
||||
* `Backend` interface is now `BackendI`, which implements `EVMBackend` (for Ethereum namespaces) and `CosmosBackend` (for Cosmos namespaces)
|
||||
* Previous `EVMBackend` type is now `Backend`, which is the concrete implementation of `BackendI`
|
||||
* Move `rpc/ethereum/types` -> `rpc/types`
|
||||
* Move `rpc/ethereum/backend` -> `rpc/backend`
|
||||
* Move `rpc/ethereum/namespaces` -> `rpc/namespaces/ethereum`
|
||||
* (rpc) [tharsis#1068](https://github.com/evmos/ethermint/pull/1068) Fix London hard-fork check logic in JSON-RPC APIs.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (ci, evm) [tharsis#1063](https://github.com/evmos/ethermint/pull/1063) Run simulations on CI.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [tharsis#1059](https://github.com/evmos/ethermint/pull/1059) Remove unnecessary event filtering logic on the `eth_baseFee` JSON-RPC endpoint.
|
||||
|
||||
## [v0.14.0] - 2022-04-19
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (evm) [tharsis#1051](https://github.com/evmos/ethermint/pull/1051) Context block height fix on TraceTx. Removes `tx_index` on `QueryTraceTxRequest` proto type.
|
||||
* (evm) [tharsis#1091](https://github.com/evmos/ethermint/pull/1091) Add query params command on EVM Module
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [tharsis#1046](https://github.com/evmos/ethermint/pull/1046) Bump Cosmos SDK version to [`v0.45.3`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.3)
|
||||
* (rpc) [tharsis#1056](https://github.com/evmos/ethermint/pull/1056) Make json-rpc namespaces extensible
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [tharsis#1050](https://github.com/evmos/ethermint/pull/1050) `eth_getBlockByNumber` fix on batch transactions
|
||||
* (app) [tharsis#658](https://github.com/evmos/ethermint/issues/658) Support simulations for the EVM.
|
||||
|
||||
## [v0.13.0] - 2022-04-05
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (evm) [tharsis#1027](https://github.com/evmos/ethermint/pull/1027) Change the `PostTxProcessing` hook interface to include the full message data.
|
||||
* (feemarket) [tharsis#1026](https://github.com/evmos/ethermint/pull/1026) Fix REST endpoints to use `/ethermint/feemarket/*` instead of `/feemarket/evm/*`.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [tharsis#1029](https://github.com/evmos/ethermint/pull/1029) Bump Cosmos SDK version to [`v0.45.2`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.2)
|
||||
* (evm) [tharsis#1025](https://github.com/evmos/ethermint/pull/1025) Allow to append logs after a post processing hook.
|
||||
|
||||
## [v0.12.2] - 2022-03-30
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (feemarket) [tharsis#1021](https://github.com/tharsis/ethermint/pull/1021) Fix fee market migration.
|
||||
* (feemarket) [tharsis#1021](https://github.com/evmos/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.
|
||||
* (evm) [tharsis#1016](https://github.com/evmos/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`.
|
||||
* (rpc) [tharsis#1012](https://github.com/evmos/ethermint/pull/1012) fix the tx hash in filter entries created by `eth_newPendingTransactionFilter`.
|
||||
* (rpc) [tharsis#1006](https://github.com/evmos/ethermint/pull/1006) Use `string` as the parameters type to correct ambiguous results.
|
||||
* (ante) [tharsis#1004](https://github.com/evmos/ethermint/pull/1004) Make `MaxTxGasWanted` configurable.
|
||||
* (ante) [tharsis#991](https://github.com/evmos/ethermint/pull/991) Set an upper bound to gasWanted to prevent DoS attack.
|
||||
* (rpc) [tharsis#990](https://github.com/evmos/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.
|
||||
* (ante) [tharsis#964](https://github.com/evmos/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.
|
||||
* (rpc) [tharsis#975](https://github.com/evmos/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
|
||||
* (rpc) [tharsis#979](https://github.com/evmos/ethermint/pull/979) Add configurable timeouts to http server
|
||||
* (rpc) [tharsis#988](https://github.com/evmos/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.
|
||||
* (rpc) [tharsis#970](https://github.com/evmos/ethermint/pull/970) Fix unexpected nil reward values on `eth_feeHistory` response
|
||||
* (evm) [tharsis#529](https://github.com/evmos/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.
|
||||
* (rpc) [tharsis#968](https://github.com/evmos/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.
|
||||
* (ante) [tharsis#866](https://github.com/evmos/ethermint/pull/866) `NewAnteHandler` constructor now receives a `HandlerOptions` field.
|
||||
* (evm) [tharsis#849](https://github.com/evmos/ethermint/pull/849) `PostTxProcessing` hook now takes an Ethereum tx `Receipt` and a `from` `Address` as arguments.
|
||||
* (ante) [tharsis#916](https://github.com/evmos/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).
|
||||
* (deps) [tharsis#912](https://github.com/evmos/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/evmos/ethermint/pull/840) Store empty topics as empty array rather than nil.
|
||||
* (feemarket) [tharsis#822](https://github.com/evmos/ethermint/pull/822) Update EIP1559 base fee in `BeginBlock`.
|
||||
* (evm) [tharsis#817](https://github.com/evmos/ethermint/pull/817) Use `effectiveGasPrice` in ante handler, add `effectiveGasPrice` to tx receipt.
|
||||
* (evm) [tharsis#808](https://github.com/evmos/ethermint/issues/808) increase nonce in ante handler for contract creation transaction.
|
||||
* (evm) [tharsis#851](https://github.com/evmos/ethermint/pull/851) fix contract address used in EVM, this issue is caused by [tharsis#808](https://github.com/evmos/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)
|
||||
* (feemarket) [tharsis#855](https://github.com/evmos/ethermint/pull/855) Consistent `BaseFee` check logic.
|
||||
* (evm) [tharsis#729](https://github.com/evmos/ethermint/pull/729) Refactor EVM `StateDB` implementation.
|
||||
* (evm) [tharsis#945](https://github.com/evmos/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
|
||||
* (ante) [tharsis#950](https://github.com/evmos/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.
|
||||
* (types) [tharsis#884](https://github.com/evmos/ethermint/pull/884) Introduce a new `EthAccountI` interface for EVM-compatible account types.
|
||||
* (types) [tharsis#849](https://github.com/evmos/ethermint/pull/849) Add `Type` function to distinguish EOAs from Contract accounts.
|
||||
* (evm) [tharsis#826](https://github.com/evmos/ethermint/issues/826) Improve allocation of bytes of `tx.To` address.
|
||||
* (evm) [tharsis#827](https://github.com/evmos/ethermint/issues/827) Speed up creation of event logs by using the slice insertion idiom with indices.
|
||||
* (ante) [tharsis#819](https://github.com/evmos/ethermint/pull/819) Remove redundant ante handlers
|
||||
* (app) [tharsis#873](https://github.com/evmos/ethermint/pull/873) Validate code hash in GenesisAccount
|
||||
* (evm) [tharsis#901](https://github.com/evmos/ethermint/pull/901) Support multiple `MsgEthereumTx` in single tx.
|
||||
* (config) [tharsis#908](https://github.com/evmos/ethermint/pull/908) Add `api.enable` flag for Cosmos SDK Rest server
|
||||
* (feemarket) [tharsis#919](https://github.com/evmos/ethermint/pull/919) Initialize baseFee in default genesis state.
|
||||
* (feemarket) [tharsis#943](https://github.com/evmos/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.
|
||||
* (rpc) [tharsis#955](https://github.com/evmos/ethermint/pull/955) Fix websocket server push duplicated messages to subscriber.
|
||||
* (rpc) [tharsis#953](https://github.com/evmos/ethermint/pull/953) Add `eth_signTypedData` api support.
|
||||
* (log) [tharsis#948](https://github.com/evmos/ethermint/pull/948) Redirect go-ethereum's logs to cosmos-sdk logger.
|
||||
* (evm) [tharsis#884](https://github.com/evmos/ethermint/pull/884) Support multiple account types on the EVM `StateDB`.
|
||||
* (rpc) [tharsis#831](https://github.com/evmos/ethermint/pull/831) Fix BaseFee value when height is specified.
|
||||
* (evm) [tharsis#838](https://github.com/evmos/ethermint/pull/838) Fix splitting of trace.Memory into 32 chunks.
|
||||
* (rpc) [tharsis#860](https://github.com/evmos/ethermint/pull/860) Fix `eth_getLogs` when specify blockHash without address/topics, and limit the response size.
|
||||
* (rpc) [tharsis#865](https://github.com/evmos/ethermint/pull/865) Fix RPC Filter parameters being ignored
|
||||
* (evm) [tharsis#871](https://github.com/evmos/ethermint/pull/871) Set correct nonce in `EthCall` and `EstimateGas` grpc query.
|
||||
* (rpc) [tharsis#878](https://github.com/evmos/ethermint/pull/878) Workaround to make GetBlock RPC api report correct block gas used.
|
||||
* (rpc) [tharsis#900](https://github.com/evmos/ethermint/pull/900) `newPendingTransactions` filter return ethereum tx hash.
|
||||
* (rpc) [tharsis#933](https://github.com/evmos/ethermint/pull/933) Fix `newPendingTransactions` subscription deadlock when a Websocket client exits without unsubscribing and the node errors.
|
||||
* (evm) [tharsis#932](https://github.com/evmos/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
|
||||
* (evm) [tharsis#802](https://github.com/evmos/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
|
||||
* (app) [tharsis#794](https://github.com/evmos/ethermint/pull/794) Setup in-place store migrators.
|
||||
* (ci) [tharsis#784](https://github.com/evmos/ethermint/pull/784) Enable automatic backport of PRs.
|
||||
* (rpc) [tharsis#786](https://github.com/evmos/ethermint/pull/786) Improve error message of `SendTransaction`/`SendRawTransaction` JSON-RPC APIs.
|
||||
* (rpc) [tharsis#810](https://github.com/evmos/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
|
||||
* (license) [tharsis#800](https://github.com/evmos/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/evmos/ethermint/pull/794) Register EVM gRPC `Msg` server.
|
||||
* (rpc) [tharsis#781](https://github.com/evmos/ethermint/pull/781) Fix get block invalid transactions filter.
|
||||
* (rpc) [tharsis#782](https://github.com/evmos/ethermint/pull/782) Fix wrong block gas limit returned by JSON-RPC.
|
||||
* (evm) [tharsis#798](https://github.com/evmos/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.
|
||||
* (feemarket) [tharsis#770](https://github.com/evmos/ethermint/pull/770) Enable fee market (EIP1559) by default.
|
||||
* (rpc) [tharsis#769](https://github.com/evmos/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
|
||||
* (evm, ante) [tharsis#620](https://github.com/evmos/ethermint/pull/620) Add fee market field to EVM `Keeper` and `AnteHandler`.
|
||||
* (all) [tharsis#231](https://github.com/evmos/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/evmos/ethermint/pull/703) Fix some fields in transaction are not authenticated by signature.
|
||||
* (evm) [tharsis#751](https://github.com/evmos/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`
|
||||
* (rpc, evm) [tharsis#673](https://github.com/evmos/ethermint/pull/673) Use tendermint events to store fee market basefee.
|
||||
* (rpc) [tharsis#624](https://github.com/evmos/ethermint/pull/624) Implement new JSON-RPC endpoints from latest geth version
|
||||
* (evm) [tharsis#662](https://github.com/evmos/ethermint/pull/662) Disable basefee for non london blocks
|
||||
* (cmd) [tharsis#712](https://github.com/evmos/ethermint/pull/712) add tx cli to build evm transaction
|
||||
* (rpc) [tharsis#733](https://github.com/evmos/ethermint/pull/733) add JSON_RPC endpoint `personal_unpair`
|
||||
* (rpc) [tharsis#734](https://github.com/evmos/ethermint/pull/734) add JSON_RPC endpoint `eth_feeHistory`
|
||||
* (rpc) [tharsis#740](https://github.com/evmos/ethermint/pull/740) add JSON_RPC endpoint `personal_initializeWallet`
|
||||
* (rpc) [tharsis#743](https://github.com/evmos/ethermint/pull/743) add JSON_RPC endpoint `debug_traceBlockByHash`
|
||||
* (rpc) [tharsis#748](https://github.com/evmos/ethermint/pull/748) add JSON_RPC endpoint `personal_listWallets`
|
||||
* (rpc) [tharsis#754](https://github.com/evmos/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
|
||||
* (evm) [tharsis#746](https://github.com/evmos/ethermint/pull/746) Set EVM debugging based on tracer configuration.
|
||||
* (app,cli) [tharsis#725](https://github.com/evmos/ethermint/pull/725) Fix cli-config for `keys` command.
|
||||
* (rpc) [tharsis#727](https://github.com/evmos/ethermint/pull/727) Decode raw transaction using RLP.
|
||||
* (rpc) [tharsis#661](https://github.com/evmos/ethermint/pull/661) Fix OOM bug when creating too many filters using JSON-RPC.
|
||||
* (evm) [tharsis#660](https://github.com/evmos/ethermint/pull/660) Fix `nil` pointer panic in `ApplyNativeMessage`.
|
||||
* (evm, test) [tharsis#649](https://github.com/evmos/ethermint/pull/649) Test DynamicFeeTx.
|
||||
* (evm) [tharsis#702](https://github.com/evmos/ethermint/pull/702) Fix panic in web3 RPC handlers
|
||||
* (rpc) [tharsis#720](https://github.com/evmos/ethermint/pull/720) Fix `debug_traceTransaction` failure
|
||||
* (rpc) [tharsis#741](https://github.com/evmos/ethermint/pull/741) Fix `eth_getBlockByNumberAndHash` return with non eth txs
|
||||
* (rpc) [tharsis#743](https://github.com/evmos/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
|
||||
* (tests) [tharsis#704](https://github.com/evmos/ethermint/pull/704) Introduce E2E testing framework for clients
|
||||
* (deps) [tharsis#737](https://github.com/evmos/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/evmos/ethermint/pull/671) Don't pass base fee externally for `EthCall`/`EthEstimateGas` apis.
|
||||
* (evm) [tharsis#674](https://github.com/evmos/ethermint/pull/674) Refactor `ApplyMessage`, remove
|
||||
`ApplyNativeMessage`.
|
||||
* (rpc) [tharsis#714](https://github.com/tharsis/ethermint/pull/714) remove `MsgEthereumTx` support in `TxConfig`
|
||||
* (rpc) [tharsis#714](https://github.com/evmos/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).
|
||||
* (deps) [tharsis#692](https://github.com/evmos/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/evmos/ethermint/pull/679) Fix file close handle.
|
||||
* (deps) [tharsis#668](https://github.com/evmos/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
|
||||
* (rpc) [tharsis#667](https://github.com/evmos/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.
|
||||
* (evm) [tharsis#650](https://github.com/evmos/ethermint/pull/650) Fix panic when flattening the cache context in case transaction is reverted.
|
||||
* (rpc, test) [tharsis#608](https://github.com/evmos/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
|
||||
* (rpc) [tharsis#400](https://github.com/evmos/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).
|
||||
* (deps) [tharsis#621](https://github.com/evmos/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/evmos/ethermint/pull/613) Refactor `traceTx`
|
||||
* (deps) [tharsis#610](https://github.com/evmos/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.
|
||||
* (rpc) [tharsis#642](https://github.com/evmos/ethermint/issues/642) Fix `eth_getLogs` when string is specified in filter's from or to fields
|
||||
* (evm) [tharsis#616](https://github.com/evmos/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/evmos/ethermint/issues/614) Use JSON for (un)marshaling tx `Log`s from events.
|
||||
* (rpc) [tharsis#611](https://github.com/evmos/ethermint/pull/611) Fix panic on JSON-RPC when querying for an invalid block height.
|
||||
* (cmd) [tharsis#483](https://github.com/evmos/ethermint/pull/483) Use config values on genesis accounts.
|
||||
|
||||
## [v0.6.0] - 2021-09-29
|
||||
|
||||
### 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
|
||||
* (app) [tharsis#476](https://github.com/evmos/ethermint/pull/476) Update Bech32 HRP to `ethm`.
|
||||
* (evm) [tharsis#556](https://github.com/evmos/ethermint/pull/556) Remove tx logs and block bloom from chain state
|
||||
* (evm) [tharsis#590](https://github.com/evmos/ethermint/pull/590) Contract storage key is not hashed anymore
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (evm) [tharsis#469](https://github.com/tharsis/ethermint/pull/469) Deprecate `YoloV3Block` and `EWASMBlock` from `ChainConfig`
|
||||
* (evm) [tharsis#469](https://github.com/evmos/ethermint/pull/469) Deprecate `YoloV3Block` and `EWASMBlock` from `ChainConfig`
|
||||
|
||||
### 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
|
||||
* (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
|
||||
* (evm) [tharsis#469](https://github.com/evmos/ethermint/pull/469) Support [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
|
||||
* (evm) [tharsis#417](https://github.com/evmos/ethermint/pull/417) Add `EvmHooks` for tx post-processing
|
||||
* (rpc) [tharsis#506](https://github.com/evmos/ethermint/pull/506) Support for `debug_traceTransaction` RPC endpoint
|
||||
* (rpc) [tharsis#555](https://github.com/evmos/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.
|
||||
* (rpc, server) [tharsis#600](https://github.com/evmos/ethermint/pull/600) Add TLS configuration for websocket API
|
||||
* (rpc) [tharsis#598](https://github.com/evmos/ethermint/pull/598) Check truncation when creating a `BlockNumber` from `big.Int`
|
||||
* (evm) [tharsis#597](https://github.com/evmos/ethermint/pull/597) Check for `uint64` -> `int64` block height overflow on `GetHashFn`
|
||||
* (evm) [tharsis#579](https://github.com/evmos/ethermint/pull/579) Update `DeriveChainID` function to handle `v` signature values `< 35`.
|
||||
* (encoding) [tharsis#478](https://github.com/evmos/ethermint/pull/478) Register `Evidence` to amino codec.
|
||||
* (rpc) [tharsis#478](https://github.com/evmos/ethermint/pull/481) Getting the node configuration when calling the `miner` rpc methods.
|
||||
* (cli) [tharsis#561](https://github.com/evmos/ethermint/pull/561) `Export` and `Start` commands now use the same home directory.
|
||||
|
||||
### 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
|
||||
* (evm) [tharsis#461](https://github.com/evmos/ethermint/pull/461) Increase performance of `StateDB` transaction log storage (r/w).
|
||||
* (evm) [tharsis#566](https://github.com/evmos/ethermint/pull/566) Introduce `stateErr` store in `StateDB` to avoid meaningless operations if any error happened before
|
||||
* (rpc, evm) [tharsis#587](https://github.com/evmos/ethermint/pull/587) Apply bloom filter when query ethlogs with range of blocks
|
||||
* (evm) [tharsis#586](https://github.com/evmos/ethermint/pull/586) Benchmark evm keeper
|
||||
|
||||
## [v0.5.0] - 2021-08-20
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
* (app, rpc) [tharsis#447](https://github.com/tharsis/ethermint/pull/447) Chain ID format has been changed from `<identifier>-<epoch>` to `<identifier>_<EIP155_number>-<epoch>`
|
||||
* (app, rpc) [tharsis#447](https://github.com/evmos/ethermint/pull/447) Chain ID format has been changed from `<identifier>-<epoch>` to `<identifier>_<EIP155_number>-<epoch>`
|
||||
in order to clearly distinguish permanent vs impermanent components.
|
||||
* (app, evm) [tharsis#434](https://github.com/tharsis/ethermint/pull/434) EVM `Keeper` struct and `NewEVM` function now have a new `trace` field to define
|
||||
* (app, evm) [tharsis#434](https://github.com/evmos/ethermint/pull/434) EVM `Keeper` struct and `NewEVM` function now have a new `trace` field to define
|
||||
the Tracer type used to collect execution traces from the EVM transaction execution.
|
||||
* (evm) [tharsis#175](https://github.com/tharsis/ethermint/issues/175) The msg `TxData` field is now represented as a `*proto.Any`.
|
||||
* (evm) [tharsis#84](https://github.com/tharsis/ethermint/pull/84) Remove `journal`, `CommitStateDB` and `stateObjects`.
|
||||
* (rpc, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) Remove tx `Receipt` from store and replace it with fields obtained from the Tendermint RPC client.
|
||||
* (evm) [tharsis#72](https://github.com/tharsis/ethermint/issues/72) Update `AccessList` to use `TransientStore` instead of map.
|
||||
* (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
|
||||
* (evm) [tharsis#175](https://github.com/evmos/ethermint/issues/175) The msg `TxData` field is now represented as a `*proto.Any`.
|
||||
* (evm) [tharsis#84](https://github.com/evmos/ethermint/pull/84) Remove `journal`, `CommitStateDB` and `stateObjects`.
|
||||
* (rpc, evm) [tharsis#81](https://github.com/evmos/ethermint/pull/81) Remove tx `Receipt` from store and replace it with fields obtained from the Tendermint RPC client.
|
||||
* (evm) [tharsis#72](https://github.com/evmos/ethermint/issues/72) Update `AccessList` to use `TransientStore` instead of map.
|
||||
* (evm) [tharsis#68](https://github.com/evmos/ethermint/issues/68) Replace block hash storage map to use staking `HistoricalInfo`.
|
||||
* (evm) [tharsis#276](https://github.com/evmos/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#334](https://github.com/tharsis/ethermint/pull/334) Log index changed to the index in block rather than
|
||||
* (evm) [tharsis#342](https://github.com/evmos/ethermint/issues/342) Don't clear balance when resetting the account.
|
||||
* (evm) [tharsis#334](https://github.com/evmos/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.
|
||||
* (evm) [tharsis#399](https://github.com/evmos/ethermint/pull/399) Exception in sub-message call reverts the call if it's not propagated.
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (proto) [tharsis#448](https://github.com/tharsis/ethermint/pull/448) Bump version for all Ethermint messages to `v1`
|
||||
* (server) [tharsis#434](https://github.com/tharsis/ethermint/pull/434) `evm-rpc` flags and app config have been renamed to `json-rpc`.
|
||||
* (proto, evm) [tharsis#207](https://github.com/tharsis/ethermint/issues/207) Replace `big.Int` in favor of `sdk.Int` for `TxData` fields
|
||||
* (proto, evm) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) gRPC Query and Tx service changes:
|
||||
* (proto) [tharsis#448](https://github.com/evmos/ethermint/pull/448) Bump version for all Ethermint messages to `v1`
|
||||
* (server) [tharsis#434](https://github.com/evmos/ethermint/pull/434) `evm-rpc` flags and app config have been renamed to `json-rpc`.
|
||||
* (proto, evm) [tharsis#207](https://github.com/evmos/ethermint/issues/207) Replace `big.Int` in favor of `sdk.Int` for `TxData` fields
|
||||
* (proto, evm) [tharsis#81](https://github.com/evmos/ethermint/pull/81) gRPC Query and Tx service changes:
|
||||
* 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.
|
||||
* (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.
|
||||
* (evm) [tharsis#202](https://github.com/evmos/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/evmos/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/evmos/ethermint/pull/321) Fix `BloomFilter` response.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (client) [tharsis#450](https://github.com/tharsis/ethermint/issues/450) Add EIP55 hex address support on `debug addr` command.
|
||||
* (server) [tharsis#343](https://github.com/tharsis/ethermint/pull/343) Define a wrap tendermint logger `Handler` go-ethereum's `root` logger.
|
||||
* (rpc) [tharsis#457](https://github.com/tharsis/ethermint/pull/457) Configure RPC gas cap through app config.
|
||||
* (evm) [tharsis#434](https://github.com/tharsis/ethermint/pull/434) Support different `Tracer` types for the EVM.
|
||||
* (deps) [tharsis#427](https://github.com/tharsis/ethermint/pull/427) Bump ibc-go to [`v1.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v1.0.0)
|
||||
* (gRPC) [tharsis#239](https://github.com/tharsis/ethermint/pull/239) Query `ChainConfig` via gRPC.
|
||||
* (rpc) [tharsis#181](https://github.com/tharsis/ethermint/pull/181) Use evm denomination for params on tx fee.
|
||||
* (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) [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`.
|
||||
* (eth) [tharsis#460](https://github.com/tharsis/ethermint/issues/460) Add support for EIP-1898.
|
||||
* (client) [tharsis#450](https://github.com/evmos/ethermint/issues/450) Add EIP55 hex address support on `debug addr` command.
|
||||
* (server) [tharsis#343](https://github.com/evmos/ethermint/pull/343) Define a wrap tendermint logger `Handler` go-ethereum's `root` logger.
|
||||
* (rpc) [tharsis#457](https://github.com/evmos/ethermint/pull/457) Configure RPC gas cap through app config.
|
||||
* (evm) [tharsis#434](https://github.com/evmos/ethermint/pull/434) Support different `Tracer` types for the EVM.
|
||||
* (deps) [tharsis#427](https://github.com/evmos/ethermint/pull/427) Bump ibc-go to [`v1.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v1.0.0)
|
||||
* (gRPC) [tharsis#239](https://github.com/evmos/ethermint/pull/239) Query `ChainConfig` via gRPC.
|
||||
* (rpc) [tharsis#181](https://github.com/evmos/ethermint/pull/181) Use evm denomination for params on tx fee.
|
||||
* (deps) [tharsis#423](https://github.com/evmos/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/evmos/ethermint/issues/66) Support legacy transaction types for signing.
|
||||
* (evm) [tharsis#24](https://github.com/evmos/ethermint/pull/24) Implement metrics for `MsgEthereumTx`, state transitions, `BeginBlock` and `EndBlock`.
|
||||
* (rpc) [tharsis#124](https://github.com/evmos/ethermint/issues/124) Implement `txpool_content`, `txpool_inspect` and `txpool_status` RPC methods
|
||||
* (rpc) [tharsis#112](https://github.com/evmos/ethermint/pull/153) Fix `eth_coinbase` to return the ethereum address of the validator
|
||||
* (rpc) [tharsis#176](https://github.com/evmos/ethermint/issues/176) Support fetching pending nonce
|
||||
* (rpc) [tharsis#272](https://github.com/evmos/ethermint/pull/272) do binary search to estimate gas accurately
|
||||
* (rpc) [tharsis#313](https://github.com/evmos/ethermint/pull/313) Implement internal debug namespace (Not including logger functions nor traces).
|
||||
* (rpc) [tharsis#349](https://github.com/evmos/ethermint/pull/349) Implement configurable JSON-RPC APIs to manage enabled namespaces.
|
||||
* (rpc) [tharsis#377](https://github.com/evmos/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/evmos/ethermint/issues/460) Add support for EIP-1898.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (keys) [tharsis#346](https://github.com/tharsis/ethermint/pull/346) Fix `keys add` command with `--ledger` flag for the `secp256k1` signing algorithm.
|
||||
* (evm) [tharsis#291](https://github.com/tharsis/ethermint/pull/291) Use block proposer address (validator operator) for `COINBASE` opcode.
|
||||
* (rpc) [tharsis#81](https://github.com/tharsis/ethermint/pull/81) Fix transaction hashing and decoding on `eth_sendTransaction`.
|
||||
* (rpc) [tharsis#45](https://github.com/tharsis/ethermint/pull/45) Use `EmptyUncleHash` and `EmptyRootHash` for empty ethereum `Header` fields.
|
||||
* (keys) [tharsis#346](https://github.com/evmos/ethermint/pull/346) Fix `keys add` command with `--ledger` flag for the `secp256k1` signing algorithm.
|
||||
* (evm) [tharsis#291](https://github.com/evmos/ethermint/pull/291) Use block proposer address (validator operator) for `COINBASE` opcode.
|
||||
* (rpc) [tharsis#81](https://github.com/evmos/ethermint/pull/81) Fix transaction hashing and decoding on `eth_sendTransaction`.
|
||||
* (rpc) [tharsis#45](https://github.com/evmos/ethermint/pull/45) Use `EmptyUncleHash` and `EmptyRootHash` for empty ethereum `Header` fields.
|
||||
|
||||
## [v0.4.1] - 2021-03-01
|
||||
|
||||
@ -373,9 +590,11 @@ the Tracer type used to collect execution traces from the EVM transaction execut
|
||||
* (evm) [tharsis#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.
|
||||
|
||||
### 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.
|
||||
|
||||
## [v0.4.0] - 2020-12-15
|
||||
|
@ -1,23 +1,23 @@
|
||||
# Contributing
|
||||
|
||||
- [Contributing](#contributing)
|
||||
- [Architecture Decision Records (ADR)](#architecture-decision-records-adr)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Pull Request Templates](#pull-request-templates)
|
||||
- [Requesting Reviews](#requesting-reviews)
|
||||
- [Reviewing Pull Requests](#reviewing-pull-requests)
|
||||
- [Updating Documentation](#updating-documentation)
|
||||
- [Forking](#forking)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Protobuf](#protobuf)
|
||||
- [Testing](#testing)
|
||||
- [Branching Model and Release](#branching-model-and-release)
|
||||
- [PR Targeting](#pr-targeting)
|
||||
- [Development Procedure](#development-procedure)
|
||||
- [Pull Merge Procedure](#pull-merge-procedure)
|
||||
- [Release Procedure](#release-procedure)
|
||||
- [Point Release Procedure](#point-release-procedure)
|
||||
- [Code Owner Membership](#code-owner-membership)
|
||||
- [Architecture Decision Records (ADR)](#architecture-decision-records-adr)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Pull Request Templates](#pull-request-templates)
|
||||
- [Requesting Reviews](#requesting-reviews)
|
||||
- [Reviewing Pull Requests](#reviewing-pull-requests)
|
||||
- [Updating Documentation](#updating-documentation)
|
||||
- [Forking](#forking)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Protobuf](#protobuf)
|
||||
- [Testing](#testing)
|
||||
- [Branching Model and Release](#branching-model-and-release)
|
||||
- [PR Targeting](#pr-targeting)
|
||||
- [Development Procedure](#development-procedure)
|
||||
- [Pull Merge Procedure](#pull-merge-procedure)
|
||||
- [Release Procedure](#release-procedure)
|
||||
- [Point Release Procedure](#point-release-procedure)
|
||||
- [Code Owner Membership](#code-owner-membership)
|
||||
|
||||
Thank you for considering making contributions to Ethermint!
|
||||
|
||||
@ -25,8 +25,8 @@ Contributing to this repo can mean many things such as participating in
|
||||
discussion or proposing code changes. To ensure a smooth workflow for all
|
||||
contributors, the general procedure for contributing has been established:
|
||||
|
||||
1. Either [open](https://github.com/tharsis/ethermint/issues/new/choose) or
|
||||
[find](https://github.com/tharsis/ethermint/issues) an issue you'd like to help with
|
||||
1. Either [open](https://github.com/evmos/ethermint/issues/new/choose) or
|
||||
[find](https://github.com/evmos/ethermint/issues) an issue you'd like to help with
|
||||
2. Participate in thoughtful discussion on that issue
|
||||
3. If you would like to contribute:
|
||||
1. If the issue is a proposal, ensure that the proposal has been accepted
|
||||
@ -55,7 +55,7 @@ taken place in a GitHub issue, that PR runs a high likelihood of being rejected.
|
||||
Other notes:
|
||||
|
||||
- Looking for a good place to start contributing? How about checking out some
|
||||
[good first issues](https://github.com/tharsis/ethermint/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
|
||||
[good first issues](https://github.com/evmos/ethermint/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
|
||||
- Please make sure to run `make format` before every commit - the easiest way
|
||||
to do this is have your editor run it for you upon saving a file. Additionally
|
||||
please ensure that your code is lint compliant by running `make lint-fix`.
|
||||
@ -64,7 +64,7 @@ Other notes:
|
||||
|
||||
## Architecture Decision Records (ADR)
|
||||
|
||||
When proposing an architecture decision for Ethermint, please start by opening an [issue](https://github.com/tharsis/ethermint/issues/new/choose) or a [discussion](https://github.com/tharsis/ethermint/discussions/new) with a summary of the proposal. Once the proposal has been discussed and there is rough alignment on a high-level approach to the design, the [ADR creation process](https://github.com/tharsis/ethermint/blob/main/docs/architecture/PROCESS.md) can begin. We are following this process to ensure all involved parties are in agreement before any party begins coding the proposed implementation. If you would like to see examples of how these are written, please refer to the current [ADRs](https://github.com/tharsis/ethermint/tree/main/docs/architecture).
|
||||
When proposing an architecture decision for Ethermint, please start by opening an [issue](https://github.com/evmos/ethermint/issues/new/choose) or a [discussion](https://github.com/evmos/ethermint/discussions/new) with a summary of the proposal. Once the proposal has been discussed and there is rough alignment on a high-level approach to the design, the [ADR creation process](https://github.com/evmos/ethermint/blob/main/docs/architecture/PROCESS.md) can begin. We are following this process to ensure all involved parties are in agreement before any party begins coding the proposed implementation. If you would like to see examples of how these are written, please refer to the current [ADRs](https://github.com/evmos/ethermint/tree/main/docs/architecture).
|
||||
|
||||
## Pull Requests
|
||||
|
||||
@ -97,12 +97,12 @@ items. In addition, use the following review explanations:
|
||||
|
||||
- `LGTM` without an explicit approval means that the changes look good, but you haven't thoroughly reviewed the reviewer checklist items.
|
||||
- `Approval` means that you have completed some or all of the reviewer checklist items. If you only reviewed selected items, you must add your handle next to the items that you have reviewed. In addition, follow these guidelines:
|
||||
- You must also think through anything which ought to be included but is not
|
||||
- You must think through whether any added code could be partially combined (DRYed) with existing code
|
||||
- You must think through any potential security issues or incentive-compatibility flaws introduced by the changes
|
||||
- Naming must be consistent with conventions and the rest of the codebase
|
||||
- Code must live in a reasonable location, considering dependency structures (for example, not importing testing modules in production code, or including example code modules in production code).
|
||||
- If you approve the PR, you are responsible for any issues mentioned here and any issues that should have been addressed after thoroughly reviewing the reviewer checklist items in the pull request template.
|
||||
- You must also think through anything which ought to be included but is not
|
||||
- You must think through whether any added code could be partially combined (DRYed) with existing code
|
||||
- You must think through any potential security issues or incentive-compatibility flaws introduced by the changes
|
||||
- Naming must be consistent with conventions and the rest of the codebase
|
||||
- Code must live in a reasonable location, considering dependency structures (for example, not importing testing modules in production code, or including example code modules in production code).
|
||||
- If you approve the PR, you are responsible for any issues mentioned here and any issues that should have been addressed after thoroughly reviewing the reviewer checklist items in the pull request template.
|
||||
- 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.
|
||||
|
||||
@ -112,12 +112,12 @@ Go requires code to live under absolute paths, and this requirement complicates
|
||||
While my fork lives at `https://github.com/rigeyrigerige/ethermint`,
|
||||
the code should never exist at `$GOPATH/src/github.com/rigeyrigerige/ethermint`.
|
||||
Instead, we use `git remote` to add the fork as a new remote for the original repo,
|
||||
`$GOPATH/src/github.com/tharsis/ethermint`, and do all the work there.
|
||||
`$GOPATH/src/github.com/evmos/ethermint`, and do all the work there.
|
||||
|
||||
For instance, to create a fork and work on a branch of it, I would:
|
||||
|
||||
- Create the fork on GitHub, using the fork button.
|
||||
- Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/tharsis/ethermint`)
|
||||
- Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/evmos/ethermint`)
|
||||
- `git remote rename origin upstream`
|
||||
- `git remote add origin git@github.com:rigeyrigerige/ethermint.git`
|
||||
|
||||
@ -220,7 +220,7 @@ should be targeted against the release candidate branch.
|
||||
- `main` must never fail `make lint test test-race`
|
||||
- `main` should not fail `make lint`
|
||||
- no `--force` onto `main` (except when reverting a broken commit, which should seldom happen)
|
||||
- create a development branch either on github.com/tharsis/ethermint, or your fork (using `git remote add origin`)
|
||||
- create a development branch either on github.com/evmos/ethermint, or your fork (using `git remote add origin`)
|
||||
- before submitting a pull request, begin `git rebase` on top of `main`
|
||||
|
||||
### Pull Merge Procedure
|
||||
@ -235,10 +235,10 @@ should be targeted against the release candidate branch.
|
||||
- Create the release candidate branch `release/v<major>.<minor>.x` (going forward known as **RC**)
|
||||
and ensure it's protected against pushing from anyone except the release
|
||||
manager/coordinator
|
||||
- **no PRs targeting this branch should be merged unless exceptional circumstances arise**
|
||||
- **no PRs targeting this branch should be merged unless exceptional circumstances arise**
|
||||
- On the `RC` branch, prepare a new version section in the `CHANGELOG.md`
|
||||
- All links must be link-ified: `$ python ./scripts/linkify_changelog.py CHANGELOG.md`
|
||||
- Copy the entries into a `RELEASE_CHANGELOG.md`, this is needed so the bot knows which entries to add to the release page on GitHub.
|
||||
- All links must be link-ified: `$ python ./scripts/linkify_changelog.py CHANGELOG.md`
|
||||
- Copy the entries into a `RELEASE_CHANGELOG.md`, this is needed so the bot knows which entries to add to the release page on GitHub.
|
||||
- Kick off a large round of simulation testing (e.g. 400 seeds for 2k blocks)
|
||||
- If errors are found during the simulation testing, commit the fixes to `main`
|
||||
and push the changes to the `RC` branch
|
||||
@ -343,7 +343,7 @@ is broken up into three distinct stages: **Strategy Discovery**, **Concept Appro
|
||||
|
||||
- Architecture Decision Records (ADRs) may be proposed by any contributors or maintainers of Ethermint,
|
||||
and should follow the guidelines outlined in the
|
||||
[ADR Creation Process](https://github.com/tharsis/ethermint/blob/main/docs/architecture/PROCESS.md)
|
||||
[ADR Creation Process](https://github.com/evmos/ethermint/blob/main/docs/architecture/PROCESS.md)
|
||||
- After proposal, a time bound period for Request for Comment (RFC) on ADRs commences
|
||||
- ADRs are intended to be iterative, and may be merged into `main` while still in a `Proposed` status
|
||||
|
||||
@ -383,8 +383,8 @@ Members must:
|
||||
- Be active contributors to Ethermint, and furthermore should be continuously making substantial contributions
|
||||
to the project's codebase, review process, documentation and ADRs
|
||||
- Have stake in Ethermint, represented by:
|
||||
- Being a client / user of Ethermint
|
||||
- "[giving back](https://www.debian.org/social_contract)" to the software
|
||||
- Being a client / user of Ethermint
|
||||
- "[giving back](https://www.debian.org/social_contract)" to the software
|
||||
- Delegate representation in case of vacation or absence
|
||||
|
||||
Code owners need to maintain participation in the process, ideally as members of **Concept Approval Committee**
|
||||
|
@ -1,353 +0,0 @@
|
||||
# Cerc-io laconic gql
|
||||
|
||||
> Browser : http://localhost:9473 for gql
|
||||
|
||||
## Start server
|
||||
|
||||
```shell
|
||||
./build/laconicd 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -17,7 +17,7 @@ COPY . .
|
||||
RUN make build
|
||||
|
||||
# Final image
|
||||
FROM alpine:3.15
|
||||
FROM alpine:3.16.2
|
||||
|
||||
# Install ca-certificates
|
||||
RUN apk add --update ca-certificates jq
|
||||
|
120
Makefile
120
Makefile
@ -12,9 +12,12 @@ LACONIC_DIR = laconic
|
||||
BUILDDIR ?= $(CURDIR)/build
|
||||
SIMAPP = ./app
|
||||
HTTPS_GIT := https://github.com/cerc-io/laconicd.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)
|
||||
DOCKER := $(shell which docker)
|
||||
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8
|
||||
# RocksDB is a native dependency, so we don't assume the library is installed.
|
||||
# Instead, it must be explicitly enabled and we warn when it is not.
|
||||
ENABLE_ROCKSDB ?= false
|
||||
|
||||
export GO111MODULE = on
|
||||
|
||||
@ -49,9 +52,6 @@ ifeq ($(LEDGER_ENABLED),true)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS)))
|
||||
build_tags += gcc
|
||||
endif
|
||||
build_tags += $(BUILD_TAGS)
|
||||
build_tags := $(strip $(build_tags))
|
||||
|
||||
@ -69,27 +69,36 @@ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=laconic \
|
||||
-X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \
|
||||
-X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION)
|
||||
|
||||
# DB backend selection
|
||||
ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS)))
|
||||
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=cleveldb
|
||||
ifeq ($(ENABLE_ROCKSDB),true)
|
||||
BUILD_TAGS += rocksdb_build
|
||||
test_tags += rocksdb_build
|
||||
else
|
||||
$(warning RocksDB support is disabled; to build and test with RocksDB support, set ENABLE_ROCKSDB=true)
|
||||
endif
|
||||
|
||||
# DB backend selection
|
||||
ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS)))
|
||||
BUILD_TAGS += gcc
|
||||
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)))
|
||||
ifneq ($(ENABLE_ROCKSDB),true)
|
||||
$(error Cannot use RocksDB backend unless ENABLE_ROCKSDB=true)
|
||||
endif
|
||||
CGO_ENABLED=1
|
||||
BUILD_TAGS += rocksdb
|
||||
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=rocksdb
|
||||
endif
|
||||
# handle boltdb
|
||||
ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS)))
|
||||
BUILD_TAGS += boltdb
|
||||
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))
|
||||
|
||||
@ -97,20 +106,11 @@ 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,15 +122,15 @@ 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
|
||||
.PHONY: build build-linux
|
||||
|
||||
docker-build:
|
||||
# TODO replace with kaniko
|
||||
@ -138,12 +138,12 @@ docker-build:
|
||||
docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${DOCKER_IMAGE}:latest
|
||||
# docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${DOCKER_IMAGE}:${COMMIT_HASH}
|
||||
# update old container
|
||||
docker rm ethermint || true
|
||||
docker rm laconicd || true
|
||||
# create a new container from the latest image
|
||||
docker create --name ethermint -t -i cerc-io/laconicd:latest ethermint
|
||||
docker create --name laconic -t -i cerc-io/laconicd:latest laconicd
|
||||
# move the binaries to the ./build directory
|
||||
mkdir -p ./build/
|
||||
docker cp ethermint:/usr/bin/ethermintd ./build/
|
||||
docker cp laconic:/usr/bin/laconicd ./build/
|
||||
|
||||
$(MOCKS_DIR):
|
||||
mkdir -p $(MOCKS_DIR)
|
||||
@ -167,7 +167,7 @@ build-all: tools build lint test
|
||||
###############################################################################
|
||||
|
||||
PACKAGE_NAME:=github.com/cerc-io/laconicd
|
||||
GOLANG_CROSS_VERSION = v1.17.1
|
||||
GOLANG_CROSS_VERSION = v1.18
|
||||
GOPATH ?= '$(HOME)/go'
|
||||
release-dry-run:
|
||||
docker run \
|
||||
@ -178,8 +178,8 @@ release-dry-run:
|
||||
-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
|
||||
ghcr.io/goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
|
||||
--rm-dist --skip-validate --skip-publish --snapshot
|
||||
|
||||
release:
|
||||
@if [ ! -f ".release-env" ]; then \
|
||||
@ -194,7 +194,7 @@ release:
|
||||
-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} \
|
||||
ghcr.io/goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
|
||||
release --rm-dist --skip-validate
|
||||
|
||||
.PHONY: release-dry-run release
|
||||
@ -215,7 +215,7 @@ RUNSIM = $(TOOLS_DESTDIR)/runsim
|
||||
runsim: $(RUNSIM)
|
||||
$(RUNSIM):
|
||||
@echo "Installing runsim..."
|
||||
@(cd /tmp && ${GO_MOD} go get github.com/cosmos/tools/cmd/runsim@master)
|
||||
@(cd /tmp && ${GO_MOD} go install github.com/cosmos/tools/cmd/runsim@master)
|
||||
|
||||
statik: $(STATIK)
|
||||
$(STATIK):
|
||||
@ -251,14 +251,6 @@ else
|
||||
@echo "protoc-gen-go already installed; skipping..."
|
||||
endif
|
||||
|
||||
ifeq (, $(shell which protoc))
|
||||
@echo "Please istalling protobuf according to your OS"
|
||||
@echo "macOS: brew install protobuf"
|
||||
@echo "linux: apt-get install -f -y protobuf-compiler"
|
||||
else
|
||||
@echo "protoc already installed; skipping..."
|
||||
endif
|
||||
|
||||
ifeq (, $(shell which solcjs))
|
||||
@echo "Installing solcjs..."
|
||||
@npm install -g solc@0.5.11
|
||||
@ -341,6 +333,12 @@ test-rpc:
|
||||
test-integration:
|
||||
./scripts/integration-test-all.sh -t "integration" -q 1 -z 1 -s 2 -m "integration" -r "true"
|
||||
|
||||
run-integration-tests:
|
||||
@nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh
|
||||
|
||||
.PHONY: run-integration-tests
|
||||
|
||||
|
||||
test-rpc-pending:
|
||||
./scripts/integration-test-all.sh -t "pending" -q 1 -z 1 -s 2 -m "pending" -r "true"
|
||||
|
||||
@ -356,10 +354,9 @@ test-sim-nondeterminism:
|
||||
@go test -mod=readonly $(SIMAPP) -run TestAppStateDeterminism -Enabled=true \
|
||||
-NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h
|
||||
|
||||
test-sim-custom-genesis-fast:
|
||||
@echo "Running custom genesis simulation..."
|
||||
@echo "By default, ${HOME}/.$(LACONIC_DIR)/config/genesis.json will be used."
|
||||
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.$(LACONIC_DIR)/config/genesis.json \
|
||||
test-sim-random-genesis-fast:
|
||||
@echo "Running random genesis simulation..."
|
||||
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation \
|
||||
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
|
||||
|
||||
test-sim-import-export: runsim
|
||||
@ -370,10 +367,9 @@ test-sim-after-import: runsim
|
||||
@echo "Running application simulation-after-import. This may take several minutes..."
|
||||
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport
|
||||
|
||||
test-sim-custom-genesis-multi-seed: runsim
|
||||
test-sim-random-genesis-multi-seed: runsim
|
||||
@echo "Running multi-seed custom genesis simulation..."
|
||||
@echo "By default, ${HOME}/.$(LACONIC_DIR)/config/genesis.json will be used."
|
||||
@$(BINDIR)/runsim -Genesis=${HOME}/.$(LACONIC_DIR)/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
|
||||
@$(BINDIR)/runsim -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
|
||||
|
||||
test-sim-multi-seed-long: runsim
|
||||
@echo "Running long multi-seed application simulation. This may take awhile!"
|
||||
@ -408,14 +404,19 @@ benchmark:
|
||||
###############################################################################
|
||||
|
||||
lint:
|
||||
golangci-lint run --out-format=tab
|
||||
@@test -n "$$golangci-lint version | awk '$4 >= 1.42')"
|
||||
golangci-lint run --out-format=tab -n
|
||||
|
||||
lint-py:
|
||||
flake8 --show-source --count --statistics \
|
||||
--format="::error file=%(path)s,line=%(row)d,col=%(col)d::%(path)s:%(row)d:%(col)d: %(code)s %(text)s" \
|
||||
|
||||
format:
|
||||
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/docs/statik/statik.go" -not -name '*.pb.go' -not -name '*.pb.gw.go' | xargs gofumpt -d -e -extra
|
||||
|
||||
lint-fix:
|
||||
golangci-lint run --fix --out-format=tab --issues-exit-code=0
|
||||
.PHONY: lint lint-fix
|
||||
.PHONY: lint lint-fix lint-py
|
||||
|
||||
format-fix:
|
||||
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/docs/statik/statik.go" -not -name '*.pb.go' -not -name '*.pb.gw.go' | xargs gofumpt -w -s
|
||||
@ -426,17 +427,18 @@ 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
|
||||
|
||||
proto-swagger-gen:
|
||||
@ -508,19 +510,19 @@ ifeq ($(OS),Windows_NT)
|
||||
mkdir localnet-setup &
|
||||
@$(MAKE) localnet-build
|
||||
|
||||
IF not exist "build/node0/$(LACONIC_BINARY)/config/genesis.json" docker run --rm -v $(CURDIR)/build\ethermint\Z laconicd/node sh -c "laconicd testnet init-files --v 4 --keyring-backend=test"
|
||||
IF not exist "build/node0/$(LACONIC_BINARY)/config/genesis.json" docker run --rm -v $(CURDIR)/build\laconicd\Z laconicd/node "./laconicd testnet --v 4 -o /laconicd --keyring-backend=test --ip-addresses laconicdnode0,laconicdnode1,laconicdnode2,laconicdnode3"
|
||||
docker-compose up -d
|
||||
else
|
||||
mkdir -p localnet-setup
|
||||
@$(MAKE) localnet-build
|
||||
|
||||
if ! [ -f localnet-setup/node0/$(LACONIC_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/localnet-setup:/localnet-setup:Z laconicd/node sh -c "laconicd testnet init-files --v 4 --keyring-backend=test"; fi
|
||||
if ! [ -f localnet-setup/node0/$(LACONIC_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/localnet-setup:/localnet-setup:Z laconicd/node "./laconicd testnet --v 4 -o /laconicd --keyring-backend=test --ip-addresses laconicdnode0,laconicdnode1,laconicdnode2,laconicdnode3"; fi
|
||||
docker-compose up -d
|
||||
endif
|
||||
|
||||
# Stop testnet
|
||||
localnet-stop:
|
||||
docker-compose down -v
|
||||
docker-compose down
|
||||
|
||||
# Clean testnet
|
||||
localnet-clean:
|
||||
@ -531,8 +533,8 @@ localnet-clean:
|
||||
localnet-unsafe-reset:
|
||||
docker-compose down
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@docker run --rm -v $(CURDIR)\localnet-setup\node0\laconicd:laconic\Z laconicd/node "laconicd unsafe-reset-all --home=/laconic"
|
||||
@docker run --rm -v $(CURDIR)\localnet-setup\node1\laconicd:laconic\Z laconicd/node "laconicd unsafe-reset-all --home=/laconic"
|
||||
@docker run --rm -v $(CURDIR)\localnet-setup\node0\laconicd:laconic\Z laconicd/node "laconicd unsafe-reset-all --home=/laconic"
|
||||
@docker run --rm -v $(CURDIR)\localnet-setup\node2\laconicd:laconic\Z laconicd/node "laconicd unsafe-reset-all --home=/laconic"
|
||||
@docker run --rm -v $(CURDIR)\localnet-setup\node3\laconicd:laconic\Z laconicd/node "laconicd unsafe-reset-all --home=/laconic"
|
||||
else
|
||||
@ -546,4 +548,4 @@ endif
|
||||
localnet-show-logstream:
|
||||
docker-compose logs --tail=1000 -f
|
||||
|
||||
.PHONY: build-docker-local-ethermint localnet-start localnet-stop
|
||||
.PHONY: build-docker-local-laconic localnet-start localnet-stop
|
||||
|
68
README.md
68
README.md
@ -1,24 +1,78 @@
|
||||
# Laconic Network
|
||||
The Source of Proof. Laconic is a next generation data availability & verifiability layer with cryptographic proofs, powering internet-scale Web3 applications, 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.
|
||||
<!--
|
||||
parent:
|
||||
order: false
|
||||
-->
|
||||
|
||||
**Note**: Requires [Go 1.17+](https://golang.org/dl/)
|
||||
<div align="center">
|
||||
<h1> Ethermint </h1>
|
||||
</div>
|
||||
|
||||
![banner](docs/ethermint.jpg)
|
||||
|
||||
<div align="center">
|
||||
<a href="https://github.com/evmos/ethermint/releases/latest">
|
||||
<img alt="Version" src="https://img.shields.io/github/tag/tharsis/ethermint.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/evmos/ethermint/blob/main/LICENSE">
|
||||
<img alt="License: Apache-2.0" src="https://img.shields.io/github/license/tharsis/ethermint.svg" />
|
||||
</a>
|
||||
<a href="https://pkg.go.dev/github.com/evmos/ethermint">
|
||||
<img alt="GoDoc" src="https://godoc.org/github.com/evmos/ethermint?status.svg" />
|
||||
</a>
|
||||
<a href="https://goreportcard.com/report/github.com/evmos/ethermint">
|
||||
<img alt="Go report card" src="https://goreportcard.com/badge/github.com/evmos/ethermint"/>
|
||||
</a>
|
||||
<a href="https://bestpractices.coreinfrastructure.org/projects/5018">
|
||||
<img alt="Lines of code" src="https://img.shields.io/tokei/lines/github/tharsis/ethermint">
|
||||
</a>
|
||||
</div>
|
||||
<div align="center">
|
||||
<a href="https://discord.gg/trje9XuAmy">
|
||||
<img alt="Discord" src="https://img.shields.io/discord/809048090249134080.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/evmos/ethermint/actions?query=branch%3Amain+workflow%3ALint">
|
||||
<img alt="Lint Status" src="https://github.com/evmos/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>
|
||||
</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.
|
||||
|
||||
**Note**: Requires [Go 1.18+](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:
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
Or check out the latest [release](https://github.com/evmos/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).
|
||||
|
||||
For an example on how Ethermint can be used on any Cosmos-SDK chain, please refer to [Evmos](https://www.github.com/tharsis/evmos).
|
||||
|
||||
## Community
|
||||
|
||||
The following chat channels and forums are a great spot to ask questions about Ethermint:
|
||||
|
||||
- [Laconic Twitter](https://twitter.com/laconicnetwork)
|
||||
- [Discord](https://discord.com/invite/ukhbBemyxY)
|
||||
- [Website](https://laconic.com)
|
||||
- [Evmos Twitter](https://twitter.com/EvmosOrg)
|
||||
- [Evmos Discord](https://discord.gg/trje9XuAmy)
|
||||
- [Evmos Telegram](https://t.me/EvmosOrg)
|
||||
- [Tharsis Twitter](https://twitter.com/TharsisHQ)
|
||||
|
||||
## Contributing
|
||||
|
||||
Looking for a good place to start contributing? Check out some [`good first issues`](https://github.com/cerc-io/laconicd/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
|
||||
Looking for a good place to start contributing? Check out some [`good first issues`](https://github.com/evmos/ethermint/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
|
||||
|
||||
For additional instructions, standards and style guides, please refer to the [Contributing](./CONTRIBUTING.md) document.
|
||||
|
||||
## 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.
|
||||
|
@ -1,17 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
cmdcfg "github.com/cerc-io/laconicd/cmd/config"
|
||||
)
|
||||
|
||||
// sdk config
|
||||
func init() {
|
||||
config := sdk.GetConfig()
|
||||
cmdcfg.SetBech32Prefixes(config)
|
||||
cmdcfg.SetBip44CoinType(config)
|
||||
config.Seal()
|
||||
|
||||
cmdcfg.RegisterDenoms()
|
||||
}
|
@ -23,7 +23,11 @@ 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(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
if err := options.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(
|
||||
ctx sdk.Context, tx sdk.Tx, sim bool,
|
||||
) (newCtx sdk.Context, err error) {
|
||||
@ -42,6 +46,9 @@ func NewAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
|
||||
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
|
||||
anteHandler = newCosmosAnteHandlerEip712(options)
|
||||
case "/ethermint.types.v1.ExtensionOptionDynamicFeeTx":
|
||||
// cosmos-sdk tx with dynamic fee extension
|
||||
anteHandler = newCosmosAnteHandler(options)
|
||||
default:
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownExtensionOptions,
|
||||
@ -62,7 +69,7 @@ func NewAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
}
|
||||
|
||||
return anteHandler(ctx, tx, sim)
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Recover(logger tmlog.Logger, err *error) {
|
||||
|
@ -1,10 +1,16 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/authz"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
@ -12,22 +18,27 @@ import (
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
ethparams "github.com/ethereum/go-ethereum/params"
|
||||
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestAnteHandler() {
|
||||
suite.enableFeemarket = false
|
||||
suite.SetupTest() // reset
|
||||
|
||||
var acc authtypes.AccountI
|
||||
addr, privKey := tests.NewAddrKey()
|
||||
to := tests.GenerateAddress()
|
||||
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
|
||||
suite.Require().NoError(acc.SetSequence(1))
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
setup := func() {
|
||||
suite.enableFeemarket = false
|
||||
suite.SetupTest() // reset
|
||||
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000))
|
||||
acc = suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
|
||||
suite.Require().NoError(acc.SetSequence(1))
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100))
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000))
|
||||
|
||||
suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100))
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@ -62,7 +73,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
func() sdk.Tx {
|
||||
signedContractTx := evmtypes.NewTxContract(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
2,
|
||||
1,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
big.NewInt(150),
|
||||
@ -83,7 +94,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
func() sdk.Tx {
|
||||
signedContractTx := evmtypes.NewTxContract(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
3,
|
||||
1,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
big.NewInt(150),
|
||||
@ -104,7 +115,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
func() sdk.Tx {
|
||||
signedTx := evmtypes.NewTx(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
4,
|
||||
1,
|
||||
&to,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
@ -126,7 +137,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
func() sdk.Tx {
|
||||
signedTx := evmtypes.NewTx(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
5,
|
||||
1,
|
||||
&to,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
@ -148,7 +159,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
func() sdk.Tx {
|
||||
signedTx := evmtypes.NewTx(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
6,
|
||||
1,
|
||||
&to,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
@ -169,7 +180,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
func() sdk.Tx {
|
||||
signedTx := evmtypes.NewTx(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
7,
|
||||
1,
|
||||
&to,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
@ -188,7 +199,7 @@ 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(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
|
||||
signedTx.From = addr.Hex()
|
||||
|
||||
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
|
||||
@ -200,7 +211,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
{
|
||||
"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(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
|
||||
signedTx.From = addr.Hex()
|
||||
|
||||
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
|
||||
@ -211,7 +222,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
{
|
||||
"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 := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil)
|
||||
signedTx.From = addr.Hex()
|
||||
|
||||
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false, true)
|
||||
@ -273,7 +284,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
|
||||
expFee := txData.Fee()
|
||||
invalidFee := new(big.Int).Add(expFee, big.NewInt(1))
|
||||
invalidFeeAmount := sdk.Coins{sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(invalidFee))}
|
||||
invalidFeeAmount := sdk.Coins{sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewIntFromBigInt(invalidFee))}
|
||||
txBuilder.SetFeeAmount(invalidFeeAmount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
@ -298,20 +309,95 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
"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)
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas))))
|
||||
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()
|
||||
gas := uint64(200000)
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas)))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgDelegate(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 create validator",
|
||||
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)
|
||||
txBuilder := suite.CreateTestEIP712MsgCreateValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 MsgSubmitProposal",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
gasAmount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
// reusing the gasAmount for deposit
|
||||
deposit := sdk.NewCoins(coinAmount)
|
||||
txBuilder := suite.CreateTestEIP712SubmitProposal(from, privKey, "ethermint_9000-1", gas, gasAmount, deposit)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 MsgGrant",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
grantee := sdk.AccAddress("_______grantee______")
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
gasAmount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
blockTime := time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)
|
||||
expiresAt := blockTime.Add(time.Hour)
|
||||
msg, err := authz.NewMsgGrant(
|
||||
from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
|
||||
{
|
||||
"success- DeliverTx EIP712 MsgGrantAllowance",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
gasAmount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712GrantAllowance(from, privKey, "ethermint_9000-1", gas, gasAmount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 edit validator",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
{
|
||||
"success- DeliverTx EIP712 submit evidence",
|
||||
func() sdk.Tx {
|
||||
from := acc.GetAddress()
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, true,
|
||||
},
|
||||
@ -319,8 +405,8 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
"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)
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas))))
|
||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9002-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
@ -329,11 +415,11 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
"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)
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas))))
|
||||
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))))
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(30))))
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
@ -341,8 +427,8 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
"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)
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas))))
|
||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||
sigsV2 := signing.SignatureV2{}
|
||||
txBuilder.SetSignatures(sigsV2)
|
||||
@ -353,8 +439,8 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
"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)
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas))))
|
||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
@ -373,8 +459,8 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
"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)
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100*int64(gas))))
|
||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
@ -389,10 +475,33 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
return txBuilder.GetTx()
|
||||
}, false, false, false,
|
||||
},
|
||||
{
|
||||
"fails - invalid from",
|
||||
func() sdk.Tx {
|
||||
msg := evmtypes.NewTxContract(
|
||||
suite.app.EvmKeeper.ChainID(),
|
||||
1,
|
||||
big.NewInt(10),
|
||||
100000,
|
||||
big.NewInt(150),
|
||||
big.NewInt(200),
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
msg.From = addr.Hex()
|
||||
tx := suite.CreateTestTx(msg, privKey, 1, false)
|
||||
msg = tx.GetMsgs()[0].(*evmtypes.MsgEthereumTx)
|
||||
msg.From = addr.Hex()
|
||||
return tx
|
||||
}, true, false, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
setup()
|
||||
|
||||
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
|
||||
|
||||
// expConsumed := params.TxGasContractCreation + params.TxGas
|
||||
@ -425,18 +534,17 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -448,18 +556,17 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -471,18 +578,17 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -494,19 +600,18 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -518,19 +623,18 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -542,19 +646,18 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -566,19 +669,18 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -590,19 +692,18 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -616,19 +717,18 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -641,18 +741,17 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
{
|
||||
"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 := 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)
|
||||
@ -686,3 +785,132 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||
suite.enableFeemarket = false
|
||||
suite.enableLondonHF = true
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestAnteHandlerWithParams() {
|
||||
addr, privKey := tests.NewAddrKey()
|
||||
to := tests.GenerateAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
txFn func() sdk.Tx
|
||||
enableCall bool
|
||||
enableCreate bool
|
||||
expErr error
|
||||
}{
|
||||
{
|
||||
"fail - Contract Creation Disabled",
|
||||
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,
|
||||
evmtypes.ErrCreateDisabled,
|
||||
},
|
||||
{
|
||||
"success - Contract Creation Enabled",
|
||||
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,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"fail - EVM Call Disabled",
|
||||
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
|
||||
},
|
||||
false, true,
|
||||
evmtypes.ErrCallDisabled,
|
||||
},
|
||||
{
|
||||
"success - EVM Call Enabled",
|
||||
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,
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.evmParamsOption = func(params *evmtypes.Params) {
|
||||
params.EnableCall = tc.enableCall
|
||||
params.EnableCreate = tc.enableCreate
|
||||
}
|
||||
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(true)
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000))
|
||||
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
|
||||
if tc.expErr == nil {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
suite.Require().True(errors.Is(err, tc.expErr))
|
||||
}
|
||||
})
|
||||
}
|
||||
suite.evmParamsOption = nil
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*Package ante defines the SDK auth module's AnteHandler as well as an internal
|
||||
/*
|
||||
Package ante defines the SDK auth module's AnteHandler as well as an internal
|
||||
AnteHandler for an Ethereum transaction (i.e MsgEthereumTx).
|
||||
|
||||
During CheckTx, the transaction is passed through a series of
|
||||
|
@ -49,7 +49,11 @@ func NewEip712SigVerificationDecorator(ak evmtypes.AccountKeeper, signModeHandle
|
||||
|
||||
// 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) {
|
||||
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)
|
||||
@ -188,13 +192,7 @@ func VerifySignature(
|
||||
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)
|
||||
extOpt, ok := opts[0].GetCachedValue().(*ethermint.ExtensionOptionsWeb3Tx)
|
||||
if !ok {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "unknown extension option")
|
||||
}
|
||||
|
204
app/ante/eth.go
204
app/ante/eth.go
@ -2,7 +2,11 @@ package ante
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
@ -49,12 +53,18 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
sender, err := signer.Sender(msgEthTx.AsTransaction())
|
||||
ethTx := msgEthTx.AsTransaction()
|
||||
if !params.AllowUnprotectedTxs && !ethTx.Protected() {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrNotSupported,
|
||||
"rejected unprotected Ethereum txs. Please EIP155 sign your transaction to protect it against replay-attacks")
|
||||
}
|
||||
|
||||
sender, err := signer.Sender(ethTx)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrorInvalidSigner,
|
||||
"couldn't retrieve sender address ('%s') from the ethereum transaction: %s",
|
||||
msgEthTx.From,
|
||||
"couldn't retrieve sender address from the ethereum transaction: %s",
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
@ -68,17 +78,15 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
|
||||
|
||||
// EthAccountVerificationDecorator validates an account balance checks
|
||||
type EthAccountVerificationDecorator struct {
|
||||
ak evmtypes.AccountKeeper
|
||||
bankKeeper evmtypes.BankKeeper
|
||||
evmKeeper EVMKeeper
|
||||
ak evmtypes.AccountKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthAccountVerificationDecorator creates a new EthAccountVerificationDecorator
|
||||
func NewEthAccountVerificationDecorator(ak evmtypes.AccountKeeper, bankKeeper evmtypes.BankKeeper, ek EVMKeeper) EthAccountVerificationDecorator {
|
||||
func NewEthAccountVerificationDecorator(ak evmtypes.AccountKeeper, ek EVMKeeper) EthAccountVerificationDecorator {
|
||||
return EthAccountVerificationDecorator{
|
||||
ak: ak,
|
||||
bankKeeper: bankKeeper,
|
||||
evmKeeper: ek,
|
||||
ak: ak,
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +96,12 @@ func NewEthAccountVerificationDecorator(ak evmtypes.AccountKeeper, bankKeeper ev
|
||||
// - any of the msgs is not a MsgEthereumTx
|
||||
// - from address is empty
|
||||
// - account balance is lower than the transaction cost
|
||||
func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
func (avd EthAccountVerificationDecorator) AnteHandle(
|
||||
ctx sdk.Context,
|
||||
tx sdk.Tx,
|
||||
simulate bool,
|
||||
next sdk.AnteHandler,
|
||||
) (newCtx sdk.Context, err error) {
|
||||
if !ctx.IsCheckTx() {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
@ -112,7 +125,7 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
|
||||
|
||||
// check whether the sender address is EOA
|
||||
fromAddr := common.BytesToAddress(from)
|
||||
acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
|
||||
acct := avd.evmKeeper.GetAccount(ctx, fromAddr) //nolint: all
|
||||
|
||||
if acct == nil {
|
||||
acc := avd.ak.NewAccountWithAddress(ctx, from)
|
||||
@ -123,10 +136,9 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
|
||||
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
||||
}
|
||||
|
||||
if err := evmkeeper.CheckSenderBalance(sdk.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||
if err := evmkeeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
|
||||
}
|
||||
|
||||
}
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
@ -163,7 +175,7 @@ func NewEthGasConsumeDecorator(
|
||||
// - 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) {
|
||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
params := egcd.evmKeeper.GetParams(ctx)
|
||||
|
||||
ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
|
||||
@ -176,6 +188,9 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
gasWanted := uint64(0)
|
||||
var events sdk.Events
|
||||
|
||||
// Use the lowest priority of all the messages as the final one.
|
||||
minPriority := int64(math.MaxInt64)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
@ -187,7 +202,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
||||
}
|
||||
|
||||
if ctx.IsCheckTx() {
|
||||
if ctx.IsCheckTx() && egcd.maxGasWanted != 0 {
|
||||
// We can't trust the tx gas limit, because we'll refund the unused gas.
|
||||
if txData.GetGas() > egcd.maxGasWanted {
|
||||
gasWanted += egcd.maxGasWanted
|
||||
@ -198,7 +213,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
gasWanted += txData.GetGas()
|
||||
}
|
||||
|
||||
fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
||||
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
||||
ctx,
|
||||
*msgEthTx,
|
||||
txData,
|
||||
@ -212,6 +227,9 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
}
|
||||
|
||||
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
|
||||
if priority < minPriority {
|
||||
minPriority = priority
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change to typed events
|
||||
@ -233,8 +251,10 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
||||
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
||||
|
||||
newCtx := ctx.WithPriority(minPriority)
|
||||
|
||||
// we know that we have enough gas on the pool to cover the intrinsic gas
|
||||
return next(ctx, tx, simulate)
|
||||
return next(newCtx, tx, simulate)
|
||||
}
|
||||
|
||||
// CanTransferDecorator checks if the sender is allowed to transfer funds according to the EVM block
|
||||
@ -263,7 +283,7 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
baseFee := ctd.evmKeeper.BaseFee(ctx, ethCfg)
|
||||
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
||||
if err != nil {
|
||||
@ -285,7 +305,7 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
|
||||
// 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()) {
|
||||
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",
|
||||
@ -397,65 +417,82 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
|
||||
|
||||
// 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")
|
||||
wrapperTx, ok := tx.(protoTxProvider)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid tx type %T, didn't implement interface protoTxProvider", tx)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
params := vbd.evmKeeper.GetParams(ctx)
|
||||
chainID := vbd.evmKeeper.ChainID()
|
||||
ethCfg := params.ChainConfig.EthereumConfig(chainID)
|
||||
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
if len(body.ExtensionOptions) != 1 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
|
||||
// Validate `From` field
|
||||
if msgEthTx.From != "" {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid From %s, expect empty string", msgEthTx.From)
|
||||
}
|
||||
|
||||
txFee := sdk.Coins{}
|
||||
txGasLimit := uint64(0)
|
||||
txGasLimit += msgEthTx.GetGas()
|
||||
|
||||
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())))
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
|
||||
}
|
||||
|
||||
authInfo := protoTx.AuthInfo
|
||||
if len(authInfo.SignerInfos) > 0 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
|
||||
// return error if contract creation or call are disabled through governance
|
||||
if !params.EnableCreate && txData.GetTo() == nil {
|
||||
return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
|
||||
} else if !params.EnableCall && txData.GetTo() != nil {
|
||||
return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
|
||||
}
|
||||
|
||||
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 baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
|
||||
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
|
||||
}
|
||||
|
||||
if !authInfo.Fee.Amount.IsEqual(txFee) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
|
||||
}
|
||||
txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdkmath.NewIntFromBigInt(txData.Fee())))
|
||||
}
|
||||
|
||||
if authInfo.Fee.GasLimit != txGasLimit {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
|
||||
}
|
||||
authInfo := protoTx.AuthInfo
|
||||
if len(authInfo.SignerInfos) > 0 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
|
||||
}
|
||||
|
||||
sigs := protoTx.Signatures
|
||||
if len(sigs) > 0 {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures 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 next(ctx, tx, simulate)
|
||||
@ -511,7 +548,7 @@ func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat
|
||||
if ctx.IsCheckTx() && !simulate {
|
||||
params := mfd.evmKeeper.GetParams(ctx)
|
||||
ethCfg := params.ChainConfig.EthereumConfig(mfd.evmKeeper.ChainID())
|
||||
baseFee := mfd.evmKeeper.BaseFee(ctx, ethCfg)
|
||||
baseFee := mfd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
if baseFee == nil {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
@ -532,3 +569,36 @@ func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthEmitEventDecorator emit events in ante handler in case of tx execution failed (out of block gas limit).
|
||||
type EthEmitEventDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthEmitEventDecorator creates a new EthEmitEventDecorator
|
||||
func NewEthEmitEventDecorator(evmKeeper EVMKeeper) EthEmitEventDecorator {
|
||||
return EthEmitEventDecorator{evmKeeper}
|
||||
}
|
||||
|
||||
// AnteHandle emits some basic events for the eth messages
|
||||
func (eeed EthEmitEventDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// After eth tx passed ante handler, the fee is deducted and nonce increased, it shouldn't be ignored by json-rpc,
|
||||
// we need to emit some basic events at the very end of ante handler to be indexed by tendermint.
|
||||
txIndex := eeed.evmKeeper.GetTxIndexTransient(ctx)
|
||||
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))
|
||||
}
|
||||
|
||||
// emit ethereum tx hash as event, should be indexed by tm tx indexer for query purpose.
|
||||
// it's emitted in ante handler so we can query failed transaction (out of block gas limit).
|
||||
ctx.EventManager().EmitEvent(sdk.NewEvent(
|
||||
evmtypes.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msgEthTx.Hash),
|
||||
sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(txIndex+uint64(i), 10)),
|
||||
))
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -14,12 +15,7 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
func nextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
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)
|
||||
@ -27,26 +23,40 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
||||
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
unprotectedTx := evmtypes.NewTxContract(nil, 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
unprotectedTx.From = addr.Hex()
|
||||
err = unprotectedTx.Sign(ethtypes.HomesteadSigner{}, tests.NewSigner(privKey))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
reCheckTx bool
|
||||
expPass bool
|
||||
name string
|
||||
tx sdk.Tx
|
||||
allowUnprotectedTxs bool
|
||||
reCheckTx bool
|
||||
expPass bool
|
||||
}{
|
||||
{"ReCheckTx", &invalidTx{}, true, false},
|
||||
{"invalid transaction type", &invalidTx{}, false, false},
|
||||
{"ReCheckTx", &invalidTx{}, false, true, false},
|
||||
{"invalid transaction type", &invalidTx{}, false, false, false},
|
||||
{
|
||||
"invalid sender",
|
||||
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
},
|
||||
{"successful signature verification", signedTx, false, true},
|
||||
{"successful signature verification", signedTx, false, false, true},
|
||||
{"invalid, reject unprotected txs", unprotectedTx, false, false, false},
|
||||
{"successful, allow unprotected txs", unprotectedTx, true, false, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
||||
suite.evmParamsOption = func(params *evmtypes.Params) {
|
||||
params.AllowUnprotectedTxs = tc.allowUnprotectedTxs
|
||||
}
|
||||
suite.SetupTest()
|
||||
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@ -55,11 +65,12 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
||||
}
|
||||
})
|
||||
}
|
||||
suite.evmParamsOption = nil
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
||||
dec := ante.NewEthAccountVerificationDecorator(
|
||||
suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper,
|
||||
suite.app.AccountKeeper, suite.app.EvmKeeper,
|
||||
)
|
||||
|
||||
addr := tests.GenerateAddress()
|
||||
@ -134,7 +145,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
||||
tc.malleate()
|
||||
suite.Require().NoError(vmdb.Commit())
|
||||
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(tc.checkTx), tc.tx, false, nextFn)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(tc.checkTx), tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@ -190,7 +201,7 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
tc.malleate()
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@ -210,41 +221,61 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), txGasLimit, big.NewInt(1), nil, nil, nil, nil)
|
||||
tx.From = addr.Hex()
|
||||
|
||||
ethCfg := suite.app.EvmKeeper.GetParams(suite.ctx).
|
||||
ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
|
||||
baseFee := suite.app.EvmKeeper.GetBaseFee(suite.ctx, ethCfg)
|
||||
suite.Require().Equal(int64(1000000000), baseFee.Int64())
|
||||
|
||||
gasPrice := new(big.Int).Add(baseFee, evmtypes.DefaultPriorityReduction.BigInt())
|
||||
|
||||
tx2GasLimit := uint64(1000000)
|
||||
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, big.NewInt(1), nil, nil, nil, ðtypes.AccessList{{Address: addr, StorageKeys: nil}})
|
||||
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, gasPrice, nil, nil, nil, ðtypes.AccessList{{Address: addr, StorageKeys: nil}})
|
||||
tx2.From = addr.Hex()
|
||||
tx2Priority := int64(1)
|
||||
|
||||
dynamicFeeTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit,
|
||||
nil, // gasPrice
|
||||
new(big.Int).Add(baseFee, big.NewInt(evmtypes.DefaultPriorityReduction.Int64()*2)), // gasFeeCap
|
||||
evmtypes.DefaultPriorityReduction.BigInt(), // gasTipCap
|
||||
nil, ðtypes.AccessList{{Address: addr, StorageKeys: nil}})
|
||||
dynamicFeeTx.From = addr.Hex()
|
||||
dynamicFeeTxPriority := int64(1)
|
||||
|
||||
var vmdb *statedb.StateDB
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
gasLimit uint64
|
||||
malleate func()
|
||||
expPass bool
|
||||
expPanic bool
|
||||
name string
|
||||
tx sdk.Tx
|
||||
gasLimit uint64
|
||||
malleate func()
|
||||
expPass bool
|
||||
expPanic bool
|
||||
expPriority int64
|
||||
}{
|
||||
{"invalid transaction type", &invalidTx{}, 0, func() {}, false, false},
|
||||
{"invalid transaction type", &invalidTx{}, math.MaxUint64, func() {}, false, false, 0},
|
||||
{
|
||||
"sender not found",
|
||||
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
|
||||
0,
|
||||
math.MaxUint64,
|
||||
func() {},
|
||||
false, false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"gas limit too low",
|
||||
tx,
|
||||
0,
|
||||
math.MaxUint64,
|
||||
func() {},
|
||||
false, false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"not enough balance for fees",
|
||||
tx2,
|
||||
0,
|
||||
math.MaxUint64,
|
||||
func() {},
|
||||
false, false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"not enough tx gas",
|
||||
@ -254,6 +285,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1000000))
|
||||
},
|
||||
false, true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"not enough block gas",
|
||||
@ -261,21 +293,32 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
0,
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1000000))
|
||||
|
||||
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1))
|
||||
},
|
||||
false, true,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"success",
|
||||
"success - legacy tx",
|
||||
tx2,
|
||||
config.DefaultMaxTxGasWanted, // it's capped
|
||||
tx2GasLimit, // it's capped
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1000000))
|
||||
|
||||
vmdb.AddBalance(addr, big.NewInt(1001000000000000))
|
||||
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(10000000000000000000))
|
||||
},
|
||||
true, false,
|
||||
tx2Priority,
|
||||
},
|
||||
{
|
||||
"success - dynamic fee tx",
|
||||
dynamicFeeTx,
|
||||
tx2GasLimit, // it's capped
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1001000000000000))
|
||||
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(10000000000000000000))
|
||||
},
|
||||
true, false,
|
||||
dynamicFeeTxPriority,
|
||||
},
|
||||
}
|
||||
|
||||
@ -287,19 +330,19 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
|
||||
if tc.expPanic {
|
||||
suite.Require().Panics(func() {
|
||||
_, _ = dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewGasMeter(1)), tc.tx, false, nextFn)
|
||||
_, _ = dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewGasMeter(1)), tc.tx, false, NextFn)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, nextFn)
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, NextFn)
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(tc.expPriority, ctx.Priority())
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
// TODO: needs to check the gasmeter limit issue
|
||||
// suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
|
||||
suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -377,7 +420,7 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
|
||||
tc.malleate()
|
||||
suite.Require().NoError(vmdb.Commit())
|
||||
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@ -456,12 +499,12 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
||||
|
||||
if tc.expPanic {
|
||||
suite.Require().Panics(func() {
|
||||
_, _ = dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
||||
_, _ = dec.AnteHandle(suite.ctx, tc.tx, false, NextFn)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@ -498,7 +541,7 @@ func (suite AnteTestSuite) TestEthSetupContextDecorator() {
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
|
143
app/ante/fee_checker.go
Normal file
143
app/ante/fee_checker.go
Normal file
@ -0,0 +1,143 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cerc-io/laconicd/x/evm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
)
|
||||
|
||||
// NewDynamicFeeChecker returns a `TxFeeChecker` that applies a dynamic fee to
|
||||
// Cosmos txs using the EIP-1559 fee market logic.
|
||||
// This can be called in both CheckTx and deliverTx modes.
|
||||
// a) feeCap = tx.fees / tx.gas
|
||||
// b) tipFeeCap = tx.MaxPriorityPrice (default) or MaxInt64
|
||||
// - when `ExtensionOptionDynamicFeeTx` is omitted, `tipFeeCap` defaults to `MaxInt64`.
|
||||
// - when london hardfork is not enabled, it fallbacks to SDK default behavior (validator min-gas-prices).
|
||||
// - Tx priority is set to `effectiveGasPrice / DefaultPriorityReduction`.
|
||||
func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker {
|
||||
return func(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) {
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return nil, 0, fmt.Errorf("tx must be a FeeTx")
|
||||
}
|
||||
|
||||
if ctx.BlockHeight() == 0 {
|
||||
// genesis transactions: fallback to min-gas-price logic
|
||||
return checkTxFeeWithValidatorMinGasPrices(ctx, feeTx)
|
||||
}
|
||||
|
||||
params := k.GetParams(ctx)
|
||||
denom := params.EvmDenom
|
||||
ethCfg := params.ChainConfig.EthereumConfig(k.ChainID())
|
||||
|
||||
baseFee := k.GetBaseFee(ctx, ethCfg)
|
||||
if baseFee == nil {
|
||||
// london hardfork is not enabled: fallback to min-gas-prices logic
|
||||
return checkTxFeeWithValidatorMinGasPrices(ctx, feeTx)
|
||||
}
|
||||
|
||||
// default to `MaxInt64` when there's no extension option.
|
||||
maxPriorityPrice := sdkmath.NewInt(math.MaxInt64)
|
||||
|
||||
// get the priority tip cap from the extension option.
|
||||
if hasExtOptsTx, ok := tx.(authante.HasExtensionOptionsTx); ok {
|
||||
for _, opt := range hasExtOptsTx.GetExtensionOptions() {
|
||||
if extOpt, ok := opt.GetCachedValue().(*ethermint.ExtensionOptionDynamicFeeTx); ok {
|
||||
maxPriorityPrice = extOpt.MaxPriorityPrice
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gas := feeTx.GetGas()
|
||||
feeCoins := feeTx.GetFee()
|
||||
fee := feeCoins.AmountOfNoDenomValidation(denom)
|
||||
|
||||
feeCap := fee.Quo(sdkmath.NewIntFromUint64(gas))
|
||||
baseFeeInt := sdkmath.NewIntFromBigInt(baseFee)
|
||||
|
||||
if feeCap.LT(baseFeeInt) {
|
||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient gas prices; got: %s required: %s", feeCap, baseFeeInt)
|
||||
}
|
||||
|
||||
// calculate the effective gas price using the EIP-1559 logic.
|
||||
effectivePrice := sdkmath.NewIntFromBigInt(types.EffectiveGasPrice(baseFeeInt.BigInt(), feeCap.BigInt(), maxPriorityPrice.BigInt()))
|
||||
|
||||
// NOTE: create a new coins slice without having to validate the denom
|
||||
effectiveFee := sdk.Coins{
|
||||
{
|
||||
Denom: denom,
|
||||
Amount: effectivePrice.Mul(sdkmath.NewIntFromUint64(gas)),
|
||||
},
|
||||
}
|
||||
|
||||
bigPriority := effectivePrice.Sub(baseFeeInt).Quo(types.DefaultPriorityReduction)
|
||||
priority := int64(math.MaxInt64)
|
||||
|
||||
if bigPriority.IsInt64() {
|
||||
priority = bigPriority.Int64()
|
||||
}
|
||||
|
||||
return effectiveFee, priority, nil
|
||||
}
|
||||
}
|
||||
|
||||
// checkTxFeeWithValidatorMinGasPrices implements the default fee logic, where the minimum price per
|
||||
// unit of gas is fixed and set by each validator, and the tx priority is computed from the gas price.
|
||||
func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.FeeTx) (sdk.Coins, int64, error) {
|
||||
feeCoins := tx.GetFee()
|
||||
gas := tx.GetGas()
|
||||
minGasPrices := ctx.MinGasPrices()
|
||||
|
||||
// Ensure 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.
|
||||
if ctx.IsCheckTx() && !minGasPrices.IsZero() {
|
||||
requiredFees := make(sdk.Coins, len(minGasPrices))
|
||||
|
||||
// Determine the required fees by multiplying each required minimum gas
|
||||
// price by the gas limit, where fee = ceil(minGasPrice * gasLimit).
|
||||
glDec := sdk.NewDec(int64(gas))
|
||||
|
||||
for i, gp := range minGasPrices {
|
||||
fee := gp.Amount.Mul(glDec)
|
||||
requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
|
||||
}
|
||||
|
||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
|
||||
}
|
||||
}
|
||||
|
||||
priority := getTxPriority(feeCoins, int64(gas))
|
||||
return feeCoins, priority, nil
|
||||
}
|
||||
|
||||
// getTxPriority returns a naive tx priority based on the amount of the smallest denomination of the gas price
|
||||
// provided in a transaction.
|
||||
func getTxPriority(fees sdk.Coins, gas int64) int64 {
|
||||
var priority int64
|
||||
|
||||
for _, fee := range fees {
|
||||
gasPrice := fee.Amount.QuoRaw(gas)
|
||||
amt := gasPrice.Quo(types.DefaultPriorityReduction)
|
||||
p := int64(math.MaxInt64)
|
||||
|
||||
if amt.IsInt64() {
|
||||
p = amt.Int64()
|
||||
}
|
||||
|
||||
if priority == 0 || p < priority {
|
||||
priority = p
|
||||
}
|
||||
}
|
||||
|
||||
return priority
|
||||
}
|
219
app/ante/fee_checker_test.go
Normal file
219
app/ante/fee_checker_test.go
Normal file
@ -0,0 +1,219 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cerc-io/laconicd/x/evm/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
var _ DynamicFeeEVMKeeper = MockEVMKeeper{}
|
||||
|
||||
type MockEVMKeeper struct {
|
||||
BaseFee *big.Int
|
||||
EnableLondonHF bool
|
||||
}
|
||||
|
||||
func (m MockEVMKeeper) GetBaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int {
|
||||
if m.EnableLondonHF {
|
||||
return m.BaseFee
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m MockEVMKeeper) GetParams(ctx sdk.Context) evmtypes.Params {
|
||||
return evmtypes.DefaultParams()
|
||||
}
|
||||
|
||||
func (m MockEVMKeeper) ChainID() *big.Int {
|
||||
return big.NewInt(9000)
|
||||
}
|
||||
|
||||
func TestSDKTxFeeChecker(t *testing.T) {
|
||||
// testCases:
|
||||
// fallback
|
||||
// genesis tx
|
||||
// checkTx, validate with min-gas-prices
|
||||
// deliverTx, no validation
|
||||
// dynamic fee
|
||||
// with extension option
|
||||
// without extension option
|
||||
// london hardfork enableness
|
||||
encodingConfig := encoding.MakeConfig(module.NewBasicManager())
|
||||
minGasPrices := sdk.NewDecCoins(sdk.NewDecCoin("aphoton", sdk.NewInt(10)))
|
||||
|
||||
genesisCtx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger())
|
||||
checkTxCtx := sdk.NewContext(nil, tmproto.Header{Height: 1}, true, log.NewNopLogger()).WithMinGasPrices(minGasPrices)
|
||||
deliverTxCtx := sdk.NewContext(nil, tmproto.Header{Height: 1}, false, log.NewNopLogger())
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctx sdk.Context
|
||||
keeper DynamicFeeEVMKeeper
|
||||
buildTx func() sdk.Tx
|
||||
expFees string
|
||||
expPriority int64
|
||||
expSuccess bool
|
||||
}{
|
||||
{
|
||||
"success, genesis tx",
|
||||
genesisCtx,
|
||||
MockEVMKeeper{},
|
||||
func() sdk.Tx {
|
||||
return encodingConfig.TxConfig.NewTxBuilder().GetTx()
|
||||
},
|
||||
"",
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail, min-gas-prices",
|
||||
checkTxCtx,
|
||||
MockEVMKeeper{},
|
||||
func() sdk.Tx {
|
||||
return encodingConfig.TxConfig.NewTxBuilder().GetTx()
|
||||
},
|
||||
"",
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"success, min-gas-prices",
|
||||
checkTxCtx,
|
||||
MockEVMKeeper{},
|
||||
func() sdk.Tx {
|
||||
txBuilder := encodingConfig.TxConfig.NewTxBuilder()
|
||||
txBuilder.SetGasLimit(1)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("aphoton", sdk.NewInt(10))))
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
"10aphoton",
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success, min-gas-prices deliverTx",
|
||||
deliverTxCtx,
|
||||
MockEVMKeeper{},
|
||||
func() sdk.Tx {
|
||||
return encodingConfig.TxConfig.NewTxBuilder().GetTx()
|
||||
},
|
||||
"",
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail, dynamic fee",
|
||||
deliverTxCtx,
|
||||
MockEVMKeeper{
|
||||
EnableLondonHF: true, BaseFee: big.NewInt(1),
|
||||
},
|
||||
func() sdk.Tx {
|
||||
txBuilder := encodingConfig.TxConfig.NewTxBuilder()
|
||||
txBuilder.SetGasLimit(1)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
"",
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"success, dynamic fee",
|
||||
deliverTxCtx,
|
||||
MockEVMKeeper{
|
||||
EnableLondonHF: true, BaseFee: big.NewInt(10),
|
||||
},
|
||||
func() sdk.Tx {
|
||||
txBuilder := encodingConfig.TxConfig.NewTxBuilder()
|
||||
txBuilder.SetGasLimit(1)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("aphoton", sdk.NewInt(10))))
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
"10aphoton",
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success, dynamic fee priority",
|
||||
deliverTxCtx,
|
||||
MockEVMKeeper{
|
||||
EnableLondonHF: true, BaseFee: big.NewInt(10),
|
||||
},
|
||||
func() sdk.Tx {
|
||||
txBuilder := encodingConfig.TxConfig.NewTxBuilder()
|
||||
txBuilder.SetGasLimit(1)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("aphoton", sdk.NewInt(10).Mul(types.DefaultPriorityReduction).Add(sdk.NewInt(10)))))
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
"10000010aphoton",
|
||||
10,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success, dynamic fee empty tipFeeCap",
|
||||
deliverTxCtx,
|
||||
MockEVMKeeper{
|
||||
EnableLondonHF: true, BaseFee: big.NewInt(10),
|
||||
},
|
||||
func() sdk.Tx {
|
||||
txBuilder := encodingConfig.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
|
||||
txBuilder.SetGasLimit(1)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("aphoton", sdk.NewInt(10).Mul(types.DefaultPriorityReduction))))
|
||||
|
||||
option, err := codectypes.NewAnyWithValue(ðermint.ExtensionOptionDynamicFeeTx{})
|
||||
require.NoError(t, err)
|
||||
txBuilder.SetExtensionOptions(option)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
"10aphoton",
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success, dynamic fee tipFeeCap",
|
||||
deliverTxCtx,
|
||||
MockEVMKeeper{
|
||||
EnableLondonHF: true, BaseFee: big.NewInt(10),
|
||||
},
|
||||
func() sdk.Tx {
|
||||
txBuilder := encodingConfig.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
|
||||
txBuilder.SetGasLimit(1)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("aphoton", sdk.NewInt(10).Mul(types.DefaultPriorityReduction).Add(sdk.NewInt(10)))))
|
||||
|
||||
option, err := codectypes.NewAnyWithValue(ðermint.ExtensionOptionDynamicFeeTx{
|
||||
MaxPriorityPrice: sdk.NewInt(5).Mul(types.DefaultPriorityReduction),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
txBuilder.SetExtensionOptions(option)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
"5000010aphoton",
|
||||
5,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fees, priority, err := NewDynamicFeeChecker(tc.keeper)(tc.ctx, tc.buildTx())
|
||||
if tc.expSuccess {
|
||||
require.Equal(t, tc.expFees, fees.String())
|
||||
require.Equal(t, tc.expPriority, priority)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
52
app/ante/fee_market.go
Normal file
52
app/ante/fee_market.go
Normal file
@ -0,0 +1,52 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store
|
||||
// for BaseFee calculation.
|
||||
// NOTE: This decorator does not perform any validation
|
||||
type GasWantedDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
feeMarketKeeper FeeMarketKeeper
|
||||
}
|
||||
|
||||
// NewGasWantedDecorator creates a new NewGasWantedDecorator
|
||||
func NewGasWantedDecorator(
|
||||
evmKeeper EVMKeeper,
|
||||
feeMarketKeeper FeeMarketKeeper,
|
||||
) GasWantedDecorator {
|
||||
return GasWantedDecorator{
|
||||
evmKeeper,
|
||||
feeMarketKeeper,
|
||||
}
|
||||
}
|
||||
|
||||
func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
params := gwd.evmKeeper.GetParams(ctx)
|
||||
ethCfg := params.ChainConfig.EthereumConfig(gwd.evmKeeper.ChainID())
|
||||
|
||||
blockHeight := big.NewInt(ctx.BlockHeight())
|
||||
isLondon := ethCfg.IsLondon(blockHeight)
|
||||
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok || !isLondon {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
gasWanted := feeTx.GetGas()
|
||||
feeMktParams := gwd.feeMarketKeeper.GetParams(ctx)
|
||||
|
||||
// Add total gasWanted to cumulative in block transientStore in FeeMarket module
|
||||
if feeMktParams.IsBaseFeeEnabled(ctx.BlockHeight()) {
|
||||
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store")
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
95
app/ante/fee_market_test.go
Normal file
95
app/ante/fee_market_test.go
Normal file
@ -0,0 +1,95 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/cerc-io/laconicd/app/ante"
|
||||
"github.com/cerc-io/laconicd/tests"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestGasWantedDecorator() {
|
||||
suite.enableFeemarket = true
|
||||
suite.SetupTest()
|
||||
dec := ante.NewGasWantedDecorator(suite.app.EvmKeeper, suite.app.FeeMarketKeeper)
|
||||
from, fromPrivKey := tests.NewAddrKey()
|
||||
to := tests.GenerateAddress()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
expectedGasWanted uint64
|
||||
malleate func() sdk.Tx
|
||||
}{
|
||||
{
|
||||
"Cosmos Tx",
|
||||
TestGasLimit,
|
||||
func() sdk.Tx {
|
||||
denom := evmtypes.DefaultEVMDenom
|
||||
testMsg := banktypes.MsgSend{
|
||||
FromAddress: "evmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp",
|
||||
ToAddress: "evmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn",
|
||||
Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}},
|
||||
}
|
||||
txBuilder := suite.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), "stake", &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
},
|
||||
{
|
||||
"Ethereum Legacy Tx",
|
||||
TestGasLimit,
|
||||
func() sdk.Tx {
|
||||
msg := suite.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), nil, nil, nil)
|
||||
return suite.CreateTestTx(msg, fromPrivKey, 1, false)
|
||||
},
|
||||
},
|
||||
{
|
||||
"Ethereum Access List Tx",
|
||||
TestGasLimit,
|
||||
func() sdk.Tx {
|
||||
emptyAccessList := ethtypes.AccessList{}
|
||||
msg := suite.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), nil, nil, &emptyAccessList)
|
||||
return suite.CreateTestTx(msg, fromPrivKey, 1, false)
|
||||
},
|
||||
},
|
||||
{
|
||||
"Ethereum Dynamic Fee Tx (EIP1559)",
|
||||
TestGasLimit,
|
||||
func() sdk.Tx {
|
||||
emptyAccessList := ethtypes.AccessList{}
|
||||
msg := suite.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), big.NewInt(100), big.NewInt(50), &emptyAccessList)
|
||||
return suite.CreateTestTx(msg, fromPrivKey, 1, false)
|
||||
},
|
||||
},
|
||||
{
|
||||
"EIP712 message",
|
||||
200000,
|
||||
func() sdk.Tx {
|
||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||
gas := uint64(200000)
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, from.Bytes())
|
||||
suite.Require().NoError(acc.SetSequence(1))
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
tx := suite.CreateTestEIP712TxBuilderMsgSend(acc.GetAddress(), fromPrivKey, suite.ctx.ChainID(), gas, amount)
|
||||
return tx.GetTx()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// cumulative gas wanted from all test transactions in the same block
|
||||
var expectedGasWanted uint64
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.malleate(), false, NextFn)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
gasWanted := suite.app.FeeMarketKeeper.GetTransientGasWanted(suite.ctx)
|
||||
expectedGasWanted += tc.expectedGasWanted
|
||||
suite.Require().Equal(expectedGasWanted, gasWanted)
|
||||
})
|
||||
}
|
||||
}
|
145
app/ante/fees.go
Normal file
145
app/ante/fees.go
Normal file
@ -0,0 +1,145 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// MinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies for both CheckTx and DeliverTx
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
// CONTRACT: Tx must implement FeeTx to use MinGasPriceDecorator
|
||||
type MinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
|
||||
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
||||
}
|
||||
|
||||
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
|
||||
// Short-circuit if min gas price is 0 or if simulating
|
||||
if minGasPrice.IsZero() || simulate {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
evmParams := mpd.evmKeeper.GetParams(ctx)
|
||||
minGasPrices := sdk.DecCoins{
|
||||
{
|
||||
Denom: evmParams.EvmDenom,
|
||||
Amount: minGasPrice,
|
||||
},
|
||||
}
|
||||
|
||||
feeCoins := feeTx.GetFee()
|
||||
gas := feeTx.GetGas()
|
||||
|
||||
requiredFees := make(sdk.Coins, 0)
|
||||
|
||||
// Determine the required fees by multiplying each required minimum gas
|
||||
// price by the gas limit, where fee = ceil(minGasPrice * gasLimit).
|
||||
gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(gas))
|
||||
|
||||
for _, gp := range minGasPrices {
|
||||
fee := gp.Amount.Mul(gasLimit).Ceil().RoundInt()
|
||||
if fee.IsPositive() {
|
||||
requiredFees = requiredFees.Add(sdk.Coin{Denom: gp.Denom, Amount: fee})
|
||||
}
|
||||
}
|
||||
|
||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee,
|
||||
"provided fee < minimum global fee (%s < %s). Please increase the gas price.",
|
||||
feeCoins,
|
||||
requiredFees)
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
type EthMinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
|
||||
// short-circuit if min gas price is 0
|
||||
if minGasPrice.IsZero() {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
paramsEvm := empd.evmKeeper.GetParams(ctx)
|
||||
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID())
|
||||
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
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),
|
||||
)
|
||||
}
|
||||
|
||||
feeAmt := ethMsg.GetFee()
|
||||
|
||||
// For dynamic transactions, GetFee() uses the GasFeeCap value, which
|
||||
// is the maximum gas price that the signer can pay. In practice, the
|
||||
// signer can pay less, if the block's BaseFee is lower. So, in this case,
|
||||
// we use the EffectiveFee. If the feemarket formula results in a BaseFee
|
||||
// that lowers EffectivePrice until it is < MinGasPrices, the users must
|
||||
// increase the GasTipCap (priority fee) until EffectivePrice > MinGasPrices.
|
||||
// Transactions with MinGasPrices * gasUsed < tx fees < EffectiveFee are rejected
|
||||
// by the feemarket AnteHandle
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(ethMsg.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
|
||||
}
|
||||
|
||||
if txData.TxType() != ethtypes.LegacyTxType {
|
||||
feeAmt = ethMsg.GetEffectiveFee(baseFee)
|
||||
}
|
||||
|
||||
gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(ethMsg.GetGas()))
|
||||
|
||||
requiredFee := minGasPrice.Mul(gasLimit)
|
||||
fee := sdk.NewDecFromBigInt(feeAmt)
|
||||
|
||||
if fee.LT(requiredFee) {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee,
|
||||
"provided fee < minimum global fee (%d < %d). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", //nolint:lll
|
||||
fee.TruncateInt().Int64(), requiredFee.TruncateInt().Int64(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
347
app/ante/fees_test.go
Normal file
347
app/ante/fees_test.go
Normal file
@ -0,0 +1,347 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/cerc-io/laconicd/app/ante"
|
||||
"github.com/cerc-io/laconicd/tests"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
var execTypes = []struct {
|
||||
name string
|
||||
isCheckTx bool
|
||||
simulate bool
|
||||
}{
|
||||
{"deliverTx", false, false},
|
||||
{"deliverTxSimulate", false, true},
|
||||
}
|
||||
|
||||
func (s AnteTestSuite) TestMinGasPriceDecorator() {
|
||||
denom := evmtypes.DefaultEVMDenom
|
||||
testMsg := banktypes.MsgSend{
|
||||
FromAddress: "evmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp",
|
||||
ToAddress: "evmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn",
|
||||
Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() sdk.Tx
|
||||
expPass bool
|
||||
errMsg string
|
||||
allowPassOnSimulate bool
|
||||
}{
|
||||
{
|
||||
"invalid cosmos tx type",
|
||||
func() sdk.Tx {
|
||||
return &invalidTx{}
|
||||
},
|
||||
false,
|
||||
"must be a FeeTx",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid cosmos tx with MinGasPrices = 0, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(0), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
true,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid cosmos tx with MinGasPrices = 0, gasPrice > 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
true,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid cosmos tx with MinGasPrices = 10, gasPrice = 10",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
true,
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid cosmos tx with MinGasPrices = 10, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(0), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid cosmos tx with wrong denom",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), "stake", &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, et := range execTypes {
|
||||
for _, tc := range testCases {
|
||||
s.Run(et.name+"_"+tc.name, func() {
|
||||
// s.SetupTest(et.isCheckTx)
|
||||
ctx := s.ctx.WithIsReCheckTx(et.isCheckTx)
|
||||
dec := ante.NewMinGasPriceDecorator(s.app.FeeMarketKeeper, s.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(ctx, tc.malleate(), et.simulate, NextFn)
|
||||
|
||||
if tc.expPass || (et.simulate && tc.allowPassOnSimulate) {
|
||||
s.Require().NoError(err, tc.name)
|
||||
} else {
|
||||
s.Require().Error(err, tc.name)
|
||||
s.Require().Contains(err.Error(), tc.errMsg, tc.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s AnteTestSuite) TestEthMinGasPriceDecorator() {
|
||||
denom := evmtypes.DefaultEVMDenom
|
||||
from, privKey := tests.NewAddrKey()
|
||||
to := tests.GenerateAddress()
|
||||
emptyAccessList := ethtypes.AccessList{}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() sdk.Tx
|
||||
expPass bool
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
"invalid tx type",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
return &invalidTx{}
|
||||
},
|
||||
false,
|
||||
"invalid message type",
|
||||
},
|
||||
{
|
||||
"wrong tx type",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
testMsg := banktypes.MsgSend{
|
||||
FromAddress: "evmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp",
|
||||
ToAddress: "evmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn",
|
||||
Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}},
|
||||
}
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(0), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
false,
|
||||
"invalid message type",
|
||||
},
|
||||
{
|
||||
"valid: invalid tx type with MinGasPrices = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
return &invalidTx{}
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid legacy tx with MinGasPrices = 0, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid legacy tx with MinGasPrices = 0, gasPrice > 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(10), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid legacy tx with MinGasPrices = 10, gasPrice = 10",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(10), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid legacy tx with MinGasPrices = 10, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices = 0, EffectivePrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(0), big.NewInt(0), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices = 0, EffectivePrice > 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(100), big.NewInt(50), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices < EffectivePrice",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(100), big.NewInt(100), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid dynamic tx with MinGasPrices > EffectivePrice",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(0), big.NewInt(0), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"invalid dynamic tx with MinGasPrices > BaseFee, MinGasPrices > EffectivePrice",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(100)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
feemarketParams := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
feemarketParams.BaseFee = sdkmath.NewInt(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, feemarketParams)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(1000), big.NewInt(0), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices > BaseFee, MinGasPrices < EffectivePrice (big GasTipCap)",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(100)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
feemarketParams := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
feemarketParams.BaseFee = sdkmath.NewInt(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, feemarketParams)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(1000), big.NewInt(101), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, et := range execTypes {
|
||||
for _, tc := range testCases {
|
||||
s.Run(et.name+"_"+tc.name, func() {
|
||||
// s.SetupTest(et.isCheckTx)
|
||||
s.SetupTest()
|
||||
dec := ante.NewEthMinGasPriceDecorator(s.app.FeeMarketKeeper, s.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(s.ctx, tc.malleate(), et.simulate, NextFn)
|
||||
|
||||
if tc.expPass {
|
||||
s.Require().NoError(err, tc.name)
|
||||
} else {
|
||||
s.Require().Error(err, tc.name)
|
||||
s.Require().Contains(err.Error(), tc.errMsg, tc.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -8,8 +8,8 @@ import (
|
||||
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"
|
||||
ibcante "github.com/cosmos/ibc-go/v5/modules/core/ante"
|
||||
ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper"
|
||||
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
)
|
||||
@ -17,32 +17,33 @@ import (
|
||||
// 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
|
||||
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
|
||||
ExtensionOptionChecker ante.ExtensionOptionChecker
|
||||
TxFeeChecker ante.TxFeeChecker
|
||||
}
|
||||
|
||||
func (options HandlerOptions) Validate() error {
|
||||
if options.AccountKeeper == nil {
|
||||
func (options HandlerOptions) validate() error {
|
||||
if options.AccountKeeper == evmtypes.AccountKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
|
||||
}
|
||||
if options.BankKeeper == nil {
|
||||
if options.BankKeeper == evmtypes.BankKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
|
||||
}
|
||||
if options.SignModeHandler == nil {
|
||||
if options.SignModeHandler == authsigning.SignModeHandler(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
||||
}
|
||||
if options.FeeMarketKeeper == nil {
|
||||
if options.FeeMarketKeeper == evmtypes.FeeMarketKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
|
||||
}
|
||||
if options.EvmKeeper == nil {
|
||||
if options.EvmKeeper == EVMKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
|
||||
}
|
||||
return nil
|
||||
@ -50,14 +51,17 @@ func (options HandlerOptions) Validate() error {
|
||||
|
||||
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
|
||||
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
|
||||
NewEthMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper), // Check eth effective gas price against the global MinGasPrice
|
||||
NewEthValidateBasicDecorator(options.EvmKeeper),
|
||||
NewEthSigVerificationDecorator(options.EvmKeeper),
|
||||
NewEthAccountVerificationDecorator(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
|
||||
NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted),
|
||||
NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper),
|
||||
NewCanTransferDecorator(options.EvmKeeper),
|
||||
NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted),
|
||||
NewEthIncrementSenderSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator.
|
||||
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
|
||||
NewEthEmitEventDecorator(options.EvmKeeper), // emit eth tx hash and index at the very last ante handler.
|
||||
)
|
||||
}
|
||||
|
||||
@ -65,6 +69,8 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
return sdk.ChainAnteDecorators(
|
||||
RejectMessagesDecorator{}, // reject MsgEthereumTxs
|
||||
ante.NewSetUpContextDecorator(),
|
||||
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
@ -76,7 +82,8 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
|
||||
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
||||
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
|
||||
ibcante.NewAnteDecorator(options.IBCKeeper),
|
||||
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
|
||||
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
|
||||
)
|
||||
}
|
||||
|
||||
@ -86,6 +93,7 @@ func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
|
||||
ante.NewSetUpContextDecorator(),
|
||||
// NOTE: extensions option decorator removed
|
||||
// ante.NewRejectExtensionOptionsDecorator(),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
@ -98,6 +106,7 @@ func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
|
||||
// Note: signature verification uses EIP instead of the cosmos signature validator
|
||||
NewEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
||||
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
|
||||
ibcante.NewAnteDecorator(options.IBCKeeper),
|
||||
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
|
||||
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
|
||||
)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
|
||||
"github.com/cerc-io/laconicd/x/evm/statedb"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
evm "github.com/cerc-io/laconicd/x/evm/vm"
|
||||
feemarkettypes "github.com/cerc-io/laconicd/x/feemarket/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
tx "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -13,21 +15,33 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// DynamicFeeEVMKeeper is a subset of EVMKeeper interface that supports dynamic fee checker
|
||||
type DynamicFeeEVMKeeper interface {
|
||||
ChainID() *big.Int
|
||||
GetParams(ctx sdk.Context) evmtypes.Params
|
||||
GetBaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
|
||||
}
|
||||
|
||||
// EVMKeeper defines the expected keeper interface used on the Eth AnteHandler
|
||||
type EVMKeeper interface {
|
||||
statedb.Keeper
|
||||
DynamicFeeEVMKeeper
|
||||
|
||||
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
|
||||
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.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
|
||||
) (fees sdk.Coins, priority int64, err error)
|
||||
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
|
||||
ResetTransientGasUsed(ctx sdk.Context)
|
||||
GetTxIndexTransient(ctx sdk.Context) uint64
|
||||
}
|
||||
|
||||
type protoTxProvider interface {
|
||||
GetProtoTx() *tx.Tx
|
||||
}
|
||||
|
||||
// FeeMarketKeeper defines the expected keeper interface used on the AnteHandler
|
||||
type FeeMarketKeeper interface {
|
||||
GetParams(ctx sdk.Context) (params feemarkettypes.Params)
|
||||
AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error)
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cerc-io/laconicd/ethereum/eip712"
|
||||
"github.com/cerc-io/laconicd/types"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
@ -16,8 +22,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
@ -25,6 +30,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
@ -37,6 +43,10 @@ import (
|
||||
"github.com/cerc-io/laconicd/x/evm/statedb"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
feemarkettypes "github.com/cerc-io/laconicd/x/feemarket/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
@ -51,8 +61,11 @@ type AnteTestSuite struct {
|
||||
ethSigner ethtypes.Signer
|
||||
enableFeemarket bool
|
||||
enableLondonHF bool
|
||||
evmParamsOption func(*evmtypes.Params)
|
||||
}
|
||||
|
||||
const TestGasLimit uint64 = 100000
|
||||
|
||||
func (suite *AnteTestSuite) StateDB() *statedb.StateDB {
|
||||
return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes())))
|
||||
}
|
||||
@ -60,7 +73,7 @@ func (suite *AnteTestSuite) StateDB() *statedb.StateDB {
|
||||
func (suite *AnteTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(suite.T(), checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||
suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||
if suite.enableFeemarket {
|
||||
// setup feemarketGenesis params
|
||||
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
||||
@ -71,14 +84,19 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
suite.Require().NoError(err)
|
||||
genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
|
||||
}
|
||||
evmGenesis := evmtypes.DefaultGenesisState()
|
||||
evmGenesis.Params.AllowUnprotectedTxs = false
|
||||
if !suite.enableLondonHF {
|
||||
evmGenesis := evmtypes.DefaultGenesisState()
|
||||
maxInt := sdk.NewInt(math.MaxInt64)
|
||||
maxInt := sdkmath.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)
|
||||
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
|
||||
}
|
||||
if suite.evmParamsOption != nil {
|
||||
suite.evmParamsOption(&evmGenesis.Params)
|
||||
}
|
||||
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
|
||||
return genesis
|
||||
})
|
||||
|
||||
@ -96,7 +114,7 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
|
||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||
|
||||
options := ante.HandlerOptions{
|
||||
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
|
||||
AccountKeeper: suite.app.AccountKeeper,
|
||||
BankKeeper: suite.app.BankKeeper,
|
||||
EvmKeeper: suite.app.EvmKeeper,
|
||||
@ -105,11 +123,10 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
FeeMarketKeeper: suite.app.FeeMarketKeeper,
|
||||
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
}
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().NoError(options.Validate())
|
||||
|
||||
suite.anteHandler = ante.NewAnteHandler(options)
|
||||
suite.anteHandler = anteHandler
|
||||
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
|
||||
}
|
||||
|
||||
@ -119,6 +136,38 @@ func TestAnteTestSuite(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AnteTestSuite) BuildTestEthTx(
|
||||
from common.Address,
|
||||
to common.Address,
|
||||
amount *big.Int,
|
||||
input []byte,
|
||||
gasPrice *big.Int,
|
||||
gasFeeCap *big.Int,
|
||||
gasTipCap *big.Int,
|
||||
accesses *ethtypes.AccessList,
|
||||
) *evmtypes.MsgEthereumTx {
|
||||
chainID := s.app.EvmKeeper.ChainID()
|
||||
nonce := s.app.EvmKeeper.GetNonce(
|
||||
s.ctx,
|
||||
common.BytesToAddress(from.Bytes()),
|
||||
)
|
||||
|
||||
msgEthereumTx := evmtypes.NewTx(
|
||||
chainID,
|
||||
nonce,
|
||||
&to,
|
||||
amount,
|
||||
TestGasLimit,
|
||||
gasPrice,
|
||||
gasFeeCap,
|
||||
gasTipCap,
|
||||
input,
|
||||
accesses,
|
||||
)
|
||||
msgEthereumTx.From = from.String()
|
||||
return msgEthereumTx
|
||||
}
|
||||
|
||||
// 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,
|
||||
@ -150,13 +199,14 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
|
||||
err = msg.Sign(suite.ethSigner, tests.NewSigner(priv))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
msg.From = ""
|
||||
err = builder.SetMsgs(msg)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msg.Data)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(txData.Fee())))
|
||||
fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewIntFromBigInt(txData.Fee())))
|
||||
builder.SetFeeAmount(fees)
|
||||
builder.SetGasLimit(msg.GetGas())
|
||||
|
||||
@ -199,10 +249,21 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, denom string, msgs ...sdk.Msg) client.TxBuilder {
|
||||
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
txBuilder.SetGasLimit(TestGasLimit)
|
||||
fees := &sdk.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(TestGasLimit))}}
|
||||
txBuilder.SetFeeAmount(*fees)
|
||||
err := txBuilder.SetMsgs(msgs...)
|
||||
suite.Require().NoError(err)
|
||||
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))))
|
||||
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
}
|
||||
|
||||
@ -210,10 +271,111 @@ func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAdd
|
||||
// Build MsgSend
|
||||
valEthAddr := tests.GenerateAddress()
|
||||
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
||||
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
||||
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgCreateValidator
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
privEd := ed25519.GenPrivKey()
|
||||
msgCreate, err := types3.NewMsgCreateValidator(
|
||||
valAddr,
|
||||
privEd.PubKey(),
|
||||
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
||||
// TODO: can this values be empty strings?
|
||||
types3.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
||||
types3.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||
sdk.OneInt(),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) client.TxBuilder {
|
||||
proposal, ok := types5.ContentFromProposalType("My proposal", "My description", types5.ProposalTypeText)
|
||||
suite.Require().True(ok)
|
||||
msgSubmit, err := types5.NewMsgSubmitProposal(proposal, deposit, from)
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSubmit)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
spendLimit := sdk.NewCoins(sdk.NewInt64Coin(evmtypes.DefaultEVMDenom, 10))
|
||||
threeHours := time.Now().Add(3 * time.Hour)
|
||||
basic := &feegrant.BasicAllowance{
|
||||
SpendLimit: spendLimit,
|
||||
Expiration: &threeHours,
|
||||
}
|
||||
granted := tests.GenerateAddress()
|
||||
grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes())
|
||||
msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
msgEdit := types3.NewMsgEditValidator(
|
||||
valAddr,
|
||||
types3.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEdit)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
pk := ed25519.GenPrivKey()
|
||||
msgEvidence, err := evtypes.NewMsgSubmitEvidence(from, &evtypes.Equivocation{
|
||||
Height: 11,
|
||||
Time: time.Now().UTC(),
|
||||
Power: 100,
|
||||
ConsensusAddress: pk.PubKey().Address().String(),
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
||||
}
|
||||
|
||||
// StdSignBytes returns the bytes to sign for a transaction.
|
||||
func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequence uint64, timeout uint64, fee legacytx.StdFee, msgs []sdk.Msg, memo string, tip *txtypes.Tip) []byte {
|
||||
msgsBytes := make([]json.RawMessage, 0, len(msgs))
|
||||
for _, msg := range msgs {
|
||||
legacyMsg, ok := msg.(legacytx.LegacyMsg)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("expected %T when using amino JSON", (*legacytx.LegacyMsg)(nil)))
|
||||
}
|
||||
|
||||
msgsBytes = append(msgsBytes, json.RawMessage(legacyMsg.GetSignBytes()))
|
||||
}
|
||||
|
||||
var stdTip *legacytx.StdTip
|
||||
if tip != nil {
|
||||
if tip.Tipper == "" {
|
||||
panic(fmt.Errorf("tipper cannot be empty"))
|
||||
}
|
||||
|
||||
stdTip = &legacytx.StdTip{Amount: tip.Amount, Tipper: tip.Tipper}
|
||||
}
|
||||
|
||||
bz, err := cdc.MarshalJSON(legacytx.StdSignDoc{
|
||||
AccountNumber: accnum,
|
||||
ChainID: chainID,
|
||||
Fee: json.RawMessage(fee.Bytes()),
|
||||
Memo: memo,
|
||||
Msgs: msgsBytes,
|
||||
Sequence: sequence,
|
||||
TimeoutHeight: timeout,
|
||||
Tip: stdTip,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return sdk.MustSortJSON(bz)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
|
||||
) client.TxBuilder {
|
||||
@ -228,6 +390,11 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
|
||||
// GenerateTypedData TypedData
|
||||
var ethermintCodec codec.ProtoCodecMarshaler
|
||||
registry := codectypes.NewInterfaceRegistry()
|
||||
types.RegisterInterfaces(registry)
|
||||
ethermintCodec = codec.NewProtoCodec(registry)
|
||||
cryptocodec.RegisterInterfaces(registry)
|
||||
|
||||
fee := legacytx.NewStdFee(gas, gasAmount)
|
||||
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
||||
|
||||
@ -281,6 +448,10 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
return builder
|
||||
}
|
||||
|
||||
func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
var _ sdk.Tx = &invalidTx{}
|
||||
|
||||
type invalidTx struct{}
|
||||
|
373
app/app.go
373
app/app.go
@ -11,29 +11,28 @@ import (
|
||||
"github.com/rakyll/statik/fs"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/cerc-io/laconicd/app/ante"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
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/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"
|
||||
|
||||
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"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
|
||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
@ -67,6 +66,7 @@ import (
|
||||
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"
|
||||
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
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"
|
||||
@ -87,29 +87,26 @@ 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/v5/modules/apps/transfer"
|
||||
ibctransferkeeper "github.com/cosmos/ibc-go/v5/modules/apps/transfer/keeper"
|
||||
ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
|
||||
ibc "github.com/cosmos/ibc-go/v5/modules/core"
|
||||
ibcclient "github.com/cosmos/ibc-go/v5/modules/core/02-client"
|
||||
ibcclientclient "github.com/cosmos/ibc-go/v5/modules/core/02-client/client"
|
||||
porttypes "github.com/cosmos/ibc-go/v5/modules/core/05-port/types"
|
||||
ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host"
|
||||
ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper"
|
||||
|
||||
// unnamed import of statik for swagger UI support
|
||||
_ "github.com/cerc-io/laconicd/client/docs/statik"
|
||||
|
||||
"github.com/cerc-io/laconicd/app/ante"
|
||||
srvflags "github.com/cerc-io/laconicd/server/flags"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cerc-io/laconicd/x/evm"
|
||||
|
||||
// evmrest "github.com/cerc-io/laconicd/x/evm/client/rest"
|
||||
evmkeeper "github.com/cerc-io/laconicd/x/evm/keeper"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/cerc-io/laconicd/x/evm/vm/geth"
|
||||
"github.com/cerc-io/laconicd/x/feemarket"
|
||||
feemarketkeeper "github.com/cerc-io/laconicd/x/feemarket/keeper"
|
||||
feemarkettypes "github.com/cerc-io/laconicd/x/feemarket/types"
|
||||
@ -155,10 +152,10 @@ var (
|
||||
staking.AppModuleBasic{},
|
||||
mint.AppModuleBasic{},
|
||||
distr.AppModuleBasic{},
|
||||
gov.NewAppModuleBasic(
|
||||
[]govclient.ProposalHandler{paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.LegacyProposalHandler, upgradeclient.LegacyCancelProposalHandler,
|
||||
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler},
|
||||
),
|
||||
gov.NewAppModuleBasic([]govclient.ProposalHandler{
|
||||
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.LegacyProposalHandler, upgradeclient.LegacyCancelProposalHandler,
|
||||
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler,
|
||||
}),
|
||||
params.AppModuleBasic{},
|
||||
crisis.AppModuleBasic{},
|
||||
slashing.AppModuleBasic{},
|
||||
@ -172,7 +169,7 @@ var (
|
||||
// Ethermint modules
|
||||
evm.AppModuleBasic{},
|
||||
feemarket.AppModuleBasic{},
|
||||
// Cerc-io laconic modules
|
||||
// Laconic modules
|
||||
auction.AppModuleBasic{},
|
||||
bond.AppModuleBasic{},
|
||||
nameservice.AppModuleBasic{},
|
||||
@ -216,7 +213,8 @@ 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
|
||||
@ -268,7 +266,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 +274,12 @@ func NewEthermintApp(
|
||||
invCheckPeriod uint,
|
||||
encodingConfig simappparams.EncodingConfig,
|
||||
appOpts servertypes.AppOptions,
|
||||
baseAppOptions ...baseapp.AppOption,
|
||||
baseAppOptions ...func(*baseapp.BaseApp),
|
||||
) *EthermintApp {
|
||||
appCodec := encodingConfig.Codec
|
||||
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,
|
||||
// laconic 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 +290,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,
|
||||
// laconic keys
|
||||
auctiontypes.StoreKey,
|
||||
bondtypes.StoreKey,
|
||||
nameservicetypes.StoreKey,
|
||||
)
|
||||
|
||||
// Add the EVM transient store key
|
||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
||||
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
||||
|
||||
app := &EthermintApp{
|
||||
BaseApp: bApp,
|
||||
@ -385,47 +341,96 @@ 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,
|
||||
sdk.GetConfig().GetBech32AccountAddrPrefix(),
|
||||
)
|
||||
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
||||
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
|
||||
appCodec,
|
||||
keys[banktypes.StoreKey],
|
||||
app.AccountKeeper,
|
||||
app.GetSubspace(banktypes.ModuleName),
|
||||
app.BlockedAddrs(),
|
||||
)
|
||||
stakingKeeper := stakingkeeper.NewKeeper(
|
||||
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
|
||||
appCodec, keys[stakingtypes.StoreKey],
|
||||
app.AccountKeeper,
|
||||
app.BankKeeper,
|
||||
app.GetSubspace(stakingtypes.ModuleName),
|
||||
)
|
||||
app.MintKeeper = mintkeeper.NewKeeper(
|
||||
appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
|
||||
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
|
||||
appCodec,
|
||||
keys[minttypes.StoreKey],
|
||||
app.GetSubspace(minttypes.ModuleName),
|
||||
&stakingKeeper,
|
||||
app.AccountKeeper,
|
||||
app.BankKeeper,
|
||||
authtypes.FeeCollectorName,
|
||||
)
|
||||
app.DistrKeeper = distrkeeper.NewKeeper(
|
||||
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
||||
&stakingKeeper, authtypes.FeeCollectorName,
|
||||
appCodec,
|
||||
keys[distrtypes.StoreKey],
|
||||
app.GetSubspace(distrtypes.ModuleName),
|
||||
app.AccountKeeper,
|
||||
app.BankKeeper,
|
||||
&stakingKeeper,
|
||||
authtypes.FeeCollectorName,
|
||||
)
|
||||
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
||||
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
||||
appCodec,
|
||||
keys[slashingtypes.StoreKey],
|
||||
&stakingKeeper,
|
||||
app.GetSubspace(slashingtypes.ModuleName),
|
||||
)
|
||||
app.CrisisKeeper = crisiskeeper.NewKeeper(
|
||||
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
|
||||
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.FeeGrantKeeper = feegrantkeeper.NewKeeper(
|
||||
appCodec,
|
||||
keys[feegrant.StoreKey],
|
||||
app.AccountKeeper)
|
||||
|
||||
// set the governance module account as the authority for conducting upgrades
|
||||
app.UpgradeKeeper = upgradekeeper.NewKeeper(
|
||||
skipUpgradeHeights,
|
||||
keys[upgradetypes.StoreKey],
|
||||
appCodec,
|
||||
homePath,
|
||||
app.BaseApp,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String())
|
||||
|
||||
// register the staking hooks
|
||||
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
|
||||
app.StakingKeeper = *stakingKeeper.SetHooks(
|
||||
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
||||
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.MsgServiceRouter(),
|
||||
app.AccountKeeper)
|
||||
|
||||
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
||||
|
||||
// Create Ethermint keepers
|
||||
app.FeeMarketKeeper = feemarketkeeper.NewKeeper(
|
||||
appCodec, keys[feemarkettypes.StoreKey], app.GetSubspace(feemarkettypes.ModuleName),
|
||||
appCodec, app.GetSubspace(feemarkettypes.ModuleName), keys[feemarkettypes.StoreKey], tkeys[feemarkettypes.TransientKey],
|
||||
)
|
||||
|
||||
// Create Cerc-io laconic keepers
|
||||
app.EvmKeeper = evmkeeper.NewKeeper(
|
||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
|
||||
app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.FeeMarketKeeper,
|
||||
nil, geth.NewEVM, tracer,
|
||||
)
|
||||
|
||||
// Create laconic keepers
|
||||
app.AuctionKeeper = auctionkeeper.NewKeeper(
|
||||
app.AccountKeeper, app.BankKeeper, keys[auctiontypes.StoreKey],
|
||||
appCodec, app.GetSubspace(auctiontypes.ModuleName),
|
||||
@ -446,12 +451,6 @@ 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,
|
||||
@ -464,13 +463,11 @@ func NewEthermintApp(
|
||||
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,
|
||||
@ -491,7 +488,7 @@ func NewEthermintApp(
|
||||
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)
|
||||
app.IBCKeeper.SetRouter(ibcRouter)
|
||||
@ -522,6 +519,7 @@ func NewEthermintApp(
|
||||
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
||||
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
||||
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
||||
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
||||
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||
@ -530,8 +528,8 @@ func NewEthermintApp(
|
||||
upgrade.NewAppModule(app.UpgradeKeeper),
|
||||
evidence.NewAppModule(app.EvidenceKeeper),
|
||||
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,
|
||||
@ -548,7 +546,7 @@ func NewEthermintApp(
|
||||
// there is nothing left over in the validator fee pool, so as to keep the
|
||||
// CanWithdrawInvariant invariant.
|
||||
// NOTE: upgrade module must go first to handle software upgrades.
|
||||
// NOTE: staking module is required if HistoricalEntries param > 0.
|
||||
// NOTE: staking module is required if HistoricalEntries param > 0
|
||||
// NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC)
|
||||
app.mm.SetOrderBeginBlockers(
|
||||
upgradetypes.ModuleName,
|
||||
@ -609,6 +607,7 @@ func NewEthermintApp(
|
||||
|
||||
// NOTE: The genutils module must occur after staking so that pools are
|
||||
// properly initialized with tokens from genesis accounts.
|
||||
// NOTE: The genutils module must also occur after auth so that it can access the params from auth.
|
||||
// NOTE: Capability module must occur first so that it can initialize any capabilities
|
||||
// so that other modules that want to create or claim capabilities afterwards in InitChain
|
||||
// can do so safely.
|
||||
@ -623,6 +622,11 @@ func NewEthermintApp(
|
||||
govtypes.ModuleName,
|
||||
minttypes.ModuleName,
|
||||
ibchost.ModuleName,
|
||||
// evm module denomination is used by the feemarket module, in AnteHandle
|
||||
evmtypes.ModuleName,
|
||||
// NOTE: feemarket need to be initialized before genutil module:
|
||||
// gentx transactions use MinGasPriceDecorator.AnteHandle
|
||||
feemarkettypes.ModuleName,
|
||||
genutiltypes.ModuleName,
|
||||
evidencetypes.ModuleName,
|
||||
ibctransfertypes.ModuleName,
|
||||
@ -631,76 +635,70 @@ func NewEthermintApp(
|
||||
paramstypes.ModuleName,
|
||||
upgradetypes.ModuleName,
|
||||
vestingtypes.ModuleName,
|
||||
// Ethermint modules
|
||||
evmtypes.ModuleName,
|
||||
feemarkettypes.ModuleName,
|
||||
// laconic modules
|
||||
auctiontypes.ModuleName,
|
||||
bondtypes.ModuleName,
|
||||
nameservicetypes.ModuleName,
|
||||
|
||||
// NOTE: crisis module must go at the end to check for invariants on each module
|
||||
crisistypes.ModuleName,
|
||||
)
|
||||
|
||||
// Uncomment if you want to set a custom migration order here.
|
||||
// app.mm.SetOrderMigrations(custom order)
|
||||
|
||||
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
||||
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
|
||||
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
|
||||
app.mm.RegisterServices(app.configurator)
|
||||
|
||||
// RegisterUpgradeHandlers is used for registering any on-chain upgrades.
|
||||
// Make sure it's called after `app.mm` and `app.configurator` are set.
|
||||
app.RegisterUpgradeHandlers()
|
||||
|
||||
// add test gRPC service for testing gRPC queries in isolation
|
||||
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
||||
|
||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
||||
|
||||
//
|
||||
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
||||
// transactions
|
||||
app.sm = module.NewSimulationManager(
|
||||
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
||||
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
||||
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
||||
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
||||
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||
params.NewAppModule(app.ParamsKeeper),
|
||||
evidence.NewAppModule(app.EvidenceKeeper),
|
||||
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
||||
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),
|
||||
)
|
||||
overrideModules := map[string]module.AppModuleSimulation{
|
||||
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
||||
}
|
||||
app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules)
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
app.setAnteHandler(encodingConfig.TxConfig, cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted)))
|
||||
// In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
|
||||
// antehandlers, but are run _after_ the `runMsgs` execution. They are also
|
||||
// defined as a chain, and have the same signature as antehandlers.
|
||||
//
|
||||
// In baseapp, postHandlers are run in the same store branch as `runMsgs`,
|
||||
// meaning that both `runMsgs` and `postHandler` state will be committed if
|
||||
// both are successful, and both will be reverted if any of the two fails.
|
||||
//
|
||||
// The SDK exposes a default empty postHandlers chain.
|
||||
//
|
||||
// Please note that changing any of the anteHandler or postHandler chain is
|
||||
// likely to be a state-machine breaking change, which needs a coordinated
|
||||
// upgrade.
|
||||
app.setPostHandler()
|
||||
|
||||
if loadLatest {
|
||||
if err := app.LoadLatestVersion(); err != nil {
|
||||
tmos.Exit(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
app.ScopedIBCKeeper = scopedIBCKeeper
|
||||
app.ScopedTransferKeeper = scopedTransferKeeper
|
||||
@ -708,6 +706,37 @@ func NewEthermintApp(
|
||||
return app
|
||||
}
|
||||
|
||||
// use Ethermint's custom AnteHandler
|
||||
func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64) {
|
||||
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
|
||||
AccountKeeper: app.AccountKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
SignModeHandler: txConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
IBCKeeper: app.IBCKeeper,
|
||||
EvmKeeper: app.EvmKeeper,
|
||||
FeeMarketKeeper: app.FeeMarketKeeper,
|
||||
MaxTxGasWanted: maxGasWanted,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app.SetAnteHandler(anteHandler)
|
||||
}
|
||||
|
||||
func (app *EthermintApp) setPostHandler() {
|
||||
postHandler, err := posthandler.NewPostHandler(
|
||||
posthandler.HandlerOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app.SetPostHandler(postHandler)
|
||||
}
|
||||
|
||||
// Name returns the name of the App
|
||||
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
|
||||
|
||||
@ -733,13 +762,13 @@ 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.
|
||||
func (app *EthermintApp) ModuleAccountAddrs() map[string]bool {
|
||||
modAccAddrs := make(map[string]bool)
|
||||
// #nosec G705
|
||||
for acc := range maccPerms {
|
||||
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
|
||||
}
|
||||
@ -751,6 +780,7 @@ func (app *EthermintApp) ModuleAccountAddrs() map[string]bool {
|
||||
// allowed to receive external tokens.
|
||||
func (app *EthermintApp) BlockedAddrs() map[string]bool {
|
||||
blockedAddrs := make(map[string]bool)
|
||||
// #nosec G705
|
||||
for acc := range maccPerms {
|
||||
blockedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc]
|
||||
}
|
||||
@ -817,16 +847,12 @@ 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)
|
||||
|
||||
// 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 grpc-gateway routes for all modules.
|
||||
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
|
||||
// register swagger API from root so that other applications can override easily
|
||||
@ -835,10 +861,12 @@ func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterTxService implements the Application.RegisterTxService method.
|
||||
func (app *EthermintApp) RegisterTxService(clientCtx client.Context) {
|
||||
authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
|
||||
}
|
||||
|
||||
// RegisterTendermintService implements the Application.RegisterTendermintService method.
|
||||
func (app *EthermintApp) RegisterTendermintService(clientCtx client.Context) {
|
||||
tmservice.RegisterTendermintService(
|
||||
clientCtx,
|
||||
@ -865,14 +893,11 @@ func GetMaccPerms() map[string][]string {
|
||||
for k, v := range maccPerms {
|
||||
dupMaccPerms[k] = v
|
||||
}
|
||||
|
||||
return dupMaccPerms
|
||||
}
|
||||
|
||||
// initParamsKeeper init params keeper and its subspaces
|
||||
func initParamsKeeper(
|
||||
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey,
|
||||
) paramskeeper.Keeper {
|
||||
func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey) paramskeeper.Keeper {
|
||||
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
||||
|
||||
// SDK subspaces
|
||||
|
@ -1,45 +1,26 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
memdb "github.com/cosmos/cosmos-sdk/db/memdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cerc-io/laconicd/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{},
|
||||
})
|
||||
|
||||
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",
|
||||
)
|
||||
}
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
app := SetupWithDB(false, nil, db)
|
||||
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())
|
||||
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")
|
||||
}
|
||||
|
@ -2,21 +2,21 @@ package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
"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"
|
||||
)
|
||||
|
||||
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 := NewTestGenesisState(app.AppCodec())
|
||||
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)
|
||||
}
|
||||
|
@ -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/cerc-io/laconicd/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.Codec)
|
||||
}
|
||||
|
||||
// ExportAppStateAndValidators exports the state of the application for a genesis
|
||||
@ -60,7 +62,7 @@ func (app *EthermintApp) ExportAppStateAndValidators(
|
||||
|
||||
// prepare for fresh start at zero height
|
||||
// NOTE zero height genesis is a temporary feature which will be deprecated
|
||||
// in favor of export at a block height
|
||||
// in favor of export at a block height
|
||||
func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) error {
|
||||
applyAllowedAddrs := false
|
||||
|
||||
@ -123,7 +125,9 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAd
|
||||
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
|
||||
app.DistrKeeper.SetFeePool(ctx, feePool)
|
||||
|
||||
app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator())
|
||||
if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()); err != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
@ -137,8 +141,12 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAd
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr)
|
||||
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr)
|
||||
if err := app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// reset context height
|
||||
|
@ -6,16 +6,22 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cerc-io/laconicd/app/ante"
|
||||
evmenc "github.com/cerc-io/laconicd/encoding"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
|
||||
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"
|
||||
@ -26,15 +32,12 @@ import (
|
||||
"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"
|
||||
|
||||
evmenc "github.com/cerc-io/laconicd/encoding"
|
||||
"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"
|
||||
ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
|
||||
ibchost "github.com/cosmos/ibc-go/v5/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"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
// MakeEncodingConfig creates the EncodingConfig
|
||||
@ -56,15 +59,40 @@ type storeKeysPrefixes struct {
|
||||
|
||||
// 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) {
|
||||
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
|
||||
bapp.SetFauxMerkleMode()
|
||||
})
|
||||
}
|
||||
|
||||
// NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail.
|
||||
func NewSimApp(logger log.Logger, db dbm.DB) (*EthermintApp, error) {
|
||||
encodingConfig := MakeEncodingConfig()
|
||||
app := NewEthermintApp(logger, db, nil, false, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, encodingConfig, simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
|
||||
// disable feemarket on native tx
|
||||
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
|
||||
AccountKeeper: app.AccountKeeper,
|
||||
BankKeeper: app.BankKeeper,
|
||||
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
||||
FeegrantKeeper: app.FeeGrantKeeper,
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
IBCKeeper: app.IBCKeeper,
|
||||
EvmKeeper: app.EvmKeeper,
|
||||
FeeMarketKeeper: app.FeeMarketKeeper,
|
||||
MaxTxGasWanted: 0,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.SetAnteHandler(anteHandler)
|
||||
if err := app.LoadLatestVersion(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return app, nil
|
||||
}
|
||||
|
||||
// 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 interBlockCacheOpt() func(*baseapp.BaseApp) {
|
||||
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
|
||||
}
|
||||
|
||||
func TestFullAppSimulation(t *testing.T) {
|
||||
@ -74,21 +102,24 @@ func TestFullAppSimulation(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
require.NoError(t, db.Close())
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.Equal(t, appName, app.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
// 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
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
@ -112,12 +143,14 @@ func TestAppImportExport(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
require.NoError(t, db.Close())
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, appName, app.Name())
|
||||
|
||||
// Run randomized simulation
|
||||
@ -125,8 +158,8 @@ func TestAppImportExport(t *testing.T) {
|
||||
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
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
@ -149,24 +182,36 @@ func TestAppImportExport(t *testing.T) {
|
||||
|
||||
fmt.Printf("importing genesis...\n")
|
||||
|
||||
// nolint: dogsled
|
||||
//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, 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)
|
||||
newApp, err := NewSimApp(log.NewNopLogger(), newDB)
|
||||
require.Equal(t, appName, newApp.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
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()})
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err := fmt.Sprintf("%v", r)
|
||||
if !strings.Contains(err, "validator set is empty after InitGenesis") {
|
||||
panic(r)
|
||||
}
|
||||
logger.Info("Skipping simulation as all validators have been unbonded")
|
||||
logger.Info("err", err, "stacktrace", string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID})
|
||||
ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID})
|
||||
newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState)
|
||||
newApp.StoreConsensusParams(ctxB, exported.ConsensusParams)
|
||||
|
||||
@ -189,6 +234,7 @@ func TestAppImportExport(t *testing.T) {
|
||||
{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[authzkeeper.StoreKey], newApp.keys[authzkeeper.StoreKey], [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}},
|
||||
{app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}},
|
||||
{app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}},
|
||||
}
|
||||
@ -212,21 +258,24 @@ func TestAppSimulationAfterImport(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
|
||||
defer func() {
|
||||
db.Close()
|
||||
require.NoError(t, db.Close())
|
||||
require.NoError(t, os.RemoveAll(dir))
|
||||
}()
|
||||
|
||||
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.Equal(t, appName, app.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
// 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
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
@ -258,14 +307,16 @@ func TestAppSimulationAfterImport(t *testing.T) {
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
defer func() {
|
||||
newDB.Close()
|
||||
require.NoError(t, 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)
|
||||
newApp, err := NewSimApp(log.NewNopLogger(), newDB)
|
||||
require.Equal(t, appName, newApp.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
newApp.InitChain(abci.RequestInitChain{
|
||||
ChainId: SimAppChainID,
|
||||
AppStateBytes: exported.AppState,
|
||||
})
|
||||
|
||||
@ -273,8 +324,8 @@ func TestAppSimulationAfterImport(t *testing.T) {
|
||||
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
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(newApp, newApp.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
@ -312,20 +363,21 @@ func TestAppStateDeterminism(t *testing.T) {
|
||||
logger = log.NewNopLogger()
|
||||
}
|
||||
|
||||
db := memdb.NewDB()
|
||||
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, interBlockCacheOpt())
|
||||
db := dbm.NewMemDB()
|
||||
app, err := NewSimApp(logger, db)
|
||||
require.NoError(t, err)
|
||||
|
||||
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(
|
||||
_, _, 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
|
||||
StateFn(app.AppCodec(), app.SimulationManager()),
|
||||
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
|
||||
simapp.SimulationOperations(app, app.AppCodec(), config),
|
||||
app.ModuleAccountAddrs(),
|
||||
config,
|
||||
|
@ -1,283 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"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/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// 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{
|
||||
MaxBytes: 200000,
|
||||
MaxGas: -1, // no limit
|
||||
},
|
||||
Evidence: &tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 302400,
|
||||
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
|
||||
MaxBytes: 10000,
|
||||
},
|
||||
Validator: &tmproto.ValidatorParams{
|
||||
PubKeyTypes: []string{
|
||||
tmtypes.ABCIPubKeyTypeEd25519,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 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 := ðermint.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)
|
||||
|
||||
if !isCheckTx {
|
||||
// init chain must be called to stop deliverState from being nil
|
||||
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Initialize the chain
|
||||
app.InitChain(
|
||||
abci.RequestInitChain{
|
||||
ChainId: "ethermint_9000-1",
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: DefaultConsensusParams,
|
||||
AppStateBytes: stateBytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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 := ðermint.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.
|
||||
testAddrs := make([]sdk.AccAddress, accNum)
|
||||
for i := 0; i < accNum; i++ {
|
||||
pk := ed25519.GenPrivKey().PubKey()
|
||||
testAddrs[i] = sdk.AccAddress(pk.Address())
|
||||
}
|
||||
|
||||
return testAddrs
|
||||
}
|
||||
|
||||
// EmptyAppOptions is a stub implementing AppOptions
|
||||
type EmptyAppOptions struct{}
|
||||
|
||||
// Get implements AppOptions
|
||||
func (ao EmptyAppOptions) Get(o string) interface{} {
|
||||
return nil
|
||||
}
|
14
app/upgrades.go
Normal file
14
app/upgrades.go
Normal file
@ -0,0 +1,14 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
)
|
||||
|
||||
func (app *EthermintApp) RegisterUpgradeHandlers() {
|
||||
planName := "integration-test-upgrade"
|
||||
app.UpgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
})
|
||||
}
|
274
app/utils.go
Normal file
274
app/utils.go
Normal file
@ -0,0 +1,274 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand" // #nosec G702
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
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"
|
||||
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
// DefaultConsensusParams defines the default Tendermint consensus params used in
|
||||
// EthermintApp testing.
|
||||
var DefaultConsensusParams = &abci.ConsensusParams{
|
||||
Block: &abci.BlockParams{
|
||||
MaxBytes: 200000,
|
||||
MaxGas: -1, // no limit
|
||||
},
|
||||
Evidence: &tmproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 302400,
|
||||
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
|
||||
MaxBytes: 10000,
|
||||
},
|
||||
Validator: &tmproto.ValidatorParams{
|
||||
PubKeyTypes: []string{
|
||||
tmtypes.ABCIPubKeyTypeEd25519,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
|
||||
func Setup(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) *EthermintApp {
|
||||
return SetupWithDB(isCheckTx, patchGenesis, dbm.NewMemDB())
|
||||
}
|
||||
|
||||
// SetupWithDB initializes a new EthermintApp. A Nop logger is set in EthermintApp.
|
||||
func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState, db dbm.DB) *EthermintApp {
|
||||
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
|
||||
genesisState := NewTestGenesisState(app.AppCodec())
|
||||
if patchGenesis != nil {
|
||||
genesisState = patchGenesis(app, genesisState)
|
||||
}
|
||||
|
||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Initialize the chain
|
||||
app.InitChain(
|
||||
abci.RequestInitChain{
|
||||
ChainId: "ethermint_9000-1",
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: DefaultConsensusParams,
|
||||
AppStateBytes: stateBytes,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// RandomGenesisAccounts is used by the auth module to create random genesis accounts in simulation when a genesis.json is not specified.
|
||||
// In contrast, the default auth module's RandomGenesisAccounts implementation creates only base accounts and vestings accounts.
|
||||
func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts {
|
||||
emptyCodeHash := crypto.Keccak256(nil)
|
||||
genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts))
|
||||
for i, acc := range simState.Accounts {
|
||||
bacc := authtypes.NewBaseAccountWithAddress(acc.Address)
|
||||
|
||||
ethacc := ðermint.EthAccount{
|
||||
BaseAccount: bacc,
|
||||
CodeHash: common.BytesToHash(emptyCodeHash).String(),
|
||||
}
|
||||
genesisAccs[i] = ethacc
|
||||
}
|
||||
|
||||
return genesisAccs
|
||||
}
|
||||
|
||||
// RandomAccounts creates random accounts with an ethsecp256k1 private key
|
||||
// TODO: replace secp256k1.GenPrivKeyFromSecret() with similar function in go-ethereum
|
||||
func RandomAccounts(r *rand.Rand, n int) []simtypes.Account {
|
||||
accs := make([]simtypes.Account, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// don't need that much entropy for simulation
|
||||
privkeySeed := make([]byte, 15)
|
||||
_, _ = r.Read(privkeySeed)
|
||||
|
||||
prv := secp256k1.GenPrivKeyFromSecret(privkeySeed)
|
||||
ethPrv := ðsecp256k1.PrivKey{}
|
||||
_ = ethPrv.UnmarshalAmino(prv.Bytes()) // UnmarshalAmino simply copies the bytes and assigns them to ethPrv.Key
|
||||
accs[i].PrivKey = ethPrv
|
||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||
|
||||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
|
||||
}
|
||||
|
||||
return accs
|
||||
}
|
||||
|
||||
// StateFn returns the initial application state using a genesis or the simulation parameters.
|
||||
// It is a wrapper of simapp.AppStateFn to replace evm param EvmDenom with staking param BondDenom.
|
||||
func StateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
|
||||
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
|
||||
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
|
||||
appStateFn := simapp.AppStateFn(cdc, simManager)
|
||||
appState, simAccs, chainID, genesisTimestamp = appStateFn(r, accs, config)
|
||||
|
||||
rawState := make(map[string]json.RawMessage)
|
||||
err := json.Unmarshal(appState, &rawState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
|
||||
if !ok {
|
||||
panic("staking genesis state is missing")
|
||||
}
|
||||
|
||||
stakingState := new(stakingtypes.GenesisState)
|
||||
cdc.MustUnmarshalJSON(stakingStateBz, stakingState)
|
||||
|
||||
// we should get the BondDenom and make it the evmdenom.
|
||||
// thus simulation accounts could have positive amount of gas token.
|
||||
bondDenom := stakingState.Params.BondDenom
|
||||
|
||||
evmStateBz, ok := rawState[evmtypes.ModuleName]
|
||||
if !ok {
|
||||
panic("evm genesis state is missing")
|
||||
}
|
||||
|
||||
evmState := new(evmtypes.GenesisState)
|
||||
cdc.MustUnmarshalJSON(evmStateBz, evmState)
|
||||
|
||||
// we should replace the EvmDenom with BondDenom
|
||||
evmState.Params.EvmDenom = bondDenom
|
||||
|
||||
// change appState back
|
||||
rawState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmState)
|
||||
|
||||
// replace appstate
|
||||
appState, err = json.Marshal(rawState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return appState, simAccs, chainID, genesisTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
// NewTestGenesisState generate genesis state with single validator
|
||||
func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
|
||||
privVal := mock.NewPV()
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// create validator set with single validator
|
||||
validator := tmtypes.NewValidator(pubKey, 1)
|
||||
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
||||
|
||||
// generate genesis account
|
||||
senderPrivKey := secp256k1.GenPrivKey()
|
||||
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
|
||||
balance := banktypes.Balance{
|
||||
Address: acc.GetAddress().String(),
|
||||
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
|
||||
}
|
||||
|
||||
genesisState := NewDefaultGenesisState()
|
||||
return genesisStateWithValSet(codec, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
|
||||
}
|
||||
|
||||
func genesisStateWithValSet(codec codec.Codec, 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] = codec.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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pkAny, err := codectypes.NewAnyWithValue(pk)
|
||||
if err != nil {
|
||||
panic(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] = codec.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] = codec.MustMarshalJSON(bankGenesis)
|
||||
|
||||
return genesisState
|
||||
}
|
113
app/utils_test.go
Normal file
113
app/utils_test.go
Normal file
@ -0,0 +1,113 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var (
|
||||
maxTestingAccounts = 100
|
||||
seed = int64(233)
|
||||
)
|
||||
|
||||
func TestRandomGenesisAccounts(t *testing.T) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
accs := RandomAccounts(r, rand.Intn(maxTestingAccounts))
|
||||
|
||||
encodingConfig := MakeEncodingConfig()
|
||||
appCodec := encodingConfig.Codec
|
||||
cdc := encodingConfig.Amino
|
||||
|
||||
paramsKeeper := initParamsKeeper(appCodec, cdc, sdk.NewKVStoreKey(paramstypes.StoreKey), sdk.NewTransientStoreKey(paramstypes.StoreKey))
|
||||
subSpace, find := paramsKeeper.GetSubspace(authtypes.ModuleName)
|
||||
require.True(t, find)
|
||||
accountKeeper := authkeeper.NewAccountKeeper(
|
||||
appCodec, sdk.NewKVStoreKey(authtypes.StoreKey), subSpace, ethermint.ProtoAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(),
|
||||
)
|
||||
authModule := auth.NewAppModule(appCodec, accountKeeper, RandomGenesisAccounts)
|
||||
|
||||
genesisState := simapp.NewDefaultGenesisState(appCodec)
|
||||
simState := &module.SimulationState{Accounts: accs, Cdc: appCodec, Rand: r, GenState: genesisState}
|
||||
authModule.GenerateGenesisState(simState)
|
||||
|
||||
authStateBz, find := genesisState[authtypes.ModuleName]
|
||||
require.True(t, find)
|
||||
|
||||
authState := new(authtypes.GenesisState)
|
||||
appCodec.MustUnmarshalJSON(authStateBz, authState)
|
||||
accounts, err := authtypes.UnpackAccounts(authState.Accounts)
|
||||
require.NoError(t, err)
|
||||
for _, acc := range accounts {
|
||||
_, ok := acc.(ethermint.EthAccountI)
|
||||
require.True(t, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateFn(t *testing.T) {
|
||||
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
|
||||
if skip {
|
||||
t.Skip("skipping AppStateFn testing")
|
||||
}
|
||||
require.NoError(t, err, "simulation setup failed")
|
||||
|
||||
config.ChainID = SimAppChainID
|
||||
config.Commit = true
|
||||
|
||||
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())
|
||||
|
||||
appStateFn := StateFn(app.AppCodec(), app.SimulationManager())
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts))
|
||||
appState, _, _, _ := appStateFn(r, accounts, config)
|
||||
|
||||
rawState := make(map[string]json.RawMessage)
|
||||
err = json.Unmarshal(appState, &rawState)
|
||||
require.NoError(t, err)
|
||||
|
||||
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
|
||||
require.True(t, ok)
|
||||
|
||||
stakingState := new(stakingtypes.GenesisState)
|
||||
app.AppCodec().MustUnmarshalJSON(stakingStateBz, stakingState)
|
||||
bondDenom := stakingState.Params.BondDenom
|
||||
|
||||
evmStateBz, ok := rawState[evmtypes.ModuleName]
|
||||
require.True(t, ok)
|
||||
|
||||
evmState := new(evmtypes.GenesisState)
|
||||
app.AppCodec().MustUnmarshalJSON(evmStateBz, evmState)
|
||||
require.Equal(t, bondDenom, evmState.Params.EvmDenom)
|
||||
}
|
||||
|
||||
func TestRandomAccounts(t *testing.T) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts))
|
||||
for _, acc := range accounts {
|
||||
_, ok := acc.PrivKey.(*ethsecp256k1.PrivKey)
|
||||
require.True(t, ok)
|
||||
}
|
||||
}
|
3
client/docs/statik/statik.go
vendored
3
client/docs/statik/statik.go
vendored
File diff suppressed because one or more lines are too long
481
client/docs/swagger-ui/swagger.yaml
vendored
481
client/docs/swagger-ui/swagger.yaml
vendored
@ -1,10 +1,10 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: Ethermint Chain - Legacy REST and gRPC Gateway docs
|
||||
description: 'A REST interface for state queries, legacy transactions'
|
||||
description: A REST interface for state queries, legacy transactions
|
||||
version: 1.0.0
|
||||
paths:
|
||||
'/ethermint/evm/v1/account/{address}':
|
||||
/ethermint/evm/v1/account/{address}:
|
||||
get:
|
||||
summary: Account queries an Ethereum account.
|
||||
operationId: Account
|
||||
@ -224,7 +224,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/ethermint/evm/v1/balances/{address}':
|
||||
/ethermint/evm/v1/balances/{address}:
|
||||
get:
|
||||
summary: |-
|
||||
Balance queries the balance of a the EVM denomination for a single
|
||||
@ -439,7 +439,215 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/ethermint/evm/v1/codes/{address}':
|
||||
/ethermint/evm/v1/base_fee:
|
||||
get:
|
||||
summary: >-
|
||||
BaseFee queries the base fee of the parent block of the current block,
|
||||
|
||||
it's similar to feemarket module's method, but also checks london
|
||||
hardfork status.
|
||||
operationId: BaseFee
|
||||
responses:
|
||||
'200':
|
||||
description: A successful response.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
base_fee:
|
||||
type: string
|
||||
description: BaseFeeResponse returns the EIP1559 base fee.
|
||||
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"
|
||||
}
|
||||
tags:
|
||||
- Query
|
||||
/ethermint/evm/v1/codes/{address}:
|
||||
get:
|
||||
summary: Code queries the balance of all coins for a single account.
|
||||
operationId: Code
|
||||
@ -653,7 +861,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/ethermint/evm/v1/cosmos_account/{address}':
|
||||
/ethermint/evm/v1/cosmos_account/{address}:
|
||||
get:
|
||||
summary: CosmosAccount queries an Ethereum account's Cosmos Address.
|
||||
operationId: CosmosAccount
|
||||
@ -1131,7 +1339,7 @@ paths:
|
||||
data:
|
||||
type: string
|
||||
format: byte
|
||||
title: 'supplied by the contract, usually ABI-encoded'
|
||||
title: supplied by the contract, usually ABI-encoded
|
||||
block_number:
|
||||
type: string
|
||||
format: uint64
|
||||
@ -1500,11 +1708,28 @@ paths:
|
||||
title: >-
|
||||
London switch block (nil = no fork, 0 = already on
|
||||
london)
|
||||
arrow_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 =
|
||||
already activated)
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 =
|
||||
already in merge proceedings)
|
||||
description: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters
|
||||
using *sdk.Int values
|
||||
|
||||
instead of *big.Int.
|
||||
allow_unprotected_txs:
|
||||
type: boolean
|
||||
description: >-
|
||||
Allow unprotected transactions defines if replay-protected
|
||||
(i.e non EIP155
|
||||
|
||||
signed) transactions can be executed on the state machine.
|
||||
title: Params defines the EVM module parameters
|
||||
description: >-
|
||||
QueryParamsResponse defines the response type for querying x/evm
|
||||
@ -1700,7 +1925,7 @@ paths:
|
||||
}
|
||||
tags:
|
||||
- Query
|
||||
'/ethermint/evm/v1/storage/{address}/{key}':
|
||||
/ethermint/evm/v1/storage/{address}/{key}:
|
||||
get:
|
||||
summary: Storage queries the balance of all coins for a single account.
|
||||
operationId: Storage
|
||||
@ -2166,13 +2391,13 @@ paths:
|
||||
required: false
|
||||
type: boolean
|
||||
- name: trace_config.limit
|
||||
description: 'maximum length of output, but zero means unlimited.'
|
||||
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).'
|
||||
description: Homestead switch block (nil no fork, 0 = already homestead).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2213,12 +2438,12 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.byzantium_block
|
||||
description: 'Byzantium switch block (nil no fork, 0 = already on byzantium).'
|
||||
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).'
|
||||
description: Constantinople switch block (nil no fork, 0 = already activated).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2228,7 +2453,7 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.istanbul_block
|
||||
description: 'Istanbul switch block (nil no fork, 0 = already on istanbul).'
|
||||
description: Istanbul switch block (nil no fork, 0 = already on istanbul).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2240,12 +2465,26 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.berlin_block
|
||||
description: 'Berlin switch block (nil = no fork, 0 = already on berlin).'
|
||||
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).'
|
||||
description: London switch block (nil = no fork, 0 = already on london).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.arrow_glacier_block
|
||||
description: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.merge_fork_block
|
||||
description: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
|
||||
merge proceedings).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2562,12 +2801,6 @@ paths:
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: tx_index
|
||||
description: transaction index.
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
format: uint64
|
||||
- name: trace_config.tracer
|
||||
description: custom javascript tracer.
|
||||
in: query
|
||||
@ -2604,13 +2837,13 @@ paths:
|
||||
required: false
|
||||
type: boolean
|
||||
- name: trace_config.limit
|
||||
description: 'maximum length of output, but zero means unlimited.'
|
||||
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).'
|
||||
description: Homestead switch block (nil no fork, 0 = already homestead).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2651,12 +2884,12 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.byzantium_block
|
||||
description: 'Byzantium switch block (nil no fork, 0 = already on byzantium).'
|
||||
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).'
|
||||
description: Constantinople switch block (nil no fork, 0 = already activated).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2666,7 +2899,7 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.istanbul_block
|
||||
description: 'Istanbul switch block (nil no fork, 0 = already on istanbul).'
|
||||
description: Istanbul switch block (nil no fork, 0 = already on istanbul).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2678,12 +2911,26 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.berlin_block
|
||||
description: 'Berlin switch block (nil = no fork, 0 = already on berlin).'
|
||||
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).'
|
||||
description: London switch block (nil = no fork, 0 = already on london).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.arrow_glacier_block
|
||||
description: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: trace_config.overrides.merge_fork_block
|
||||
description: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
|
||||
merge proceedings).
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
@ -2716,7 +2963,7 @@ paths:
|
||||
format: date-time
|
||||
tags:
|
||||
- Query
|
||||
'/ethermint/evm/v1/validator_account/{cons_address}':
|
||||
/ethermint/evm/v1/validator_account/{cons_address}:
|
||||
get:
|
||||
summary: >-
|
||||
ValidatorAccount queries an Ethereum account's from a validator
|
||||
@ -3397,7 +3644,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/auth/v1beta1/accounts/{address}':
|
||||
/cosmos/auth/v1beta1/accounts/{address}:
|
||||
get:
|
||||
summary: Account returns account details based on address.
|
||||
operationId: AuthAccount
|
||||
@ -4001,7 +4248,7 @@ paths:
|
||||
}
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/bank/v1beta1/balances/{address}':
|
||||
/cosmos/bank/v1beta1/balances/{address}:
|
||||
get:
|
||||
summary: AllBalances queries the balance of all coins for a single account.
|
||||
operationId: AllBalances
|
||||
@ -4135,7 +4382,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/bank/v1beta1/balances/{address}/{denom}':
|
||||
/cosmos/bank/v1beta1/balances/{address}/{denom}:
|
||||
get:
|
||||
summary: Balance queries the balance of a single coin for a single account.
|
||||
operationId: BankBalance
|
||||
@ -4383,7 +4630,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/bank/v1beta1/denoms_metadata/{denom}':
|
||||
/cosmos/bank/v1beta1/denoms_metadata/{denom}:
|
||||
get:
|
||||
summary: DenomsMetadata queries the client metadata of a given coin denomination.
|
||||
operationId: DenomMetadata
|
||||
@ -4681,7 +4928,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/bank/v1beta1/supply/{denom}':
|
||||
/cosmos/bank/v1beta1/supply/{denom}:
|
||||
get:
|
||||
summary: SupplyOf queries the supply of a single coin.
|
||||
operationId: SupplyOf
|
||||
@ -4797,7 +5044,7 @@ paths:
|
||||
format: byte
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards':
|
||||
/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards:
|
||||
get:
|
||||
summary: |-
|
||||
DelegationTotalRewards queries the total rewards accrued by a each
|
||||
@ -4890,7 +5137,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards/{validator_address}':
|
||||
/cosmos/distribution/v1beta1/delegators/{delegator_address}/rewards/{validator_address}:
|
||||
get:
|
||||
summary: DelegationRewards queries the total rewards accrued by a delegation.
|
||||
operationId: DelegationRewards
|
||||
@ -4957,7 +5204,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/delegators/{delegator_address}/validators':
|
||||
/cosmos/distribution/v1beta1/delegators/{delegator_address}/validators:
|
||||
get:
|
||||
summary: DelegatorValidators queries the validators of a delegator.
|
||||
operationId: DistDelegatorValidators
|
||||
@ -5007,7 +5254,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/delegators/{delegator_address}/withdraw_address':
|
||||
/cosmos/distribution/v1beta1/delegators/{delegator_address}/withdraw_address:
|
||||
get:
|
||||
summary: DelegatorWithdrawAddress queries withdraw address of a delegator.
|
||||
operationId: DelegatorWithdrawAddress
|
||||
@ -5102,7 +5349,7 @@ paths:
|
||||
format: byte
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/validators/{validator_address}/commission':
|
||||
/cosmos/distribution/v1beta1/validators/{validator_address}/commission:
|
||||
get:
|
||||
summary: ValidatorCommission queries accumulated commission for a validator.
|
||||
operationId: ValidatorCommission
|
||||
@ -5167,7 +5414,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/validators/{validator_address}/outstanding_rewards':
|
||||
/cosmos/distribution/v1beta1/validators/{validator_address}/outstanding_rewards:
|
||||
get:
|
||||
summary: ValidatorOutstandingRewards queries rewards of a validator address.
|
||||
operationId: ValidatorOutstandingRewards
|
||||
@ -5239,7 +5486,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/distribution/v1beta1/validators/{validator_address}/slashes':
|
||||
/cosmos/distribution/v1beta1/validators/{validator_address}/slashes:
|
||||
get:
|
||||
summary: ValidatorSlashes queries slash events of a validator.
|
||||
operationId: ValidatorSlashes
|
||||
@ -5536,7 +5783,7 @@ paths:
|
||||
format: byte
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/params/{params_type}':
|
||||
/cosmos/gov/v1beta1/params/{params_type}:
|
||||
get:
|
||||
summary: Params queries all parameters of the gov module.
|
||||
operationId: GovParams
|
||||
@ -6380,7 +6627,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/proposals/{proposal_id}':
|
||||
/cosmos/gov/v1beta1/proposals/{proposal_id}:
|
||||
get:
|
||||
summary: Proposal queries proposal details based on ProposalID.
|
||||
operationId: Proposal
|
||||
@ -6843,7 +7090,7 @@ paths:
|
||||
format: uint64
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits':
|
||||
/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits:
|
||||
get:
|
||||
summary: Deposits queries all deposits of a single proposal.
|
||||
operationId: Deposits
|
||||
@ -7158,7 +7405,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}':
|
||||
/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}:
|
||||
get:
|
||||
summary: >-
|
||||
Deposit queries single deposit information based proposalID,
|
||||
@ -7406,7 +7653,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/proposals/{proposal_id}/tally':
|
||||
/cosmos/gov/v1beta1/proposals/{proposal_id}/tally:
|
||||
get:
|
||||
summary: TallyResult queries the tally of a proposal vote.
|
||||
operationId: TallyResult
|
||||
@ -7631,7 +7878,7 @@ paths:
|
||||
format: uint64
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/proposals/{proposal_id}/votes':
|
||||
/cosmos/gov/v1beta1/proposals/{proposal_id}/votes:
|
||||
get:
|
||||
summary: Votes queries votes of a given proposal.
|
||||
operationId: Votes
|
||||
@ -7975,9 +8222,9 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}':
|
||||
/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}:
|
||||
get:
|
||||
summary: 'Vote queries voted information based on proposalID, voterAddr.'
|
||||
summary: Vote queries voted information based on proposalID, voterAddr.
|
||||
operationId: Vote
|
||||
responses:
|
||||
'200':
|
||||
@ -8250,7 +8497,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/delegations/{delegator_addr}':
|
||||
/cosmos/staking/v1beta1/delegations/{delegator_addr}:
|
||||
get:
|
||||
summary: >-
|
||||
DelegatorDelegations queries all delegations of a given delegator
|
||||
@ -8586,7 +8833,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/delegators/{delegator_addr}/redelegations':
|
||||
/cosmos/staking/v1beta1/delegators/{delegator_addr}/redelegations:
|
||||
get:
|
||||
summary: Redelegations queries redelegations of given address.
|
||||
operationId: Redelegations
|
||||
@ -8992,7 +9239,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/delegators/{delegator_addr}/unbonding_delegations':
|
||||
/cosmos/staking/v1beta1/delegators/{delegator_addr}/unbonding_delegations:
|
||||
get:
|
||||
summary: >-
|
||||
DelegatorUnbondingDelegations queries all unbonding delegations of a
|
||||
@ -9330,7 +9577,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators':
|
||||
/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators:
|
||||
get:
|
||||
summary: |-
|
||||
DelegatorValidators queries all validators info for given delegator
|
||||
@ -9926,7 +10173,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators/{validator_addr}':
|
||||
/cosmos/staking/v1beta1/delegators/{delegator_addr}/validators/{validator_addr}:
|
||||
get:
|
||||
summary: |-
|
||||
DelegatorValidator queries validator info for given delegator validator
|
||||
@ -10450,7 +10697,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/historical_info/{height}':
|
||||
/cosmos/staking/v1beta1/historical_info/{height}:
|
||||
get:
|
||||
summary: HistoricalInfo queries the historical info for given height.
|
||||
operationId: HistoricalInfo
|
||||
@ -12092,7 +12339,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/validators/{validator_addr}':
|
||||
/cosmos/staking/v1beta1/validators/{validator_addr}:
|
||||
get:
|
||||
summary: Validator queries validator info for given validator address.
|
||||
operationId: Validator
|
||||
@ -12609,7 +12856,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/validators/{validator_addr}/delegations':
|
||||
/cosmos/staking/v1beta1/validators/{validator_addr}/delegations:
|
||||
get:
|
||||
summary: ValidatorDelegations queries delegate info for given validator.
|
||||
operationId: ValidatorDelegations
|
||||
@ -12940,7 +13187,7 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}':
|
||||
/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}:
|
||||
get:
|
||||
summary: Delegation queries delegate info for given validator delegator pair.
|
||||
operationId: Delegation
|
||||
@ -13203,7 +13450,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}/unbonding_delegation':
|
||||
/cosmos/staking/v1beta1/validators/{validator_addr}/delegations/{delegator_addr}/unbonding_delegation:
|
||||
get:
|
||||
summary: |-
|
||||
UnbondingDelegation queries unbonding info for given validator delegator
|
||||
@ -13469,7 +13716,7 @@ paths:
|
||||
type: string
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/staking/v1beta1/validators/{validator_addr}/unbonding_delegations':
|
||||
/cosmos/staking/v1beta1/validators/{validator_addr}/unbonding_delegations:
|
||||
get:
|
||||
summary: >-
|
||||
ValidatorUnbondingDelegations queries unbonding delegations of a
|
||||
@ -13811,7 +14058,7 @@ definitions:
|
||||
properties:
|
||||
homestead_block:
|
||||
type: string
|
||||
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
|
||||
title: Homestead switch block (nil no fork, 0 = already homestead)
|
||||
dao_fork_block:
|
||||
type: string
|
||||
title: TheDAO hard-fork switch block (nil no fork)
|
||||
@ -13838,16 +14085,16 @@ definitions:
|
||||
title: EIP158 HF block
|
||||
byzantium_block:
|
||||
type: string
|
||||
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
|
||||
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)'
|
||||
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)'
|
||||
title: Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||
muir_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
@ -13855,10 +14102,20 @@ definitions:
|
||||
activated)
|
||||
berlin_block:
|
||||
type: string
|
||||
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
|
||||
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)'
|
||||
title: London switch block (nil = no fork, 0 = already on london)
|
||||
arrow_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in merge
|
||||
proceedings)
|
||||
description: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
|
||||
values
|
||||
@ -13886,7 +14143,7 @@ definitions:
|
||||
data:
|
||||
type: string
|
||||
format: byte
|
||||
title: 'supplied by the contract, usually ABI-encoded'
|
||||
title: supplied by the contract, usually ABI-encoded
|
||||
block_number:
|
||||
type: string
|
||||
format: uint64
|
||||
@ -14123,7 +14380,7 @@ definitions:
|
||||
data:
|
||||
type: string
|
||||
format: byte
|
||||
title: 'supplied by the contract, usually ABI-encoded'
|
||||
title: supplied by the contract, usually ABI-encoded
|
||||
block_number:
|
||||
type: string
|
||||
format: uint64
|
||||
@ -14205,7 +14462,7 @@ definitions:
|
||||
properties:
|
||||
homestead_block:
|
||||
type: string
|
||||
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
|
||||
title: Homestead switch block (nil no fork, 0 = already homestead)
|
||||
dao_fork_block:
|
||||
type: string
|
||||
title: TheDAO hard-fork switch block (nil no fork)
|
||||
@ -14232,16 +14489,16 @@ definitions:
|
||||
title: EIP158 HF block
|
||||
byzantium_block:
|
||||
type: string
|
||||
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
|
||||
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)'
|
||||
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)'
|
||||
title: Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||
muir_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
@ -14249,15 +14506,32 @@ definitions:
|
||||
activated)
|
||||
berlin_block:
|
||||
type: string
|
||||
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
|
||||
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)'
|
||||
title: London switch block (nil = no fork, 0 = already on london)
|
||||
arrow_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
|
||||
merge proceedings)
|
||||
description: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
|
||||
values
|
||||
|
||||
instead of *big.Int.
|
||||
allow_unprotected_txs:
|
||||
type: boolean
|
||||
description: >-
|
||||
Allow unprotected transactions defines if replay-protected (i.e non
|
||||
EIP155
|
||||
|
||||
signed) transactions can be executed on the state machine.
|
||||
title: Params defines the EVM module parameters
|
||||
ethermint.evm.v1.QueryAccountResponse:
|
||||
type: object
|
||||
@ -14284,6 +14558,12 @@ definitions:
|
||||
description: >-
|
||||
QueryBalanceResponse is the response type for the Query/Balance RPC
|
||||
method.
|
||||
ethermint.evm.v1.QueryBaseFeeResponse:
|
||||
type: object
|
||||
properties:
|
||||
base_fee:
|
||||
type: string
|
||||
description: BaseFeeResponse returns the EIP1559 base fee.
|
||||
ethermint.evm.v1.QueryCodeResponse:
|
||||
type: object
|
||||
properties:
|
||||
@ -14349,7 +14629,7 @@ definitions:
|
||||
properties:
|
||||
homestead_block:
|
||||
type: string
|
||||
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
|
||||
title: Homestead switch block (nil no fork, 0 = already homestead)
|
||||
dao_fork_block:
|
||||
type: string
|
||||
title: TheDAO hard-fork switch block (nil no fork)
|
||||
@ -14376,7 +14656,7 @@ definitions:
|
||||
title: EIP158 HF block
|
||||
byzantium_block:
|
||||
type: string
|
||||
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
|
||||
title: Byzantium switch block (nil no fork, 0 = already on byzantium)
|
||||
constantinople_block:
|
||||
type: string
|
||||
title: >-
|
||||
@ -14387,7 +14667,7 @@ definitions:
|
||||
title: Petersburg switch block (nil same as Constantinople)
|
||||
istanbul_block:
|
||||
type: string
|
||||
title: 'Istanbul switch block (nil no fork, 0 = already on istanbul)'
|
||||
title: Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||
muir_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
@ -14395,15 +14675,32 @@ definitions:
|
||||
activated)
|
||||
berlin_block:
|
||||
type: string
|
||||
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
|
||||
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)'
|
||||
title: London switch block (nil = no fork, 0 = already on london)
|
||||
arrow_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already
|
||||
in merge proceedings)
|
||||
description: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using
|
||||
*sdk.Int values
|
||||
|
||||
instead of *big.Int.
|
||||
allow_unprotected_txs:
|
||||
type: boolean
|
||||
description: >-
|
||||
Allow unprotected transactions defines if replay-protected (i.e
|
||||
non EIP155
|
||||
|
||||
signed) transactions can be executed on the state machine.
|
||||
title: Params defines the EVM module parameters
|
||||
description: >-
|
||||
QueryParamsResponse defines the response type for querying x/evm
|
||||
@ -14480,7 +14777,7 @@ definitions:
|
||||
limit:
|
||||
type: integer
|
||||
format: int32
|
||||
title: 'maximum length of output, but zero means unlimited'
|
||||
title: maximum length of output, but zero means unlimited
|
||||
overrides:
|
||||
title: >-
|
||||
Chain overrides, can be used to execute a trace using future fork
|
||||
@ -14489,7 +14786,7 @@ definitions:
|
||||
properties:
|
||||
homestead_block:
|
||||
type: string
|
||||
title: 'Homestead switch block (nil no fork, 0 = already homestead)'
|
||||
title: Homestead switch block (nil no fork, 0 = already homestead)
|
||||
dao_fork_block:
|
||||
type: string
|
||||
title: TheDAO hard-fork switch block (nil no fork)
|
||||
@ -14516,16 +14813,16 @@ definitions:
|
||||
title: EIP158 HF block
|
||||
byzantium_block:
|
||||
type: string
|
||||
title: 'Byzantium switch block (nil no fork, 0 = already on byzantium)'
|
||||
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)'
|
||||
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)'
|
||||
title: Istanbul switch block (nil no fork, 0 = already on istanbul)
|
||||
muir_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
@ -14533,10 +14830,20 @@ definitions:
|
||||
activated)
|
||||
berlin_block:
|
||||
type: string
|
||||
title: 'Berlin switch block (nil = no fork, 0 = already on berlin)'
|
||||
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)'
|
||||
title: London switch block (nil = no fork, 0 = already on london)
|
||||
arrow_glacier_block:
|
||||
type: string
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
|
||||
merge proceedings)
|
||||
description: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
|
||||
values
|
||||
@ -17468,7 +17775,7 @@ definitions:
|
||||
properties:
|
||||
rate:
|
||||
type: string
|
||||
description: 'rate is the commission rate charged to delegators, as a fraction.'
|
||||
description: rate is the commission rate charged to delegators, as a fraction.
|
||||
max_rate:
|
||||
type: string
|
||||
description: >-
|
||||
@ -17489,7 +17796,7 @@ definitions:
|
||||
properties:
|
||||
rate:
|
||||
type: string
|
||||
description: 'rate is the commission rate charged to delegators, as a fraction.'
|
||||
description: rate is the commission rate charged to delegators, as a fraction.
|
||||
max_rate:
|
||||
type: string
|
||||
description: >-
|
||||
|
@ -6,10 +6,8 @@ import (
|
||||
"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"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/spf13/cobra"
|
||||
@ -27,19 +25,8 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
|
||||
Long: `**UNSAFE** Export an Ethereum private key unencrypted to use in dev tooling`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(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)
|
||||
kr, err := keyring.New(
|
||||
sdk.KeyringServiceName(),
|
||||
keyringBackend,
|
||||
rootDir,
|
||||
inBuf,
|
||||
clientCtx.Codec,
|
||||
hd.EthSecp256k1Option(),
|
||||
)
|
||||
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -47,7 +34,8 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
|
||||
decryptPassword := ""
|
||||
conf := true
|
||||
|
||||
switch keyringBackend {
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
switch clientCtx.Keyring.Backend() {
|
||||
case keyring.BackendFile:
|
||||
decryptPassword, err = input.GetPassword(
|
||||
"**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:",
|
||||
@ -62,7 +50,7 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
// Exports private key from keybase using password
|
||||
armor, err := kr.ExportPrivKeyArmor(args[0], decryptPassword)
|
||||
armor, err := clientCtx.Keyring.ExportPrivKeyArmor(args[0], decryptPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -7,11 +7,8 @@ import (
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"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"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/hd"
|
||||
@ -29,23 +26,13 @@ func UnsafeImportKeyCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
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(),
|
||||
)
|
||||
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
passphrase, err := input.GetPassword("Enter passphrase to encrypt your key:", inBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -57,5 +44,5 @@ func runImportCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
armor := crypto.EncryptArmorPrivKey(privKey, passphrase, "eth_secp256k1")
|
||||
|
||||
return kb.ImportPrivKey(args[0], armor, passphrase)
|
||||
return clientCtx.Keyring.ImportPrivKey(args[0], armor, passphrase)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
@ -49,7 +48,7 @@ The pass backend requires GnuPG: https://gnupg.org/
|
||||
addCmd := keys.AddKeyCommand()
|
||||
|
||||
// update the default signing algorithm value to "eth_secp256k1"
|
||||
algoFlag := addCmd.Flag("algo")
|
||||
algoFlag := addCmd.Flag(flags.FlagKeyAlgorithm)
|
||||
algoFlag.DefValue = string(hd.EthSecp256k1Type)
|
||||
err := algoFlag.Value.Set(string(hd.EthSecp256k1Type))
|
||||
if err != nil {
|
||||
@ -65,8 +64,8 @@ The pass backend requires GnuPG: https://gnupg.org/
|
||||
keys.ImportKeyCommand(),
|
||||
keys.ListKeysCmd(),
|
||||
keys.ShowKeysCmd(),
|
||||
flags.LineBreak,
|
||||
keys.DeleteKeyCommand(),
|
||||
keys.RenameKeyCommand(),
|
||||
keys.ParseKeyStringCommand(),
|
||||
keys.MigrateCommand(),
|
||||
flags.LineBreak,
|
||||
@ -82,23 +81,11 @@ The pass backend requires GnuPG: https://gnupg.org/
|
||||
}
|
||||
|
||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
buf := bufio.NewReader(cmd.InOrStdin())
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
|
||||
var (
|
||||
kr keyring.Keyring
|
||||
err 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)
|
||||
}
|
||||
|
||||
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := bufio.NewReader(clientCtx.Input)
|
||||
return clientkeys.RunAddCmd(clientCtx, cmd, args, buf)
|
||||
}
|
||||
|
@ -38,70 +38,16 @@ const (
|
||||
mnemonicEntropySize = 256
|
||||
)
|
||||
|
||||
// AddKeyCommand defines a keys command to add a generated or recovered private key to keybase.
|
||||
func AddKeyCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add <name>",
|
||||
Short: "Add an encrypted private key (either newly generated or recovered), encrypt it, and save to <name> file",
|
||||
Long: `Derive a new private key and encrypt to disk.
|
||||
Optionally specify a BIP39 mnemonic, a BIP39 passphrase to further secure the mnemonic,
|
||||
and a bip32 HD path to derive a specific account. The key will be stored under the given name
|
||||
and encrypted with the given password. The only input that is required is the encryption password.
|
||||
|
||||
If run with -i, it will prompt the user for BIP44 path, BIP39 mnemonic, and passphrase.
|
||||
The flag --recover allows one to recover a key from a seed passphrase.
|
||||
If run with --dry-run, a key would be generated (or recovered) but not stored to the
|
||||
local keystore.
|
||||
Use the --pubkey flag to add arbitrary public keys to the keystore for constructing
|
||||
multisig transactions.
|
||||
|
||||
You can create and store a multisig key by passing the list of key names stored in a keyring
|
||||
and the minimum number of signatures required through --multisig-threshold. The keys are
|
||||
sorted by address, unless the flag --nosort is set.
|
||||
Example:
|
||||
|
||||
keys add mymultisig --multisig "keyname1,keyname2,keyname3" --multisig-threshold 2
|
||||
`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runAddCmdPrepare,
|
||||
}
|
||||
f := cmd.Flags()
|
||||
f.StringSlice(flagMultisig, nil, "List of key names stored in keyring to construct a public legacy multisig key")
|
||||
f.Int(flagMultiSigThreshold, 1, "K out of N required signatures. For use in conjunction with --multisig")
|
||||
f.Bool(flagNoSort, false, "Keys passed to --multisig are taken in the order they're supplied")
|
||||
f.String(keys.FlagPublicKey, "", "Parse a public key in JSON format and saves key info to <name> file.")
|
||||
f.BoolP(flagInteractive, "i", false, "Interactively prompt user for BIP39 passphrase and mnemonic")
|
||||
f.Bool(flags.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device")
|
||||
f.Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating")
|
||||
f.Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)")
|
||||
f.Bool(flags.FlagDryRun, false, "Perform action, but don't add key to local keystore")
|
||||
f.String(flagHDPath, "", "Manual HD Path derivation (overrides BIP44 config)")
|
||||
f.Uint32(flagCoinType, sdk.GetConfig().GetCoinType(), "coin type number for HD derivation")
|
||||
f.Uint32(flagAccount, 0, "Account number for HD derivation")
|
||||
f.Uint32(flagIndex, 0, "Address index number for HD derivation")
|
||||
f.String(flags.FlagKeyAlgorithm, string(etherminthd.EthSecp256k1Type), "Key signing algorithm to generate keys for")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runAddCmdPrepare(cmd *cobra.Command, args []string) error {
|
||||
buf := bufio.NewReader(cmd.InOrStdin())
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return RunAddCmd(clientCtx, cmd, args, buf)
|
||||
}
|
||||
|
||||
/*
|
||||
RunAddCmd
|
||||
input
|
||||
- bip39 mnemonic
|
||||
- bip39 passphrase
|
||||
- bip44 path
|
||||
- local encryption password
|
||||
- bip39 mnemonic
|
||||
- bip39 passphrase
|
||||
- bip44 path
|
||||
- local encryption password
|
||||
|
||||
output
|
||||
- armor encrypted private key (saved to file)
|
||||
- armor encrypted private key (saved to file)
|
||||
*/
|
||||
func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *bufio.Reader) error {
|
||||
var err error
|
||||
@ -156,9 +102,11 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
||||
return err
|
||||
}
|
||||
|
||||
if pks[i], err = k.GetPubKey(); err != nil {
|
||||
key, err := k.GetPubKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pks[i] = key
|
||||
}
|
||||
|
||||
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
|
||||
@ -168,29 +116,28 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
||||
}
|
||||
|
||||
pk := multisig.NewLegacyAminoPubKey(multisigThreshold, pks)
|
||||
info, err := kb.SaveMultisig(name, pk)
|
||||
k, err := kb.SaveMultisig(name, pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return printCreate(cmd, info, false, "", outputFormat)
|
||||
return printCreate(cmd, k, false, "", outputFormat)
|
||||
}
|
||||
}
|
||||
|
||||
pubKey, _ := cmd.Flags().GetString(keys.FlagPublicKey)
|
||||
if pubKey != "" {
|
||||
var pk cryptotypes.PubKey
|
||||
err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk)
|
||||
if err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k, err := kb.SaveOfflineKey(name, pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := kb.SaveOfflineKey(name, pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return printCreate(cmd, info, false, "", outputFormat)
|
||||
return printCreate(cmd, k, false, "", outputFormat)
|
||||
}
|
||||
|
||||
coinType, _ := cmd.Flags().GetUint32(flagCoinType)
|
||||
@ -208,13 +155,12 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
||||
// If we're using ledger, only thing we need is the path and the bech32 prefix.
|
||||
if useLedger {
|
||||
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
|
||||
|
||||
info, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index)
|
||||
k, err := kb.SaveLedgerKey(name, hd.Secp256k1, bech32PrefixAccAddr, coinType, account, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return printCreate(cmd, info, false, "", outputFormat)
|
||||
return printCreate(cmd, k, false, "", outputFormat)
|
||||
}
|
||||
|
||||
// Get bip39 mnemonic
|
||||
@ -276,7 +222,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
||||
}
|
||||
}
|
||||
|
||||
info, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
|
||||
k, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -288,24 +234,27 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
||||
mnemonic = ""
|
||||
}
|
||||
|
||||
return printCreate(cmd, info, showMnemonic, mnemonic, outputFormat)
|
||||
return printCreate(cmd, k, showMnemonic, mnemonic, outputFormat)
|
||||
}
|
||||
|
||||
func printCreate(cmd *cobra.Command, info *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
|
||||
func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
|
||||
switch outputFormat {
|
||||
case OutputFormatText:
|
||||
cmd.PrintErrln()
|
||||
printKeyInfo(cmd.OutOrStdout(), info, keyring.MkAccKeyOutput, outputFormat)
|
||||
if err := printKeyringRecord(cmd.OutOrStdout(), k, keyring.MkAccKeyOutput, outputFormat); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// print mnemonic unless requested not to.
|
||||
if showMnemonic {
|
||||
fmt.Fprintln(cmd.ErrOrStderr(), "\n**Important** write this mnemonic phrase in a safe place.")
|
||||
fmt.Fprintln(cmd.ErrOrStderr(), "It is the only way to recover your account if you ever forget your password.")
|
||||
fmt.Fprintln(cmd.ErrOrStderr(), "")
|
||||
fmt.Fprintln(cmd.ErrOrStderr(), mnemonic)
|
||||
if _, err := fmt.Fprintf(cmd.ErrOrStderr(),
|
||||
"\n**Important** write this mnemonic phrase in a safe place.\nIt is the only way to recover your account if you ever forget your password.\n\n%s\n\n", //nolint:lll
|
||||
mnemonic); err != nil {
|
||||
return fmt.Errorf("failed to print mnemonic: %v", err)
|
||||
}
|
||||
}
|
||||
case OutputFormatJSON:
|
||||
out, err := keyring.MkAccKeyOutput(info)
|
||||
out, err := keyring.MkAccKeyOutput(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -327,3 +276,14 @@ func printCreate(cmd *cobra.Command, info *keyring.Record, showMnemonic bool, mn
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateMultisigThreshold(k, nKeys int) error {
|
||||
if k <= 0 {
|
||||
return fmt.Errorf("threshold must be a positive integer")
|
||||
}
|
||||
if nKeys < k {
|
||||
return fmt.Errorf(
|
||||
"threshold k of n multisignature: %d < %d", nKeys, k)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
)
|
||||
|
||||
// Commands registers a sub-tree of commands to interact with
|
||||
// local private key storage.
|
||||
func Commands(defaultNodeHome string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Manage your application's keys",
|
||||
Long: `Keyring management commands. These keys may be in any format supported by the
|
||||
Tendermint crypto library and can be used by light-clients, full nodes, or any other application
|
||||
that needs to sign with a private key.
|
||||
|
||||
The keyring supports the following backends:
|
||||
|
||||
os Uses the operating system's default credentials store.
|
||||
file Uses encrypted file-based keystore within the app's configuration directory.
|
||||
This keyring will request a password each time it is accessed, which may occur
|
||||
multiple times in a single command resulting in repeated password prompts.
|
||||
kwallet Uses KDE Wallet Manager as a credentials management application.
|
||||
pass Uses the pass command line utility to store and retrieve keys.
|
||||
test Stores keys insecurely to disk. It does not prompt for a password to be unlocked
|
||||
and it should be use only for testing purposes.
|
||||
|
||||
kwallet and pass backends depend on external tools. Refer to their respective documentation for more
|
||||
information:
|
||||
KWallet https://github.com/KDE/kwallet
|
||||
pass https://www.passwordstore.org/
|
||||
|
||||
The pass backend requires GnuPG: https://gnupg.org/
|
||||
`,
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
keys.MnemonicKeyCommand(),
|
||||
AddKeyCommand(),
|
||||
keys.ExportKeyCommand(),
|
||||
keys.ImportKeyCommand(),
|
||||
keys.ListKeysCmd(),
|
||||
keys.ShowKeysCmd(),
|
||||
flags.LineBreak,
|
||||
keys.DeleteKeyCommand(),
|
||||
keys.ParseKeyStringCommand(),
|
||||
keys.MigrateCommand(),
|
||||
)
|
||||
|
||||
cmd.PersistentFlags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
|
||||
cmd.PersistentFlags().String(flags.FlagKeyringDir, "", "The client Keyring directory; if omitted, the default 'home' directory will be used")
|
||||
cmd.PersistentFlags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
cmd.PersistentFlags().String(cli.OutputFlag, "text", "Output format (text|json)")
|
||||
|
||||
return cmd
|
||||
}
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
@ -14,48 +14,45 @@ import (
|
||||
const (
|
||||
OutputFormatText = "text"
|
||||
OutputFormatJSON = "json"
|
||||
|
||||
// defaultKeyDBName is the client's subdirectory where keys are stored.
|
||||
defaultKeyDBName = "keys"
|
||||
)
|
||||
|
||||
type bechKeyOutFn func(keyInfo *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
|
||||
type bechKeyOutFn func(k *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
|
||||
|
||||
func printKeyInfo(w io.Writer, keyInfo *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) {
|
||||
ko, err := bechKeyOut(keyInfo)
|
||||
func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) error {
|
||||
ko, err := bechKeyOut(k)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
switch output {
|
||||
case OutputFormatText:
|
||||
printTextInfos(w, []cryptokeyring.KeyOutput{ko})
|
||||
if err := printTextRecords(w, []cryptokeyring.KeyOutput{ko}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case OutputFormatJSON:
|
||||
out, err := keys.KeysCdc.MarshalJSON(ko)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, string(out))
|
||||
if _, err := fmt.Fprintln(w, string(out)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printTextRecords(w io.Writer, kos []cryptokeyring.KeyOutput) error {
|
||||
out, err := yaml.Marshal(&kos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintln(w, string(out)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func printTextInfos(w io.Writer, kos []cryptokeyring.KeyOutput) {
|
||||
out, err := yaml.Marshal(&kos)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Fprintln(w, string(out))
|
||||
}
|
||||
|
||||
func validateMultisigThreshold(k, nKeys int) error {
|
||||
if k <= 0 {
|
||||
return fmt.Errorf("threshold must be a positive integer")
|
||||
}
|
||||
if nKeys < k {
|
||||
return fmt.Errorf(
|
||||
"threshold k of n multisignature: %d < %d", nKeys, k)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -6,18 +6,17 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
tmcfg "github.com/tendermint/tendermint/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
tmconfig "github.com/tendermint/tendermint/config"
|
||||
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"
|
||||
@ -35,8 +34,7 @@ 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"
|
||||
|
||||
govv1 "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"
|
||||
|
||||
@ -89,9 +87,12 @@ type startArgs struct {
|
||||
|
||||
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().StringP(flagOutputDir, "o", "./.testnets", "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(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")
|
||||
}
|
||||
|
||||
@ -116,7 +117,7 @@ func NewTestnetCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBala
|
||||
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)",
|
||||
Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)", //nolint:lll
|
||||
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.
|
||||
|
||||
@ -126,7 +127,7 @@ 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:
|
||||
laconicd testnet init-files --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
|
||||
evmosd 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)
|
||||
@ -153,8 +154,10 @@ Example:
|
||||
|
||||
addTestnetFlagsToCmd(cmd)
|
||||
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)")
|
||||
cmd.Flags().String(flagNodeDaemonHome, "laconicd", "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(flagNodeDaemonHome, "evmosd", "Home directory of the node's daemon configuration")
|
||||
cmd.Flags().String(flagStartingIPAddress,
|
||||
"192.168.0.1",
|
||||
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
|
||||
return cmd
|
||||
@ -170,7 +173,7 @@ and generate "v" directories, populated with necessary validator configuration f
|
||||
(private validator, genesis, config, etc.).
|
||||
|
||||
Example:
|
||||
laconicd testnet --v 4 --output-dir ./.testnets
|
||||
evmosd testnet --v 4 --output-dir ./.testnets
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
args := startArgs{}
|
||||
@ -212,7 +215,7 @@ func initTestnetFiles(
|
||||
args initArgs,
|
||||
) error {
|
||||
if args.chainID == "" {
|
||||
args.chainID = fmt.Sprintf("ethermint_%d-1", rand.Int63n(9999999999999)+1)
|
||||
args.chainID = fmt.Sprintf("ethermint_%d-1", tmrand.Int63n(9999999999999)+1)
|
||||
}
|
||||
|
||||
nodeIDs := make([]string, args.numValidators)
|
||||
@ -346,8 +349,7 @@ func initTestnetFiles(
|
||||
|
||||
customAppTemplate, customAppConfig := config.AppConfig(ethermint.AttoPhoton)
|
||||
srvconfig.SetConfigTemplate(customAppTemplate)
|
||||
customTmConfig := tmcfg.DefaultConfig()
|
||||
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTmConfig); err != nil {
|
||||
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, tmconfig.DefaultConfig()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -406,7 +408,7 @@ func initGenFiles(
|
||||
stakingGenState.Params.BondDenom = coinDenom
|
||||
appGenState[stakingtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&stakingGenState)
|
||||
|
||||
var govGenState v1.GenesisState
|
||||
var govGenState govv1.GenesisState
|
||||
clientCtx.Codec.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
|
||||
|
||||
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
|
||||
@ -456,7 +458,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)
|
||||
|
@ -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
|
||||
@ -40,7 +40,7 @@ func SetBech32Prefixes(config *sdk.Config) {
|
||||
func SetBip44CoinType(config *sdk.Config) {
|
||||
config.SetCoinType(ethermint.Bip44CoinType)
|
||||
config.SetPurpose(sdk.Purpose) // Shared
|
||||
config.SetFullFundraiserPath(ethermint.BIP44HDPath) // nolint: staticcheck
|
||||
config.SetFullFundraiserPath(ethermint.BIP44HDPath) //nolint: staticcheck
|
||||
}
|
||||
|
||||
// RegisterDenoms registers the base and display denominations to the SDK.
|
||||
|
@ -23,6 +23,6 @@ func TestInitCmd(t *testing.T) {
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint_9000-1"),
|
||||
})
|
||||
|
||||
err := svrcmd.Execute(rootCmd, laconicd.EnvPrefix, app.DefaultNodeHome)
|
||||
err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -11,7 +10,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"
|
||||
@ -43,36 +41,20 @@ 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)
|
||||
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
serverCtx := server.GetServerContextFromCmd(cmd)
|
||||
config := serverCtx.Config
|
||||
|
||||
config.SetRoot(clientCtx.HomeDir)
|
||||
|
||||
var kr keyring.Keyring
|
||||
kr := clientCtx.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])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get address from Keyring: %w", err)
|
||||
@ -80,7 +62,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
|
||||
|
||||
addr, err = info.GetAddress()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get address from Keyring: %w", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,19 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cerc-io/laconicd/app"
|
||||
cmdcfg "github.com/cerc-io/laconicd/cmd/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
setupConfig()
|
||||
cmdcfg.RegisterDenoms()
|
||||
|
||||
rootCmd, _ := NewRootCmd()
|
||||
|
||||
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
|
||||
if err := svrcmd.Execute(rootCmd, EnvPrefix, app.DefaultNodeHome); err != nil {
|
||||
switch e := err.(type) {
|
||||
case server.ErrorCode:
|
||||
os.Exit(e.Code)
|
||||
@ -22,3 +27,11 @@ func main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupConfig() {
|
||||
// set the address prefixes
|
||||
config := sdk.GetConfig()
|
||||
cmdcfg.SetBech32Prefixes(config)
|
||||
cmdcfg.SetBip44CoinType(config)
|
||||
config.Seal()
|
||||
}
|
||||
|
@ -6,13 +6,19 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"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"
|
||||
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"
|
||||
@ -25,11 +31,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/cerc-io/laconicd/app"
|
||||
ethermintclient "github.com/cerc-io/laconicd/client"
|
||||
@ -42,7 +43,7 @@ import (
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
)
|
||||
|
||||
const EnvPrefix = "LACONIC"
|
||||
const EnvPrefix = "ETHERMINT"
|
||||
|
||||
// NewRootCmd creates a new root command for simd. It is called once in the
|
||||
// main function.
|
||||
@ -62,7 +63,7 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "laconicd",
|
||||
Short: "Laconic Daemon",
|
||||
Short: "Ethermint Daemon",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
|
||||
// set the default command outputs
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
@ -84,14 +85,13 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
||||
|
||||
// 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, tmcfg.DefaultConfig())
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: double-check
|
||||
// authclient.Codec = encodingConfig.Marshaler
|
||||
// authclient.Codec = encodingConfig.Codec
|
||||
|
||||
cfg := sdk.GetConfig()
|
||||
cfg.Seal()
|
||||
@ -140,18 +140,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 +195,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 +213,11 @@ 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"))
|
||||
if err = os.MkdirAll(snapshotDir, os.ModePerm); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
snapshotDB, err := dbm.NewDB("metadata", sdkserver.GetAppDBBackend(appOpts), snapshotDir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -233,6 +225,7 @@ 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)),
|
||||
@ -261,7 +254,7 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore
|
||||
// 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
|
||||
|
@ -30,7 +30,7 @@ if [ -z "$4" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker_containers=($(docker ps -q -f name=ethermintd --format='{{.Names}}'))
|
||||
docker_containers=($(docker ps -q -f name=laconicd --format='{{.Names}}'))
|
||||
|
||||
while [ ${CNT} -lt $ITER ]; do
|
||||
curr_block=$(curl -s $NODEADDR:26657/status | jq -r '.result.sync_info.latest_block_height')
|
||||
|
@ -4,25 +4,31 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
||||
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
|
||||
|
||||
cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
amino "github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
|
||||
cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
|
||||
enccodec "github.com/cerc-io/laconicd/encoding/codec"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
)
|
||||
|
||||
var protoCodec codec.Codec
|
||||
var TestCodec codec.Codec
|
||||
|
||||
func init() {
|
||||
protoCodec = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
|
||||
amino := codec.NewLegacyAmino()
|
||||
cryptocodec.RegisterCrypto(amino)
|
||||
cdc := codec.NewLegacyAmino()
|
||||
cryptocodec.RegisterCrypto(cdc)
|
||||
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
TestCodec = amino.NewProtoCodec(interfaceRegistry)
|
||||
enccodec.RegisterInterfaces(interfaceRegistry)
|
||||
}
|
||||
|
||||
const mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
|
||||
@ -31,7 +37,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, TestCodec, EthSecp256k1Option())
|
||||
require.NoError(t, err)
|
||||
|
||||
// fail in retrieving key
|
||||
@ -45,6 +51,9 @@ func TestKeyring(t *testing.T) {
|
||||
require.NotEmpty(t, mnemonic)
|
||||
require.Equal(t, "foo", info.Name)
|
||||
require.Equal(t, "local", info.GetType().String())
|
||||
pubKey, err := info.GetPubKey()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(EthSecp256k1Type), pubKey.Type())
|
||||
|
||||
hdPath := ethermint.BIP44HDPath
|
||||
|
||||
|
35
default.nix
Normal file
35
default.nix
Normal file
@ -0,0 +1,35 @@
|
||||
{ lib
|
||||
, buildGoApplication
|
||||
, rev ? "dirty"
|
||||
}:
|
||||
let
|
||||
version = "v0.17.1";
|
||||
pname = "laconicd";
|
||||
tags = [ "netgo" ];
|
||||
ldflags = lib.concatStringsSep "\n" ([
|
||||
"-X github.com/cosmos/cosmos-sdk/version.Name=ethermint"
|
||||
"-X github.com/cosmos/cosmos-sdk/version.AppName=${pname}"
|
||||
"-X github.com/cosmos/cosmos-sdk/version.Version=${version}"
|
||||
"-X github.com/cosmos/cosmos-sdk/version.BuildTags=${lib.concatStringsSep "," tags}"
|
||||
"-X github.com/cosmos/cosmos-sdk/version.Commit=${rev}"
|
||||
]);
|
||||
in
|
||||
buildGoApplication rec {
|
||||
inherit pname version tags ldflags;
|
||||
src = lib.sourceByRegex ./. [
|
||||
"^(x|app|cmd|client|server|crypto|rpc|types|encoding|ethereum|indexer|testutil|version|go.mod|go.sum|gomod2nix.toml)($|/.*)"
|
||||
"^tests(/.*[.]go)?$"
|
||||
];
|
||||
modules = ./gomod2nix.toml;
|
||||
doCheck = false;
|
||||
pwd = src; # needed to support replace
|
||||
subPackages = [ "cmd/laconicd" ];
|
||||
CGO_ENABLED = "1";
|
||||
|
||||
meta = with lib; {
|
||||
description = "Ethermint is a scalable and interoperable Ethereum library, built on Proof-of-Stake with fast-finality using the Cosmos SDK which runs on top of Tendermint Core consensus engine.";
|
||||
homepage = "https://github.com/evmos/ethermint";
|
||||
license = licenses.asl20;
|
||||
mainProgram = "laconicd";
|
||||
};
|
||||
}
|
@ -5,9 +5,7 @@ services:
|
||||
container_name: laconicdnode0
|
||||
image: "laconicd/node"
|
||||
ports:
|
||||
- "26656-26657:26656-26657"
|
||||
- "1317:1317"
|
||||
- "9090:9090"
|
||||
- "26657:26657"
|
||||
- "8545:8545"
|
||||
- "8546:8546"
|
||||
- "8125:8125"
|
||||
@ -15,18 +13,16 @@ services:
|
||||
- ID=0
|
||||
- LOG=${LOG:-laconicd.log}
|
||||
volumes:
|
||||
- ./localnet-setup/node0/laconicd:/laconic:Z
|
||||
- ./localnet-setup/node0/laconicd:/laconicd:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.168.10.1
|
||||
- localnet
|
||||
entrypoint: "bash start-docker.sh"
|
||||
|
||||
laconicdnode1:
|
||||
container_name: laconicdnode1
|
||||
image: "laconicd/node"
|
||||
ports:
|
||||
- "26666-26667:26656-26657"
|
||||
- "1318:1317"
|
||||
- "9091:9090"
|
||||
- "26658:26657"
|
||||
- "8555:8545"
|
||||
- "8556:8546"
|
||||
- "8126:8125"
|
||||
@ -34,10 +30,10 @@ services:
|
||||
- ID=1
|
||||
- LOG=${LOG:-laconicd.log}
|
||||
volumes:
|
||||
- ./localnet-setup/node1/laconicd:/laconic:Z
|
||||
- ./localnet-setup/node1/laconicd:/laconicd:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.168.10.2
|
||||
- localnet
|
||||
entrypoint: "bash start-docker.sh"
|
||||
|
||||
laconicdnode2:
|
||||
container_name: laconicdnode2
|
||||
@ -46,17 +42,15 @@ services:
|
||||
- ID=2
|
||||
- LOG=${LOG:-laconicd.log}
|
||||
ports:
|
||||
- "26676-26677:26656-26657"
|
||||
- "1319:1317"
|
||||
- "9092:9090"
|
||||
- "26659:26657"
|
||||
- "8565:8545"
|
||||
- "8566:8546"
|
||||
- "8127:8125"
|
||||
volumes:
|
||||
- ./localnet-setup/node2/laconicd:/laconic:Z
|
||||
- ./localnet-setup/node2/laconicd:/laconicd:Z
|
||||
networks:
|
||||
localnet:
|
||||
ipv4_address: 192.168.10.3
|
||||
- localnet
|
||||
entrypoint: "bash start-docker.sh"
|
||||
|
||||
laconicdnode3:
|
||||
container_name: laconicdnode3
|
||||
@ -65,23 +59,15 @@ services:
|
||||
- ID=3
|
||||
- LOG=${LOG:-laconicd.log}
|
||||
ports:
|
||||
- "26686-26687:26656-26657"
|
||||
- "1320:1317"
|
||||
- "9093:9090"
|
||||
- "26660:26657"
|
||||
- "8575:8545"
|
||||
- "8576:8546"
|
||||
- "8128:8125"
|
||||
volumes:
|
||||
- ./localnet-setup/node3/laconicd:/laconic:Z
|
||||
- ./localnet-setup/node3/laconicd:/laconicd: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
|
@ -39,6 +39,8 @@
|
||||
- [QueryAccountResponse](#ethermint.evm.v1.QueryAccountResponse)
|
||||
- [QueryBalanceRequest](#ethermint.evm.v1.QueryBalanceRequest)
|
||||
- [QueryBalanceResponse](#ethermint.evm.v1.QueryBalanceResponse)
|
||||
- [QueryBaseFeeRequest](#ethermint.evm.v1.QueryBaseFeeRequest)
|
||||
- [QueryBaseFeeResponse](#ethermint.evm.v1.QueryBaseFeeResponse)
|
||||
- [QueryCodeRequest](#ethermint.evm.v1.QueryCodeRequest)
|
||||
- [QueryCodeResponse](#ethermint.evm.v1.QueryCodeResponse)
|
||||
- [QueryCosmosAccountRequest](#ethermint.evm.v1.QueryCosmosAccountRequest)
|
||||
@ -77,6 +79,12 @@
|
||||
- [ethermint/types/v1/account.proto](#ethermint/types/v1/account.proto)
|
||||
- [EthAccount](#ethermint.types.v1.EthAccount)
|
||||
|
||||
- [ethermint/types/v1/dynamic_fee.proto](#ethermint/types/v1/dynamic_fee.proto)
|
||||
- [ExtensionOptionDynamicFeeTx](#ethermint.types.v1.ExtensionOptionDynamicFeeTx)
|
||||
|
||||
- [ethermint/types/v1/indexer.proto](#ethermint/types/v1/indexer.proto)
|
||||
- [TxResult](#ethermint.types.v1.TxResult)
|
||||
|
||||
- [ethermint/types/v1/web3.proto](#ethermint/types/v1/web3.proto)
|
||||
- [ExtensionOptionsWeb3Tx](#ethermint.types.v1.ExtensionOptionsWeb3Tx)
|
||||
|
||||
@ -127,8 +135,8 @@
|
||||
- [GenesisState](#vulcanize.bond.v1beta1.GenesisState)
|
||||
|
||||
- [vulcanize/bond/v1beta1/query.proto](#vulcanize/bond/v1beta1/query.proto)
|
||||
- [QueryGetBondByIdRequest](#vulcanize.bond.v1beta1.QueryGetBondByIdRequest)
|
||||
- [QueryGetBondByIdResponse](#vulcanize.bond.v1beta1.QueryGetBondByIdResponse)
|
||||
- [QueryGetBondByIDRequest](#vulcanize.bond.v1beta1.QueryGetBondByIDRequest)
|
||||
- [QueryGetBondByIDResponse](#vulcanize.bond.v1beta1.QueryGetBondByIDResponse)
|
||||
- [QueryGetBondModuleBalanceRequest](#vulcanize.bond.v1beta1.QueryGetBondModuleBalanceRequest)
|
||||
- [QueryGetBondModuleBalanceResponse](#vulcanize.bond.v1beta1.QueryGetBondModuleBalanceResponse)
|
||||
- [QueryGetBondsByOwnerRequest](#vulcanize.bond.v1beta1.QueryGetBondsByOwnerRequest)
|
||||
@ -192,10 +200,10 @@
|
||||
- [QueryLookupCrnResponse](#vulcanize.nameservice.v1beta1.QueryLookupCrnResponse)
|
||||
- [QueryParamsRequest](#vulcanize.nameservice.v1beta1.QueryParamsRequest)
|
||||
- [QueryParamsResponse](#vulcanize.nameservice.v1beta1.QueryParamsResponse)
|
||||
- [QueryRecordByBondIdRequest](#vulcanize.nameservice.v1beta1.QueryRecordByBondIdRequest)
|
||||
- [QueryRecordByBondIdResponse](#vulcanize.nameservice.v1beta1.QueryRecordByBondIdResponse)
|
||||
- [QueryRecordByIdRequest](#vulcanize.nameservice.v1beta1.QueryRecordByIdRequest)
|
||||
- [QueryRecordByIdResponse](#vulcanize.nameservice.v1beta1.QueryRecordByIdResponse)
|
||||
- [QueryRecordByBondIDRequest](#vulcanize.nameservice.v1beta1.QueryRecordByBondIDRequest)
|
||||
- [QueryRecordByBondIDResponse](#vulcanize.nameservice.v1beta1.QueryRecordByBondIDResponse)
|
||||
- [QueryRecordByIDRequest](#vulcanize.nameservice.v1beta1.QueryRecordByIDRequest)
|
||||
- [QueryRecordByIDResponse](#vulcanize.nameservice.v1beta1.QueryRecordByIDResponse)
|
||||
- [QueryResolveCrn](#vulcanize.nameservice.v1beta1.QueryResolveCrn)
|
||||
- [QueryResolveCrnResponse](#vulcanize.nameservice.v1beta1.QueryResolveCrnResponse)
|
||||
- [QueryWhoisRequest](#vulcanize.nameservice.v1beta1.QueryWhoisRequest)
|
||||
@ -328,7 +336,8 @@ instead of *big.Int.
|
||||
| `berlin_block` | [string](#string) | | Berlin switch block (nil = no fork, 0 = already on berlin) |
|
||||
| `london_block` | [string](#string) | | London switch block (nil = no fork, 0 = already on london) |
|
||||
| `arrow_glacier_block` | [string](#string) | | Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) |
|
||||
| `merge_fork_block` | [string](#string) | | EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in merge proceedings) |
|
||||
| `gray_glacier_block` | [string](#string) | | EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated) |
|
||||
| `merge_netsplit_block` | [string](#string) | | Virtual fork after The Merge to use as a network splitter |
|
||||
|
||||
|
||||
|
||||
@ -373,6 +382,7 @@ Params defines the EVM module parameters
|
||||
| `enable_call` | [bool](#bool) | | enable call toggles state transitions that use the vm.Call function |
|
||||
| `extra_eips` | [int64](#int64) | repeated | extra eips defines the additional EIPs for the vm.Config |
|
||||
| `chain_config` | [ChainConfig](#ethermint.evm.v1.ChainConfig) | | chain config defines the EVM chain configuration parameters |
|
||||
| `allow_unprotected_txs` | [bool](#bool) | | Allow unprotected transactions defines if replay-protected (i.e non EIP155 signed) transactions can be executed on the state machine. |
|
||||
|
||||
|
||||
|
||||
@ -589,6 +599,8 @@ DynamicFeeTx is the data of EIP-1559 dinamic fee transactions.
|
||||
|
||||
### LegacyTx
|
||||
LegacyTx is the transaction data of regular Ethereum transactions.
|
||||
NOTE: All non-protected transactions (i.e non EIP155 signed) will fail if the
|
||||
AllowUnprotectedTxs parameter is disabled.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
@ -619,7 +631,7 @@ MsgEthereumTx encapsulates an Ethereum transaction as an SDK message.
|
||||
| `data` | [google.protobuf.Any](#google.protobuf.Any) | | inner transaction data
|
||||
|
||||
caches |
|
||||
| `size` | [double](#double) | | encoded storage size of the transaction |
|
||||
| `size` | [double](#double) | | DEPRECATED: encoded storage size of the transaction |
|
||||
| `hash` | [string](#string) | | transaction hash in hex format |
|
||||
| `from` | [string](#string) | | ethereum signer address in hex format. This address value is checked against the address derived from the signature (V, R, S) using the secp256k1 elliptic curve |
|
||||
|
||||
@ -766,6 +778,32 @@ QueryBalanceResponse is the response type for the Query/Balance RPC method.
|
||||
|
||||
|
||||
|
||||
<a name="ethermint.evm.v1.QueryBaseFeeRequest"></a>
|
||||
|
||||
### QueryBaseFeeRequest
|
||||
QueryBaseFeeRequest defines the request type for querying the EIP1559 base
|
||||
fee.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="ethermint.evm.v1.QueryBaseFeeResponse"></a>
|
||||
|
||||
### QueryBaseFeeResponse
|
||||
BaseFeeResponse returns the EIP1559 base fee.
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `base_fee` | [string](#string) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="ethermint.evm.v1.QueryCodeRequest"></a>
|
||||
|
||||
### QueryCodeRequest
|
||||
@ -931,7 +969,6 @@ QueryTraceTxRequest defines TraceTx request
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `msg` | [MsgEthereumTx](#ethermint.evm.v1.MsgEthereumTx) | | msgEthereumTx for the requested transaction |
|
||||
| `tx_index` | [uint64](#uint64) | | transaction index |
|
||||
| `trace_config` | [TraceConfig](#ethermint.evm.v1.TraceConfig) | | TraceConfig holds extra parameters to trace functions. |
|
||||
| `predecessors` | [MsgEthereumTx](#ethermint.evm.v1.MsgEthereumTx) | repeated | the predecessor transactions included in the same block need to be replayed first to get correct context for tracing. |
|
||||
| `block_number` | [int64](#int64) | | block number of requested transaction |
|
||||
@ -1048,6 +1085,7 @@ Query defines the gRPC querier service.
|
||||
| `EstimateGas` | [EthCallRequest](#ethermint.evm.v1.EthCallRequest) | [EstimateGasResponse](#ethermint.evm.v1.EstimateGasResponse) | EstimateGas implements the `eth_estimateGas` rpc api | GET|/ethermint/evm/v1/estimate_gas|
|
||||
| `TraceTx` | [QueryTraceTxRequest](#ethermint.evm.v1.QueryTraceTxRequest) | [QueryTraceTxResponse](#ethermint.evm.v1.QueryTraceTxResponse) | TraceTx implements the `debug_traceTransaction` rpc api | GET|/ethermint/evm/v1/trace_tx|
|
||||
| `TraceBlock` | [QueryTraceBlockRequest](#ethermint.evm.v1.QueryTraceBlockRequest) | [QueryTraceBlockResponse](#ethermint.evm.v1.QueryTraceBlockResponse) | TraceBlock implements the `debug_traceBlockByNumber` and `debug_traceBlockByHash` rpc api | GET|/ethermint/evm/v1/trace_block|
|
||||
| `BaseFee` | [QueryBaseFeeRequest](#ethermint.evm.v1.QueryBaseFeeRequest) | [QueryBaseFeeResponse](#ethermint.evm.v1.QueryBaseFeeResponse) | BaseFee queries the base fee of the parent block of the current block, it's similar to feemarket module's method, but also checks london hardfork status. | GET|/ethermint/evm/v1/base_fee|
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
@ -1073,6 +1111,8 @@ Params defines the EVM module parameters
|
||||
| `elasticity_multiplier` | [uint32](#uint32) | | elasticity multiplier bounds the maximum gas limit an EIP-1559 block may have. |
|
||||
| `enable_height` | [int64](#int64) | | height at which the base fee calculation is enabled. |
|
||||
| `base_fee` | [string](#string) | | base fee for EIP-1559 blocks. |
|
||||
| `min_gas_price` | [string](#string) | | min_gas_price defines the minimum gas price value for cosmos and eth transactions |
|
||||
| `min_gas_multiplier` | [string](#string) | | min gas denominator bounds the minimum gasUsed to be charged to senders based on GasLimit |
|
||||
|
||||
|
||||
|
||||
@ -1104,7 +1144,7 @@ GenesisState defines the feemarket module's genesis state.
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `params` | [Params](#ethermint.feemarket.v1.Params) | | params defines all the paramaters of the module. |
|
||||
| `block_gas` | [uint64](#uint64) | | block gas is the amount of gas used on the last block before the upgrade. Zero by default. |
|
||||
| `block_gas` | [uint64](#uint64) | | block gas is the amount of gas wanted on the last block before the upgrade. Zero by default. |
|
||||
|
||||
|
||||
|
||||
@ -1217,9 +1257,9 @@ Query defines the gRPC querier service.
|
||||
|
||||
| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
|
||||
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
|
||||
| `Params` | [QueryParamsRequest](#ethermint.feemarket.v1.QueryParamsRequest) | [QueryParamsResponse](#ethermint.feemarket.v1.QueryParamsResponse) | Params queries the parameters of x/feemarket module. | GET|/feemarket/evm/v1/params|
|
||||
| `BaseFee` | [QueryBaseFeeRequest](#ethermint.feemarket.v1.QueryBaseFeeRequest) | [QueryBaseFeeResponse](#ethermint.feemarket.v1.QueryBaseFeeResponse) | BaseFee queries the base fee of the parent block of the current block. | GET|/feemarket/evm/v1/base_fee|
|
||||
| `BlockGas` | [QueryBlockGasRequest](#ethermint.feemarket.v1.QueryBlockGasRequest) | [QueryBlockGasResponse](#ethermint.feemarket.v1.QueryBlockGasResponse) | BlockGas queries the gas used at a given block height | GET|/feemarket/evm/v1/block_gas|
|
||||
| `Params` | [QueryParamsRequest](#ethermint.feemarket.v1.QueryParamsRequest) | [QueryParamsResponse](#ethermint.feemarket.v1.QueryParamsResponse) | Params queries the parameters of x/feemarket module. | GET|/ethermint/feemarket/v1/params|
|
||||
| `BaseFee` | [QueryBaseFeeRequest](#ethermint.feemarket.v1.QueryBaseFeeRequest) | [QueryBaseFeeResponse](#ethermint.feemarket.v1.QueryBaseFeeResponse) | BaseFee queries the base fee of the parent block of the current block. | GET|/ethermint/feemarket/v1/base_fee|
|
||||
| `BlockGas` | [QueryBlockGasRequest](#ethermint.feemarket.v1.QueryBlockGasRequest) | [QueryBlockGasResponse](#ethermint.feemarket.v1.QueryBlockGasResponse) | BlockGas queries the gas used at a given block height | GET|/ethermint/feemarket/v1/block_gas|
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
@ -1248,6 +1288,74 @@ authtypes.BaseAccount type. It is compatible with the auth AccountKeeper.
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
<!-- end HasExtensions -->
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
|
||||
|
||||
<a name="ethermint/types/v1/dynamic_fee.proto"></a>
|
||||
<p align="right"><a href="#top">Top</a></p>
|
||||
|
||||
## ethermint/types/v1/dynamic_fee.proto
|
||||
|
||||
|
||||
|
||||
<a name="ethermint.types.v1.ExtensionOptionDynamicFeeTx"></a>
|
||||
|
||||
### ExtensionOptionDynamicFeeTx
|
||||
ExtensionOptionDynamicFeeTx is an extension option that specify the maxPrioPrice for cosmos tx
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `max_priority_price` | [string](#string) | | the same as `max_priority_fee_per_gas` in eip-1559 spec |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
|
||||
<!-- end HasExtensions -->
|
||||
|
||||
<!-- end services -->
|
||||
|
||||
|
||||
|
||||
<a name="ethermint/types/v1/indexer.proto"></a>
|
||||
<p align="right"><a href="#top">Top</a></p>
|
||||
|
||||
## ethermint/types/v1/indexer.proto
|
||||
|
||||
|
||||
|
||||
<a name="ethermint.types.v1.TxResult"></a>
|
||||
|
||||
### TxResult
|
||||
TxResult is the value stored in eth tx indexer
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| `height` | [int64](#int64) | | the block height |
|
||||
| `tx_index` | [uint32](#uint32) | | cosmos tx index |
|
||||
| `msg_index` | [uint32](#uint32) | | the msg index in a batch tx |
|
||||
| `eth_tx_index` | [int32](#int32) | | eth tx index, the index in the list of valid eth tx in the block, aka. the transaction list returned by eth_getBlock api. |
|
||||
| `failed` | [bool](#bool) | | if the eth tx is failed |
|
||||
| `gas_used` | [uint64](#uint64) | | gas used by tx, if exceeds block gas limit, it's set to gas limit which is what's actually deducted by ante handler. |
|
||||
| `cumulative_gas_used` | [uint64](#uint64) | | the cumulative gas used within current batch tx |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- end messages -->
|
||||
|
||||
<!-- end enums -->
|
||||
@ -1901,10 +2009,10 @@ GenesisState defines the bond module's genesis state.
|
||||
|
||||
|
||||
|
||||
<a name="vulcanize.bond.v1beta1.QueryGetBondByIdRequest"></a>
|
||||
<a name="vulcanize.bond.v1beta1.QueryGetBondByIDRequest"></a>
|
||||
|
||||
### QueryGetBondByIdRequest
|
||||
QueryGetBondById
|
||||
### QueryGetBondByIDRequest
|
||||
QueryGetBondByID
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
@ -1916,10 +2024,10 @@ QueryGetBondById
|
||||
|
||||
|
||||
|
||||
<a name="vulcanize.bond.v1beta1.QueryGetBondByIdResponse"></a>
|
||||
<a name="vulcanize.bond.v1beta1.QueryGetBondByIDResponse"></a>
|
||||
|
||||
### QueryGetBondByIdResponse
|
||||
QueryGetBondByIdResponse returns QueryGetBondById query response
|
||||
### QueryGetBondByIDResponse
|
||||
QueryGetBondByIDResponse returns QueryGetBondByID query response
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
@ -2059,7 +2167,7 @@ Query defines the gRPC querier service for bond module
|
||||
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
|
||||
| `Params` | [QueryParamsRequest](#vulcanize.bond.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#vulcanize.bond.v1beta1.QueryParamsResponse) | Params queries bonds module params. | GET|/vulcanize/bond/v1beta1/params|
|
||||
| `Bonds` | [QueryGetBondsRequest](#vulcanize.bond.v1beta1.QueryGetBondsRequest) | [QueryGetBondsResponse](#vulcanize.bond.v1beta1.QueryGetBondsResponse) | Bonds queries bonds list. | GET|/vulcanize/bond/v1beta1/bonds|
|
||||
| `GetBondById` | [QueryGetBondByIdRequest](#vulcanize.bond.v1beta1.QueryGetBondByIdRequest) | [QueryGetBondByIdResponse](#vulcanize.bond.v1beta1.QueryGetBondByIdResponse) | GetBondById | GET|/vulcanize/bond/v1beta1/bonds/{id}|
|
||||
| `GetBondByID` | [QueryGetBondByIDRequest](#vulcanize.bond.v1beta1.QueryGetBondByIDRequest) | [QueryGetBondByIDResponse](#vulcanize.bond.v1beta1.QueryGetBondByIDResponse) | GetBondById | GET|/vulcanize/bond/v1beta1/bonds/{id}|
|
||||
| `GetBondsByOwner` | [QueryGetBondsByOwnerRequest](#vulcanize.bond.v1beta1.QueryGetBondsByOwnerRequest) | [QueryGetBondsByOwnerResponse](#vulcanize.bond.v1beta1.QueryGetBondsByOwnerResponse) | Get Bonds List by Owner | GET|/vulcanize/bond/v1beta1/by-owner/{owner}|
|
||||
| `GetBondsModuleBalance` | [QueryGetBondModuleBalanceRequest](#vulcanize.bond.v1beta1.QueryGetBondModuleBalanceRequest) | [QueryGetBondModuleBalanceResponse](#vulcanize.bond.v1beta1.QueryGetBondModuleBalanceResponse) | Get Bonds module balance | GET|/vulcanize/bond/v1beta1/balance|
|
||||
|
||||
@ -2812,9 +2920,9 @@ QueryParamsResponse is response type for nameservice params
|
||||
|
||||
|
||||
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByBondIdRequest"></a>
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByBondIDRequest"></a>
|
||||
|
||||
### QueryRecordByBondIdRequest
|
||||
### QueryRecordByBondIDRequest
|
||||
QueryRecordByBondIdRequest is request type for get the records by bond-id
|
||||
|
||||
|
||||
@ -2828,9 +2936,9 @@ QueryRecordByBondIdRequest is request type for get the records by bond-id
|
||||
|
||||
|
||||
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByBondIdResponse"></a>
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByBondIDResponse"></a>
|
||||
|
||||
### QueryRecordByBondIdResponse
|
||||
### QueryRecordByBondIDResponse
|
||||
QueryRecordByBondIdResponse is response type for records list by bond-id
|
||||
|
||||
|
||||
@ -2844,10 +2952,10 @@ QueryRecordByBondIdResponse is response type for records list by bond-id
|
||||
|
||||
|
||||
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByIdRequest"></a>
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByIDRequest"></a>
|
||||
|
||||
### QueryRecordByIdRequest
|
||||
QueryRecordByIdRequest is request type for nameservice records by id
|
||||
### QueryRecordByIDRequest
|
||||
QueryRecordByIDRequest is request type for nameservice records by id
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
@ -2859,10 +2967,10 @@ QueryRecordByIdRequest is request type for nameservice records by id
|
||||
|
||||
|
||||
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByIdResponse"></a>
|
||||
<a name="vulcanize.nameservice.v1beta1.QueryRecordByIDResponse"></a>
|
||||
|
||||
### QueryRecordByIdResponse
|
||||
QueryRecordByIdResponse is response type for nameservice records by id
|
||||
### QueryRecordByIDResponse
|
||||
QueryRecordByIDResponse is response type for nameservice records by id
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
@ -2949,8 +3057,8 @@ Query defines the gRPC querier service for nameservice module
|
||||
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
|
||||
| `Params` | [QueryParamsRequest](#vulcanize.nameservice.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#vulcanize.nameservice.v1beta1.QueryParamsResponse) | Params queries the nameservice module params. | GET|/vulcanize/nameservice/v1beta1/params|
|
||||
| `ListRecords` | [QueryListRecordsRequest](#vulcanize.nameservice.v1beta1.QueryListRecordsRequest) | [QueryListRecordsResponse](#vulcanize.nameservice.v1beta1.QueryListRecordsResponse) | List records | GET|/vulcanize/nameservice/v1beta1/records|
|
||||
| `GetRecord` | [QueryRecordByIdRequest](#vulcanize.nameservice.v1beta1.QueryRecordByIdRequest) | [QueryRecordByIdResponse](#vulcanize.nameservice.v1beta1.QueryRecordByIdResponse) | Get record by id | GET|/vulcanize/nameservice/v1beta1/records/{id}|
|
||||
| `GetRecordByBondId` | [QueryRecordByBondIdRequest](#vulcanize.nameservice.v1beta1.QueryRecordByBondIdRequest) | [QueryRecordByBondIdResponse](#vulcanize.nameservice.v1beta1.QueryRecordByBondIdResponse) | Get records by bond id | GET|/vulcanize/nameservice/v1beta1/records-by-bond-id/{id}|
|
||||
| `GetRecord` | [QueryRecordByIDRequest](#vulcanize.nameservice.v1beta1.QueryRecordByIDRequest) | [QueryRecordByIDResponse](#vulcanize.nameservice.v1beta1.QueryRecordByIDResponse) | Get record by id | GET|/vulcanize/nameservice/v1beta1/records/{id}|
|
||||
| `GetRecordByBondID` | [QueryRecordByBondIDRequest](#vulcanize.nameservice.v1beta1.QueryRecordByBondIDRequest) | [QueryRecordByBondIDResponse](#vulcanize.nameservice.v1beta1.QueryRecordByBondIDResponse) | Get records by bond id | GET|/vulcanize/nameservice/v1beta1/records-by-bond-id/{id}|
|
||||
| `GetNameServiceModuleBalance` | [GetNameServiceModuleBalanceRequest](#vulcanize.nameservice.v1beta1.GetNameServiceModuleBalanceRequest) | [GetNameServiceModuleBalanceResponse](#vulcanize.nameservice.v1beta1.GetNameServiceModuleBalanceResponse) | Get nameservice module balance | GET|/vulcanize/nameservice/v1beta1/balance|
|
||||
| `ListNameRecords` | [QueryListNameRecordsRequest](#vulcanize.nameservice.v1beta1.QueryListNameRecordsRequest) | [QueryListNameRecordsResponse](#vulcanize.nameservice.v1beta1.QueryListNameRecordsResponse) | List name records | GET|/vulcanize/nameservice/v1beta1/names|
|
||||
| `Whois` | [QueryWhoisRequest](#vulcanize.nameservice.v1beta1.QueryWhoisRequest) | [QueryWhoisResponse](#vulcanize.nameservice.v1beta1.QueryWhoisResponse) | Whois method retrieve the name authority info | GET|/vulcanize/nameservice/v1beta1/whois/{name}|
|
||||
|
@ -14,11 +14,11 @@ ADR creation is an **iterative** process. Instead of trying to solve all decisio
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
@ -53,4 +53,4 @@ DRAFT -> PROPOSED -> LAST CALL yyyy-mm-dd -> ACCEPTED | REJECTED -> SUPERSEDED b
|
||||
## Language used in ADR
|
||||
|
||||
+ The context/background should be written in the present tense.
|
||||
+ Avoid using a first, personal form.
|
||||
+ Avoid using a first, personal form.
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
@ -11,7 +12,9 @@ import (
|
||||
|
||||
// RegisterLegacyAminoCodec registers Interfaces from types, crypto, and SDK std.
|
||||
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||
std.RegisterLegacyAminoCodec(cdc)
|
||||
sdk.RegisterLegacyAminoCodec(cdc)
|
||||
cryptocodec.RegisterCrypto(cdc)
|
||||
codec.RegisterEvidences(cdc)
|
||||
}
|
||||
|
||||
// RegisterInterfaces registers Interfaces from types, crypto, and SDK std.
|
||||
|
@ -1,7 +1,7 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
amino "github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
@ -12,16 +12,15 @@ import (
|
||||
|
||||
// MakeConfig creates an EncodingConfig for testing
|
||||
func MakeConfig(mb module.BasicManager) params.EncodingConfig {
|
||||
amino := codec.NewLegacyAmino()
|
||||
cdc := amino.NewLegacyAmino()
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
marshaler := codec.NewProtoCodec(interfaceRegistry)
|
||||
txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes)
|
||||
codec := amino.NewProtoCodec(interfaceRegistry)
|
||||
|
||||
encodingConfig := params.EncodingConfig{
|
||||
InterfaceRegistry: interfaceRegistry,
|
||||
Codec: marshaler,
|
||||
TxConfig: txCfg,
|
||||
Amino: amino,
|
||||
Codec: codec,
|
||||
TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes),
|
||||
Amino: cdc,
|
||||
}
|
||||
|
||||
enccodec.RegisterLegacyAminoCodec(encodingConfig.Amino)
|
||||
|
@ -5,8 +5,14 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"reflect" // #nosec G702
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -228,6 +234,11 @@ func traverseFields(
|
||||
// then continue as normal
|
||||
}
|
||||
|
||||
// If its a nil pointer, do not include in types
|
||||
if fieldType.Kind() == reflect.Ptr && field.IsNil() {
|
||||
continue
|
||||
}
|
||||
|
||||
for {
|
||||
if fieldType.Kind() == reflect.Ptr {
|
||||
fieldType = fieldType.Elem()
|
||||
@ -292,6 +303,11 @@ func traverseFields(
|
||||
|
||||
ethTyp := typToEth(fieldType)
|
||||
if len(ethTyp) > 0 {
|
||||
// Support array of uint64
|
||||
if isCollection && fieldType.Kind() != reflect.Slice && fieldType.Kind() != reflect.Array {
|
||||
ethTyp += "[]"
|
||||
}
|
||||
|
||||
if prefix == typeDefPrefix {
|
||||
typeMap[rootType] = append(typeMap[rootType], apitypes.Type{
|
||||
Name: fieldName,
|
||||
@ -309,7 +325,6 @@ func traverseFields(
|
||||
}
|
||||
|
||||
if fieldType.Kind() == reflect.Struct {
|
||||
|
||||
var fieldTypedef string
|
||||
|
||||
if isCollection {
|
||||
@ -355,6 +370,7 @@ func jsonNameFromTag(tag reflect.StructTag) string {
|
||||
func sanitizeTypedef(str string) string {
|
||||
buf := new(bytes.Buffer)
|
||||
parts := strings.Split(str, ".")
|
||||
caser := cases.Title(language.English, cases.NoLower)
|
||||
|
||||
for _, part := range parts {
|
||||
if part == "_" {
|
||||
@ -364,7 +380,7 @@ func sanitizeTypedef(str string) string {
|
||||
|
||||
subparts := strings.Split(part, "_")
|
||||
for _, subpart := range subparts {
|
||||
buf.WriteString(strings.Title(subpart))
|
||||
buf.WriteString(caser.String(subpart))
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,8 +391,12 @@ var (
|
||||
hashType = reflect.TypeOf(common.Hash{})
|
||||
addressType = reflect.TypeOf(common.Address{})
|
||||
bigIntType = reflect.TypeOf(big.Int{})
|
||||
cosmIntType = reflect.TypeOf(sdk.Int{})
|
||||
cosmIntType = reflect.TypeOf(sdkmath.Int{})
|
||||
cosmDecType = reflect.TypeOf(sdk.Dec{})
|
||||
cosmosAnyType = reflect.TypeOf(&codectypes.Any{})
|
||||
timeType = reflect.TypeOf(time.Time{})
|
||||
|
||||
edType = reflect.TypeOf(ed25519.PubKey{})
|
||||
)
|
||||
|
||||
// typToEth supports only basic types and arrays of basic types.
|
||||
@ -421,6 +441,9 @@ func typToEth(typ reflect.Type) string {
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if typ.Elem().ConvertibleTo(bigIntType) ||
|
||||
typ.Elem().ConvertibleTo(timeType) ||
|
||||
typ.Elem().ConvertibleTo(edType) ||
|
||||
typ.Elem().ConvertibleTo(cosmDecType) ||
|
||||
typ.Elem().ConvertibleTo(cosmIntType) {
|
||||
return str
|
||||
}
|
||||
@ -428,6 +451,9 @@ func typToEth(typ reflect.Type) string {
|
||||
if typ.ConvertibleTo(hashType) ||
|
||||
typ.ConvertibleTo(addressType) ||
|
||||
typ.ConvertibleTo(bigIntType) ||
|
||||
typ.ConvertibleTo(edType) ||
|
||||
typ.ConvertibleTo(timeType) ||
|
||||
typ.ConvertibleTo(cosmDecType) ||
|
||||
typ.ConvertibleTo(cosmIntType) {
|
||||
return str
|
||||
}
|
||||
|
83
ethereum/eip712/preprocess.go
Normal file
83
ethereum/eip712/preprocess.go
Normal file
@ -0,0 +1,83 @@
|
||||
package eip712
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cerc-io/laconicd/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cosmoskr "github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
)
|
||||
|
||||
// PreprocessLedgerTx reformats Ledger-signed Cosmos transactions to match the fork expected by Ethermint
|
||||
// by including the signature in a Web3Tx extension and sending a blank signature in the body.
|
||||
func PreprocessLedgerTx(chainID string, keyType cosmoskr.KeyType, txBuilder client.TxBuilder) error {
|
||||
// Only process Ledger transactions
|
||||
if keyType != cosmoskr.TypeLedger {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Init extension builder to set Web3 extension
|
||||
extensionBuilder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot cast TxBuilder to ExtensionOptionsTxBuilder")
|
||||
}
|
||||
|
||||
// Get signatures from TxBuilder
|
||||
sigs, err := txBuilder.GetTx().GetSignaturesV2()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get signatures: %w", err)
|
||||
}
|
||||
|
||||
// Verify single-signer
|
||||
if len(sigs) != 1 {
|
||||
return fmt.Errorf("invalid number of signatures, expected 1 and got %v", len(sigs))
|
||||
}
|
||||
|
||||
signature := sigs[0]
|
||||
sigData, ok := signature.Data.(*signing.SingleSignatureData)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected signature type, expected SingleSignatureData")
|
||||
}
|
||||
sigBytes := sigData.Signature
|
||||
|
||||
// Parse Chain ID as big.Int
|
||||
chainIDInt, err := types.ParseChainID(chainID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse chain id: %w", err)
|
||||
}
|
||||
|
||||
// Add ExtensionOptionsWeb3Tx extension with signature
|
||||
var option *codectypes.Any
|
||||
option, err = codectypes.NewAnyWithValue(&types.ExtensionOptionsWeb3Tx{
|
||||
FeePayer: txBuilder.GetTx().FeePayer().String(),
|
||||
TypedDataChainID: chainIDInt.Uint64(),
|
||||
FeePayerSig: sigBytes,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not set extension as any: %w", err)
|
||||
}
|
||||
|
||||
extensionBuilder.SetExtensionOptions(option)
|
||||
|
||||
// Set blank signature with Amino Sign Type
|
||||
// (Regardless of input signMode, Evmos requires Amino signature type for Ledger)
|
||||
blankSig := signing.SingleSignatureData{
|
||||
SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
|
||||
Signature: nil,
|
||||
}
|
||||
sig := signing.SignatureV2{
|
||||
PubKey: signature.PubKey,
|
||||
Data: &blankSig,
|
||||
Sequence: signature.Sequence,
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures(sig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to set signatures on payload: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
222
ethereum/eip712/preprocess_test.go
Normal file
222
ethereum/eip712/preprocess_test.go
Normal file
@ -0,0 +1,222 @@
|
||||
package eip712_test
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/cerc-io/laconicd/app"
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
"github.com/cerc-io/laconicd/ethereum/eip712"
|
||||
"github.com/cerc-io/laconicd/tests"
|
||||
"github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Testing Constants
|
||||
var (
|
||||
chainId = "ethermint_9000-1"
|
||||
ctx = client.Context{}.WithTxConfig(
|
||||
encoding.MakeConfig(app.ModuleBasics).TxConfig,
|
||||
)
|
||||
)
|
||||
var feePayerAddress = "ethm17xpfvakm2amg962yls6f84z3kell8c5lthdzgl"
|
||||
|
||||
type TestCaseStruct struct {
|
||||
txBuilder client.TxBuilder
|
||||
expectedFeePayer string
|
||||
expectedGas uint64
|
||||
expectedFee math.Int
|
||||
expectedMemo string
|
||||
expectedMsg string
|
||||
expectedSignatureBytes []byte
|
||||
}
|
||||
|
||||
func TestLedgerPreprocessing(t *testing.T) {
|
||||
// Update bech32 prefix
|
||||
sdk.GetConfig().SetBech32PrefixForAccount("ethm", "")
|
||||
|
||||
testCases := []TestCaseStruct{
|
||||
createBasicTestCase(t),
|
||||
createPopulatedTestCase(t),
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
// Run pre-processing
|
||||
err := eip712.PreprocessLedgerTx(
|
||||
chainId,
|
||||
keyring.TypeLedger,
|
||||
tc.txBuilder,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify Web3 extension matches expected
|
||||
hasExtOptsTx, ok := tc.txBuilder.(ante.HasExtensionOptionsTx)
|
||||
require.True(t, ok)
|
||||
require.True(t, len(hasExtOptsTx.GetExtensionOptions()) == 1)
|
||||
|
||||
expectedExt := types.ExtensionOptionsWeb3Tx{
|
||||
TypedDataChainID: 9000,
|
||||
FeePayer: feePayerAddress,
|
||||
FeePayerSig: tc.expectedSignatureBytes,
|
||||
}
|
||||
|
||||
expectedExtAny, err := codectypes.NewAnyWithValue(&expectedExt)
|
||||
require.NoError(t, err)
|
||||
|
||||
actualExtAny := hasExtOptsTx.GetExtensionOptions()[0]
|
||||
require.Equal(t, expectedExtAny, actualExtAny)
|
||||
|
||||
// Verify signature type matches expected
|
||||
signatures, err := tc.txBuilder.GetTx().GetSignaturesV2()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(signatures), 1)
|
||||
|
||||
txSig := signatures[0].Data.(*signing.SingleSignatureData)
|
||||
require.Equal(t, txSig.SignMode, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
|
||||
// Verify signature is blank
|
||||
require.Equal(t, len(txSig.Signature), 0)
|
||||
|
||||
// Verify tx fields are unchanged
|
||||
tx := tc.txBuilder.GetTx()
|
||||
|
||||
require.Equal(t, tx.FeePayer().String(), tc.expectedFeePayer)
|
||||
require.Equal(t, tx.GetGas(), tc.expectedGas)
|
||||
require.Equal(t, tx.GetFee().AmountOf(evmtypes.DefaultParams().EvmDenom), tc.expectedFee)
|
||||
require.Equal(t, tx.GetMemo(), tc.expectedMemo)
|
||||
|
||||
// Verify message is unchanged
|
||||
if tc.expectedMsg != "" {
|
||||
require.Equal(t, len(tx.GetMsgs()), 1)
|
||||
require.Equal(t, tx.GetMsgs()[0].String(), tc.expectedMsg)
|
||||
} else {
|
||||
require.Equal(t, len(tx.GetMsgs()), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlankTxBuilder(t *testing.T) {
|
||||
txBuilder := ctx.TxConfig.NewTxBuilder()
|
||||
|
||||
err := eip712.PreprocessLedgerTx(
|
||||
chainId,
|
||||
keyring.TypeLedger,
|
||||
txBuilder,
|
||||
)
|
||||
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestNonLedgerTxBuilder(t *testing.T) {
|
||||
txBuilder := ctx.TxConfig.NewTxBuilder()
|
||||
|
||||
err := eip712.PreprocessLedgerTx(
|
||||
chainId,
|
||||
keyring.TypeLocal,
|
||||
txBuilder,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestInvalidChainId(t *testing.T) {
|
||||
txBuilder := ctx.TxConfig.NewTxBuilder()
|
||||
|
||||
err := eip712.PreprocessLedgerTx(
|
||||
"invalid-chain-id",
|
||||
keyring.TypeLedger,
|
||||
txBuilder,
|
||||
)
|
||||
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func createBasicTestCase(t *testing.T) TestCaseStruct {
|
||||
t.Helper()
|
||||
txBuilder := ctx.TxConfig.NewTxBuilder()
|
||||
|
||||
feePayer, err := sdk.AccAddressFromBech32(feePayerAddress)
|
||||
require.NoError(t, err)
|
||||
|
||||
txBuilder.SetFeePayer(feePayer)
|
||||
|
||||
// Create signature unrelated to payload for testing
|
||||
signatureHex := strings.Repeat("01", 65)
|
||||
signatureBytes, err := hex.DecodeString(signatureHex)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, privKey := tests.NewAddrKey()
|
||||
sigsV2 := signing.SignatureV2{
|
||||
PubKey: privKey.PubKey(), // Use unrelated public key for testing
|
||||
Data: &signing.SingleSignatureData{
|
||||
SignMode: signing.SignMode_SIGN_MODE_DIRECT,
|
||||
Signature: signatureBytes,
|
||||
},
|
||||
Sequence: 0,
|
||||
}
|
||||
|
||||
txBuilder.SetSignatures(sigsV2)
|
||||
return TestCaseStruct{
|
||||
txBuilder: txBuilder,
|
||||
expectedFeePayer: feePayer.String(),
|
||||
expectedGas: 0,
|
||||
expectedFee: math.NewInt(0),
|
||||
expectedMemo: "",
|
||||
expectedMsg: "",
|
||||
expectedSignatureBytes: signatureBytes,
|
||||
}
|
||||
}
|
||||
|
||||
func createPopulatedTestCase(t *testing.T) TestCaseStruct {
|
||||
t.Helper()
|
||||
basicTestCase := createBasicTestCase(t)
|
||||
txBuilder := basicTestCase.txBuilder
|
||||
|
||||
gasLimit := uint64(200000)
|
||||
memo := ""
|
||||
denom := evmtypes.DefaultParams().EvmDenom
|
||||
feeAmount := math.NewInt(2000)
|
||||
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
denom,
|
||||
feeAmount,
|
||||
)))
|
||||
|
||||
txBuilder.SetGasLimit(gasLimit)
|
||||
txBuilder.SetMemo(memo)
|
||||
|
||||
msgSend := banktypes.MsgSend{
|
||||
FromAddress: feePayerAddress,
|
||||
ToAddress: "ethm12luku6uxehhak02py4rcz65zu0swh7wjun6msa",
|
||||
Amount: sdk.NewCoins(
|
||||
sdk.NewCoin(
|
||||
evmtypes.DefaultParams().EvmDenom,
|
||||
math.NewInt(10000000),
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
txBuilder.SetMsgs(&msgSend)
|
||||
|
||||
return TestCaseStruct{
|
||||
txBuilder: txBuilder,
|
||||
expectedFeePayer: basicTestCase.expectedFeePayer,
|
||||
expectedGas: gasLimit,
|
||||
expectedFee: feeAmount,
|
||||
expectedMemo: memo,
|
||||
expectedMsg: msgSend.String(),
|
||||
expectedSignatureBytes: basicTestCase.expectedSignatureBytes,
|
||||
}
|
||||
}
|
129
go.mod
129
go.mod
@ -1,111 +1,115 @@
|
||||
module github.com/cerc-io/laconicd
|
||||
|
||||
go 1.17
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
cosmossdk.io/math v1.0.0-beta.2
|
||||
github.com/99designs/gqlgen v0.17.2
|
||||
cosmossdk.io/math v1.0.0-beta.3
|
||||
github.com/99designs/gqlgen v0.17.20
|
||||
github.com/armon/go-metrics v0.4.1
|
||||
github.com/btcsuite/btcd v0.22.1
|
||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||
github.com/cosmos/cosmos-sdk v0.46.0-rc1
|
||||
github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1
|
||||
github.com/cosmos/cosmos-sdk v0.46.2-0.20220920160224-9454b97ccb77
|
||||
github.com/cosmos/go-bip39 v1.0.0
|
||||
github.com/cosmos/ibc-go/v3 v3.0.0-alpha1.0.20220530074104-c7c115244bad
|
||||
github.com/cosmos/ibc-go/v5 v5.0.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/deckarep/golang-set v1.8.0
|
||||
github.com/ethereum/go-ethereum v1.10.17
|
||||
github.com/ethereum/go-ethereum v1.10.19
|
||||
github.com/gibson042/canonicaljson-go v1.0.3
|
||||
github.com/gogo/protobuf v1.3.3
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/holiman/uint256 v1.2.0
|
||||
github.com/holiman/uint256 v1.2.1
|
||||
github.com/improbable-eng/grpc-web v0.15.0
|
||||
github.com/ipfs/go-cid v0.0.4
|
||||
github.com/ipfs/go-cid v0.3.2
|
||||
github.com/ipfs/go-ipld-cbor v0.0.6
|
||||
github.com/ipld/go-ipld-prime v0.16.0
|
||||
github.com/ipld/go-ipld-prime v0.18.0
|
||||
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
|
||||
github.com/multiformats/go-multihash v0.1.0
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/multiformats/go-multihash v0.2.1
|
||||
github.com/onsi/ginkgo/v2 v2.2.0
|
||||
github.com/onsi/gomega v1.20.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rakyll/statik v0.1.7
|
||||
github.com/regen-network/cosmos-proto v0.3.1
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/rs/zerolog v1.26.1
|
||||
github.com/spf13/cast v1.5.0
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/spf13/viper v1.12.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/tendermint/tendermint v0.35.6
|
||||
github.com/tendermint/tendermint v0.34.21
|
||||
github.com/tendermint/tm-db v0.6.7
|
||||
github.com/tyler-smith/go-bip39 v1.1.0
|
||||
github.com/vektah/gqlparser/v2 v2.4.1
|
||||
google.golang.org/genproto v0.0.0-20220930163606-c98284e70a91
|
||||
google.golang.org/grpc v1.49.0
|
||||
github.com/vektah/gqlparser/v2 v2.5.1
|
||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
||||
golang.org/x/text v0.3.7
|
||||
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a
|
||||
google.golang.org/grpc v1.50.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.104.0 // indirect
|
||||
cloud.google.com/go v0.102.1 // indirect
|
||||
cloud.google.com/go/compute v1.7.0 // indirect
|
||||
cloud.google.com/go/iam v0.3.0 // indirect
|
||||
cloud.google.com/go/storage v1.23.0 // indirect
|
||||
cosmossdk.io/api v0.1.0-alpha8 // indirect
|
||||
cosmossdk.io/errors v1.0.0-beta.6 // indirect
|
||||
cloud.google.com/go/iam v0.4.0 // indirect
|
||||
cloud.google.com/go/storage v1.22.1 // indirect
|
||||
cosmossdk.io/errors v1.0.0-beta.7 // indirect
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||
github.com/99designs/keyring v1.1.6 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
|
||||
github.com/Workiva/go-datastructures v1.0.53 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.0 // indirect
|
||||
github.com/armon/go-metrics v0.3.11 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.40.45 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
|
||||
github.com/confio/ics23/go v0.7.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.4 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7 // indirect
|
||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.18.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.2-0.20220916140702-9b6be3095313 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
||||
github.com/cosmos/ledger-go v0.9.2 // indirect
|
||||
github.com/creachadair/taskgroup v0.3.2 // indirect
|
||||
github.com/danieljoos/wincred v1.0.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/badger/v3 v3.2103.2 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
|
||||
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/gateway v1.1.0 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/flatbuffers v2.0.0+incompatible // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
@ -114,18 +118,19 @@ require (
|
||||
github.com/googleapis/go-type-adapters v1.0.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.6.1 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.4.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||
github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204 // indirect
|
||||
github.com/huin/goupnp v1.0.3 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/ipfs/go-block-format v0.0.2 // indirect
|
||||
github.com/ipfs/go-ipfs-util v0.0.1 // indirect
|
||||
@ -134,16 +139,17 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/klauspost/compress v1.15.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/lazyledger/smt v0.2.1-0.20210709230900-03ea40719554 // indirect
|
||||
github.com/lib/pq v1.10.6 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
@ -152,13 +158,12 @@ require (
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||
github.com/multiformats/go-multibase v0.0.1 // indirect
|
||||
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.0.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
|
||||
@ -169,18 +174,19 @@ require (
|
||||
github.com/prometheus/tsdb v0.7.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
||||
github.com/rjeczalik/notify v0.9.1 // indirect
|
||||
github.com/rs/zerolog v1.27.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.3.0 // indirect
|
||||
github.com/stretchr/objx v0.4.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||
github.com/tendermint/btcd v0.1.1 // indirect
|
||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tendermint/tm-db v0.6.7 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.8 // indirect
|
||||
@ -189,31 +195,26 @@ require (
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b // indirect
|
||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220908150016-7ac13a9a928d // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.97.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
lukechampine.com/blake3 v1.1.6 // indirect
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
|
||||
|
||||
// replace cosmos
|
||||
github.com/cosmos/cosmos-sdk => github.com/cerc-io/cosmos-sdk v0.46.0-smt-0.0.5-alpha
|
||||
github.com/cosmos/cosmos-sdk/db => github.com/cerc-io/cosmos-sdk/db v1.0.0-beta.1
|
||||
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
|
||||
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
|
||||
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
|
||||
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
|
||||
google.golang.org/grpc => google.golang.org/grpc v1.44.0
|
||||
)
|
||||
|
545
gomod2nix.toml
Normal file
545
gomod2nix.toml
Normal file
@ -0,0 +1,545 @@
|
||||
schema = 3
|
||||
|
||||
[mod]
|
||||
[mod."cloud.google.com/go"]
|
||||
version = "v0.102.1"
|
||||
hash = "sha256-rv3MHFvIrN6AcrmWcWGSQwgaZLbjJMmJFi3bsfHoiO4="
|
||||
[mod."cloud.google.com/go/compute"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-g+n7L36LC+NP4KaiEu9fCMn6S9fkxjp4PCLOp/oXV38="
|
||||
[mod."cloud.google.com/go/iam"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-sPtj6QPPC/QrkDXJW4Y7rMIHk5l1y9XV/DgM47eEtvg="
|
||||
[mod."cloud.google.com/go/storage"]
|
||||
version = "v1.22.1"
|
||||
hash = "sha256-YZt05wru0kacyi6moTgvocavActKpXx7FlLh+o0HGDs="
|
||||
[mod."cosmossdk.io/errors"]
|
||||
version = "v1.0.0-beta.7"
|
||||
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
|
||||
[mod."cosmossdk.io/math"]
|
||||
version = "v1.0.0-beta.3"
|
||||
hash = "sha256-lTQ27ZlL+kWlc+S//sJmyiOwaf9qS+YLv61I4OXi9XE="
|
||||
[mod."filippo.io/edwards25519"]
|
||||
version = "v1.0.0-rc.1"
|
||||
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
|
||||
[mod."github.com/99designs/keyring"]
|
||||
version = "v1.1.7-0.20210622111912-ef00f8ac3d76"
|
||||
hash = "sha256-oCalyOZWegRgKHZ1GvYHNkrMKh51j8cOE/K4yBPM5Oc="
|
||||
replaced = "github.com/cosmos/keyring"
|
||||
[mod."github.com/ChainSafe/go-schnorrkel"]
|
||||
version = "v0.0.0-20200405005733-88cbf1b4c40d"
|
||||
hash = "sha256-i8RXZemJGlSjBT35oPm0SawFiBoIU5Pkq5xp4n/rzCY="
|
||||
[mod."github.com/StackExchange/wmi"]
|
||||
version = "v0.0.0-20180116203802-5d049714c4a6"
|
||||
hash = "sha256-0yUxhZB3v3ZE3QY36zHs2cJ1S4GXptXIhyAi6sI2nOo="
|
||||
[mod."github.com/VictoriaMetrics/fastcache"]
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-u1dkRJ2Y5+hnYlkyMPm14HxKkAv999bjN622nZDjaBo="
|
||||
[mod."github.com/Workiva/go-datastructures"]
|
||||
version = "v1.0.53"
|
||||
hash = "sha256-W6qOvqu8sokMlZrpOF1SWG138H0/BotywKNLlDF8Zug="
|
||||
[mod."github.com/armon/go-metrics"]
|
||||
version = "v0.4.1"
|
||||
hash = "sha256-usxTUHA0QQMdM6sHi2z51nmnEKMbA0qUilxJFpWHlYE="
|
||||
[mod."github.com/aws/aws-sdk-go"]
|
||||
version = "v1.40.45"
|
||||
hash = "sha256-7m4jOfXs356SUZG9tR+z3Yfa/O0CorkSkOXg/AmbqRM="
|
||||
[mod."github.com/beorn7/perks"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-h75GUqfwJKngCJQVE5Ao5wnO3cfKD9lSIteoLp/3xJ4="
|
||||
[mod."github.com/bgentry/go-netrc"]
|
||||
version = "v0.0.0-20140422174119-9fd32a8b3d3d"
|
||||
hash = "sha256-NDxQzO5C5M/aDz5/pjUHfZUh4VwIXovbb3irtxWCwjY="
|
||||
[mod."github.com/bgentry/speakeasy"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-Gt1vj6CFovLnO6wX5u2O4UfecY9V2J9WGw1ez4HMrgk="
|
||||
[mod."github.com/btcsuite/btcd"]
|
||||
version = "v0.22.1"
|
||||
hash = "sha256-hBU+roIELcmbW2Gz7eGZzL9qNA1bakq5wNxqCgs4TKc="
|
||||
[mod."github.com/btcsuite/btcd/btcec/v2"]
|
||||
version = "v2.2.0"
|
||||
hash = "sha256-cwoIqi0SiAaGEBtuQKip9OVirKIeJw5fUoWo7x/xfOc="
|
||||
[mod."github.com/btcsuite/btcd/chaincfg/chainhash"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-vix0j/KGNvoKjhlKgVeSLY6un2FHeIEoZWMC4z3yvZ4="
|
||||
[mod."github.com/btcsuite/btcutil"]
|
||||
version = "v1.0.3-0.20201208143702-a53e38424cce"
|
||||
hash = "sha256-4kasJReFcj25JRHx9dJMct3yDkHqVoHGUx5cu45Msfo="
|
||||
[mod."github.com/cenkalti/backoff/v4"]
|
||||
version = "v4.1.3"
|
||||
hash = "sha256-u6MEDopHoTWAZoVvvXOKnAg++xre53YgQx0gmf6t2KU="
|
||||
[mod."github.com/cespare/xxhash"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-nVDTtXH9PC3yJ0THaQZEN243UP9xgLi/clt5xRqj3+M="
|
||||
[mod."github.com/cespare/xxhash/v2"]
|
||||
version = "v2.1.2"
|
||||
hash = "sha256-YV9SmXDtmmgQylQUfrUgQLAPfqYexcHxegMBT+IX9qM="
|
||||
[mod."github.com/chzyer/readline"]
|
||||
version = "v0.0.0-20180603132655-2972be24d48e"
|
||||
hash = "sha256-2Uj5LGpHEbLQG3d/7z9AL8DknUBZyoTAMs4j+VVDmIA="
|
||||
[mod."github.com/cockroachdb/apd/v2"]
|
||||
version = "v2.0.2"
|
||||
hash = "sha256-UrPHkvqVF8V78+kXKmjTHl79XsgDBnqFsje5BMYh0E4="
|
||||
[mod."github.com/coinbase/rosetta-sdk-go"]
|
||||
version = "v0.7.9"
|
||||
hash = "sha256-ZWIXIXcHGjeCNgMrpXymry8/8esDDauGFfF/+gEoO1Y="
|
||||
[mod."github.com/confio/ics23/go"]
|
||||
version = "v0.7.0"
|
||||
hash = "sha256-FjUQfDKtX+/13+UjJzbYPAkgM4GPZ0vk+dKz7/iRetw="
|
||||
[mod."github.com/cosmos/btcutil"]
|
||||
version = "v1.0.4"
|
||||
hash = "sha256-JvcBXBdjdmnaW/nyf/tw/uaOAGn1b78yxrtl2/Rs3kA="
|
||||
[mod."github.com/cosmos/cosmos-proto"]
|
||||
version = "v1.0.0-alpha7"
|
||||
hash = "sha256-2wCH+toTF2A6MfFjOa13muEH5oBCcxAhZEqirNOrBA0="
|
||||
[mod."github.com/cosmos/cosmos-sdk"]
|
||||
version = "v0.46.2-0.20220920160224-9454b97ccb77"
|
||||
hash = "sha256-zwOsdcoPbEzn+q/UmW6/CauW65V6a4z/7k8DXPCvKb0="
|
||||
[mod."github.com/cosmos/go-bip39"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
|
||||
[mod."github.com/cosmos/gorocksdb"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY="
|
||||
[mod."github.com/cosmos/iavl"]
|
||||
version = "v0.19.2-0.20220916140702-9b6be3095313"
|
||||
hash = "sha256-49xr/7/4L1wZ45eW5lE7C4SlcbGf4gBY+662SfJiWPQ="
|
||||
[mod."github.com/cosmos/ibc-go/v5"]
|
||||
version = "v5.0.0"
|
||||
hash = "sha256-sDZdmuGohaaBF7bxrjo9PWJnmoF+VOkjySYhsFixPz4="
|
||||
[mod."github.com/cosmos/ledger-cosmos-go"]
|
||||
version = "v0.11.1"
|
||||
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA="
|
||||
[mod."github.com/cosmos/ledger-go"]
|
||||
version = "v0.9.2"
|
||||
hash = "sha256-0YI+0A6wFBjiebBwzWOQjkgXkTakCrf7Gjg2xEaQdoM="
|
||||
[mod."github.com/creachadair/taskgroup"]
|
||||
version = "v0.3.2"
|
||||
hash = "sha256-Y261IO/d9xjV0UScqHvo31broxvnKn4IQQC9Mu6jNkE="
|
||||
[mod."github.com/danieljoos/wincred"]
|
||||
version = "v1.1.2"
|
||||
hash = "sha256-Nnklfg12vmWCOhELGyoRqEF4w4srp0WbPwreaChYLKs="
|
||||
[mod."github.com/davecgh/go-spew"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI="
|
||||
[mod."github.com/deckarep/golang-set"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-ELJKphksU9AOYwV3BtjvwPtUpbZvX9YMmo7eIiauQSc="
|
||||
[mod."github.com/decred/dcrd/dcrec/secp256k1/v4"]
|
||||
version = "v4.0.1"
|
||||
hash = "sha256-JBVRp40dDj0puapoQloV13H6TMjgJiypzYojcDRE2jI="
|
||||
[mod."github.com/desertbit/timer"]
|
||||
version = "v0.0.0-20180107155436-c41aec40b27f"
|
||||
hash = "sha256-abLOtEcomAqCWLphd2X6WkD/ED764w6sa6unox4BXss="
|
||||
[mod."github.com/dgraph-io/badger/v2"]
|
||||
version = "v2.2007.4"
|
||||
hash = "sha256-+KwqZJZpViv8S3TqUVvPXrFoMgWFyS3NoLsi4RR5fGk="
|
||||
[mod."github.com/dgraph-io/ristretto"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-01jneg1+1x8tTfUTBZ+6mHkQaqXVnPYxLJyJhJQcvt4="
|
||||
[mod."github.com/dgryski/go-farm"]
|
||||
version = "v0.0.0-20200201041132-a6ae2369ad13"
|
||||
hash = "sha256-aOMlPwFY36bLiiIx4HonbCYRAhagk5N6HAWN7Ygif+E="
|
||||
[mod."github.com/dlclark/regexp2"]
|
||||
version = "v1.4.1-0.20201116162257-a2a8dda75c91"
|
||||
hash = "sha256-VNNMZIc7NkDg3DVLnqeJNM/KZqkkaZu2/HTLBL8X2xE="
|
||||
[mod."github.com/dop251/goja"]
|
||||
version = "v0.0.0-20220405120441-9037c2b61cbf"
|
||||
hash = "sha256-ueVIwPRUwxzd9+NybuFv1Pvp5tbwl9gGEgXB6cwqzEc="
|
||||
[mod."github.com/dustin/go-humanize"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-gy4G1PnHD9iw2MitHX6y1y93qr3C9IncmXL7ttUMDs8="
|
||||
[mod."github.com/dvsekhvalnov/jose2go"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-dsju6Xt83pe5SRPN/pUOnDUQByZ6hrhKIXWs3sSu7t8="
|
||||
[mod."github.com/edsrzf/mmap-go"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo="
|
||||
[mod."github.com/ethereum/go-ethereum"]
|
||||
version = "v1.10.19"
|
||||
hash = "sha256-7FPnTGcCb8Xd1QVR+6PmGTaHdTY1mm/8osFTW1JLuG8="
|
||||
[mod."github.com/felixge/httpsnoop"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk="
|
||||
[mod."github.com/fsnotify/fsnotify"]
|
||||
version = "v1.5.4"
|
||||
hash = "sha256-iPuInpDAJvDeSTr6to713J/fTOWdQIWlLXWAuWIs2Bw="
|
||||
[mod."github.com/gballet/go-libpcsclite"]
|
||||
version = "v0.0.0-20190607065134-2772fd86a8ff"
|
||||
hash = "sha256-Nr5ocU9s1F2Lhx/Zq6/nIo+KkKEqMjDYOEs3yWRC48g="
|
||||
[mod."github.com/go-kit/kit"]
|
||||
version = "v0.12.0"
|
||||
hash = "sha256-5RkXo6s0oye8etgD5qy+AvkkkNsQ6jc0kWJj6flA4GM="
|
||||
[mod."github.com/go-kit/log"]
|
||||
version = "v0.2.1"
|
||||
hash = "sha256-puLJ+up45X2j9E3lXvBPKqHPKOA/sFAhfCqGxsITW/Y="
|
||||
[mod."github.com/go-logfmt/logfmt"]
|
||||
version = "v0.5.1"
|
||||
hash = "sha256-t50m9ffvW8PiGvO+2svnLI+N/XaWaBS+ZlhwrEQn2gU="
|
||||
[mod."github.com/go-ole/go-ole"]
|
||||
version = "v1.2.6"
|
||||
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
|
||||
[mod."github.com/go-sourcemap/sourcemap"]
|
||||
version = "v2.1.3+incompatible"
|
||||
hash = "sha256-eXhXPPLnAy/rmt/zDgeqni2G3o58UtnHjR8vHLXvISI="
|
||||
[mod."github.com/go-stack/stack"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-26RlTEcAkbewMUtmirKrDGQ1WJlNousp69v7HMopYnI="
|
||||
[mod."github.com/godbus/dbus"]
|
||||
version = "v0.0.0-20190726142602-4481cbc300e2"
|
||||
hash = "sha256-R7Gb9+Zjy80FbQSDGketoVEqfdOQKuOVTfWRjQ5kxZY="
|
||||
[mod."github.com/gogo/gateway"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-OHcA3fEGZt4uYn6V5BAaDc47DkH7z0Al+v7MpkfeR8o="
|
||||
[mod."github.com/gogo/protobuf"]
|
||||
version = "v1.3.3-alpha.regen.1"
|
||||
hash = "sha256-TKa//aFXpWH+yK/cN1oaaqhipZpPUovekP6oA9vLIHY="
|
||||
replaced = "github.com/regen-network/protobuf"
|
||||
[mod."github.com/golang/glog"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-bglITqRgzi52zc6FoYYnfCvrjFWV4RVOacPCnbEBom4="
|
||||
[mod."github.com/golang/groupcache"]
|
||||
version = "v0.0.0-20210331224755-41bb18bfe9da"
|
||||
hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
|
||||
[mod."github.com/golang/protobuf"]
|
||||
version = "v1.5.2"
|
||||
hash = "sha256-IVwooaIo46iq7euSSVWTBAdKd+2DUaJ67MtBao1DpBI="
|
||||
[mod."github.com/golang/snappy"]
|
||||
version = "v0.0.4"
|
||||
hash = "sha256-Umx+5xHAQCN/Gi4HbtMhnDCSPFAXSsjVbXd8n5LhjAA="
|
||||
[mod."github.com/google/btree"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-1PIeFGgUL4BK/StL/D12pg9bEQ5HfMT/fMLdus4pZTs="
|
||||
[mod."github.com/google/go-cmp"]
|
||||
version = "v0.5.8"
|
||||
hash = "sha256-8zkIo+Sr1NXMnj3PNmvjX2sZKnAKWXOFvmnX7D9bwxQ="
|
||||
[mod."github.com/google/orderedcode"]
|
||||
version = "v0.0.1"
|
||||
hash = "sha256-KrExYovtUQrHGI1mPQf57jGw8soz7eWOC2xqEaV0uGk="
|
||||
[mod."github.com/google/uuid"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
|
||||
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-fxaElfiGGh1mLmltkFpVFdiuaagrLZLTW9btVpK13wg="
|
||||
[mod."github.com/googleapis/gax-go/v2"]
|
||||
version = "v2.4.0"
|
||||
hash = "sha256-zzat4+3iF2XBTQ6RZAUgsCbfK0HgO0nYhM4utA5dqz0="
|
||||
[mod."github.com/googleapis/go-type-adapters"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-u3ajruRV/EN2E1WKet/zoe3zmRrAy4C5F2Dx8bpQwoc="
|
||||
[mod."github.com/gorilla/handlers"]
|
||||
version = "v1.5.1"
|
||||
hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU="
|
||||
[mod."github.com/gorilla/mux"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-s905hpzMH9bOLue09E2JmzPXfIS4HhAlgT7g13HCwKE="
|
||||
[mod."github.com/gorilla/websocket"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-EYVgkSEMo4HaVrsWKqnsYRp8SSS8gNf7t+Elva02Ofc="
|
||||
[mod."github.com/grpc-ecosystem/go-grpc-middleware"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-seaTQMNz/lWzpR3ex2gSM1Yo2yD2q6bJQZvB1L3CONk="
|
||||
[mod."github.com/grpc-ecosystem/grpc-gateway"]
|
||||
version = "v1.16.0"
|
||||
hash = "sha256-wLymGic7wZ6fSiBYDAaGqnQ9Ste1fUWeqXeolZXCHvI="
|
||||
[mod."github.com/gsterjov/go-libsecret"]
|
||||
version = "v0.0.0-20161001094733-a6f4afe4910c"
|
||||
hash = "sha256-Z5upjItPU9onq5t7VzhdQFp13lMJrSiE3gNRapuK6ic="
|
||||
[mod."github.com/gtank/merlin"]
|
||||
version = "v0.1.1"
|
||||
hash = "sha256-tfP9DFdPIfAt29pCta6dObAABCbZt4y3ZActH6ERkr0="
|
||||
[mod."github.com/gtank/ristretto255"]
|
||||
version = "v0.1.2"
|
||||
hash = "sha256-fAoVTP1s5+f7/YtnzI+gaEz1MS+FuCgy3sT19ZHIxE4="
|
||||
[mod."github.com/hashicorp/go-cleanhttp"]
|
||||
version = "v0.5.2"
|
||||
hash = "sha256-N9GOKYo7tK6XQUFhvhImtL7PZW/mr4C4Manx/yPVvcQ="
|
||||
[mod."github.com/hashicorp/go-getter"]
|
||||
version = "v1.6.1"
|
||||
hash = "sha256-WPCbbfFbE617EIUXxq81p3XrvhkSvYOeuiaR7n23nr0="
|
||||
[mod."github.com/hashicorp/go-immutable-radix"]
|
||||
version = "v1.3.1"
|
||||
hash = "sha256-65+A2HiVfS/GV9G+6/TkXXjzXhI/V98e6RlJWjxy+mg="
|
||||
[mod."github.com/hashicorp/go-safetemp"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-g5i9m7FSRInQzZ4iRpIsoUu685AY7fppUwjhuZCezT8="
|
||||
[mod."github.com/hashicorp/go-version"]
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-UV0equpmW6BiJnp4W3TZlSJ+PTHuTA+CdOs2JTeHhjs="
|
||||
[mod."github.com/hashicorp/golang-lru"]
|
||||
version = "v0.5.5-0.20210104140557-80c98217689d"
|
||||
hash = "sha256-w5utLMR7p5pF9xX+mI3N9NyfQ8ixNXNTgfXDu8fudmc="
|
||||
[mod."github.com/hashicorp/hcl"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-xsRCmYyBfglMxeWUvTZqkaRLSW+V2FvNodEDjTGg1WA="
|
||||
[mod."github.com/hdevalence/ed25519consensus"]
|
||||
version = "v0.0.0-20220222234857-c00d1f31bab3"
|
||||
hash = "sha256-1ec2xc7l9oNtWJwVtx14HnozMZCe2DpfXmu1xI1Z/yo="
|
||||
[mod."github.com/holiman/bloomfilter/v2"]
|
||||
version = "v2.0.3"
|
||||
hash = "sha256-5VsJMQzJSNd4F7yAl3iF/q6JodWOlE4dUvTQ0UGPe+k="
|
||||
[mod."github.com/holiman/uint256"]
|
||||
version = "v1.2.1"
|
||||
hash = "sha256-1N+MvvzTIegV1UPEGUVyxBZaxczId/Z/BUVcnx7ckHE="
|
||||
[mod."github.com/huin/goupnp"]
|
||||
version = "v1.0.3"
|
||||
hash = "sha256-EMGmTdoQhP2bVbCPX37hes5krqXn6NFexfnKr9E5u8I="
|
||||
[mod."github.com/improbable-eng/grpc-web"]
|
||||
version = "v0.15.0"
|
||||
hash = "sha256-9oqKb5Y3hjleOFE2BczbEzLH6q2Jg7kUTP/M8Yk4Ne4="
|
||||
[mod."github.com/inconshreveable/mousetrap"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-ogTuLrV40FwS4ueo4hh6hi1wPywOI+LyIqfNjsibwNY="
|
||||
[mod."github.com/jackpal/go-nat-pmp"]
|
||||
version = "v1.0.2"
|
||||
hash = "sha256-L1D4Yoxnzihs795GZ+Q3AZsFP5c4iqyjTeyrudzPXtw="
|
||||
[mod."github.com/jmespath/go-jmespath"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-xpT9g2qIXmPq7eeHUXHiDqJeQoHCudh44G/KCSFbcuo="
|
||||
[mod."github.com/jmhodges/levigo"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-xEd0mDBeq3eR/GYeXjoTVb2sPs8sTCosn5ayWkcgENI="
|
||||
[mod."github.com/keybase/go-keychain"]
|
||||
version = "v0.0.0-20190712205309-48d3d31d256d"
|
||||
hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q="
|
||||
[mod."github.com/klauspost/compress"]
|
||||
version = "v1.15.9"
|
||||
hash = "sha256-ctPxlVq0c/SoNPVsP66RjxUjTHys3diW2Apxjyc9WdE="
|
||||
[mod."github.com/lib/pq"]
|
||||
version = "v1.10.6"
|
||||
hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM="
|
||||
[mod."github.com/libp2p/go-buffer-pool"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-wQqGTtRWsfR9n0O/SXHVgECebbnNmHddxJIbG63OJBQ="
|
||||
[mod."github.com/magiconair/properties"]
|
||||
version = "v1.8.6"
|
||||
hash = "sha256-xToSfpuePctkTdhJtsuKIEkXwfMZbnkFT98ahIfd4wY="
|
||||
[mod."github.com/manifoldco/promptui"]
|
||||
version = "v0.9.0"
|
||||
hash = "sha256-Fe2OPoyRExZejwtUBivKhfJAJW7o9b1eyYpgDlWQ1No="
|
||||
[mod."github.com/mattn/go-colorable"]
|
||||
version = "v0.1.12"
|
||||
hash = "sha256-Y1vCt0ShrCz4wSmwsppCfeLPLKrWusc2zM2lUFwDMyI="
|
||||
[mod."github.com/mattn/go-isatty"]
|
||||
version = "v0.0.16"
|
||||
hash = "sha256-YMaPZvShDfA98vqw1+zWWl7M1IT4nHPGBrAt7kHo8Iw="
|
||||
[mod."github.com/mattn/go-runewidth"]
|
||||
version = "v0.0.9"
|
||||
hash = "sha256-dK/kIPe1tcxEubwI4CWfov/HWRBgD/fqlPC3d5i30CY="
|
||||
[mod."github.com/matttproud/golang_protobuf_extensions"]
|
||||
version = "v1.0.2-0.20181231171920-c182affec369"
|
||||
hash = "sha256-uovu7OycdeZ2oYQ7FhVxLey5ZX3T0FzShaRldndyGvc="
|
||||
[mod."github.com/miguelmota/go-ethereum-hdwallet"]
|
||||
version = "v0.1.1"
|
||||
hash = "sha256-SoKy4Mwkbm0J2yQLDcIcBbo/J6auTNdlZslTvJrSknM="
|
||||
[mod."github.com/mimoo/StrobeGo"]
|
||||
version = "v0.0.0-20181016162300-f8f6d4d2b643"
|
||||
hash = "sha256-ih5WfC48IniPuAHUpC6upOabZA1/DssTAcxhZe6A/dE="
|
||||
[mod."github.com/minio/highwayhash"]
|
||||
version = "v1.0.2"
|
||||
hash = "sha256-UeHeepKtToyA5e/w3KdmpbCn+4medesZG0cAcU6P2cY="
|
||||
[mod."github.com/mitchellh/go-homedir"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-oduBKXHAQG8X6aqLEpqZHs5DOKe84u6WkBwi4W6cv3k="
|
||||
[mod."github.com/mitchellh/go-testing-interface"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-/Dpv/4i5xuK8hDH+q8YTdF6Jg6NNtfO4Wqig2JCWgrY="
|
||||
[mod."github.com/mitchellh/mapstructure"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-ztVhGQXs67MF8UadVvG72G3ly0ypQW0IRDdOOkjYwoE="
|
||||
[mod."github.com/mtibben/percent"]
|
||||
version = "v0.2.1"
|
||||
hash = "sha256-Zj1lpCP6mKQ0UUTMs2By4LC414ou+iJzKkK+eBHfEcc="
|
||||
[mod."github.com/olekukonko/tablewriter"]
|
||||
version = "v0.0.5"
|
||||
hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4="
|
||||
[mod."github.com/onsi/ginkgo/v2"]
|
||||
version = "v2.2.0"
|
||||
hash = "sha256-+VzAN6pB5DwEqT/KHdhgfPnWBtyIIcHi1J4HQkqCvvU="
|
||||
[mod."github.com/onsi/gomega"]
|
||||
version = "v1.20.2"
|
||||
hash = "sha256-3SGyvhWVlR3tYojnRSDr2SRToontAtw4hbZX+agn/Hs="
|
||||
[mod."github.com/pelletier/go-toml"]
|
||||
version = "v1.9.5"
|
||||
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="
|
||||
[mod."github.com/pelletier/go-toml/v2"]
|
||||
version = "v2.0.5"
|
||||
hash = "sha256-YWdHmuCGliWfiH0tTHuf07AAn/zOJNoq7g+5fvqdnrQ="
|
||||
[mod."github.com/petermattis/goid"]
|
||||
version = "v0.0.0-20180202154549-b0b1615b78e5"
|
||||
hash = "sha256-TCyVuP7rAtrvlterVCapFtbf6UmIf72FXQvkQoDtDj4="
|
||||
[mod."github.com/pkg/errors"]
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-mNfQtcrQmu3sNg/7IwiieKWOgFQOVVe2yXgKBpe/wZw="
|
||||
[mod."github.com/pmezard/go-difflib"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA="
|
||||
[mod."github.com/prometheus/client_golang"]
|
||||
version = "v1.12.2"
|
||||
hash = "sha256-d8xHyML/FImuPmFOy7UGW/y85NPLzJYL6IFhR3s7XzE="
|
||||
[mod."github.com/prometheus/client_model"]
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-LTHxYPRgoggl+v89ly2/RkyPIuJlmZRdGs6ZRtK3zkk="
|
||||
[mod."github.com/prometheus/common"]
|
||||
version = "v0.34.0"
|
||||
hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA="
|
||||
[mod."github.com/prometheus/procfs"]
|
||||
version = "v0.7.3"
|
||||
hash = "sha256-ik0WpnpSjMwifPYfQTfu/eb5ilNj+eLJF0d5Dftp8A8="
|
||||
[mod."github.com/prometheus/tsdb"]
|
||||
version = "v0.7.1"
|
||||
hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA="
|
||||
[mod."github.com/rakyll/statik"]
|
||||
version = "v0.1.7"
|
||||
hash = "sha256-/bfnXHBmN8vviPL7D85IzcEVXCaWyjbPPNyauzEcQ8Q="
|
||||
[mod."github.com/rcrowley/go-metrics"]
|
||||
version = "v0.0.0-20200313005456-10cdbea86bc0"
|
||||
hash = "sha256-xHqWWd4/RyAxqb80zjnrqHnHtWPfVTyByE+vDfbT52E="
|
||||
[mod."github.com/regen-network/cosmos-proto"]
|
||||
version = "v0.3.1"
|
||||
hash = "sha256-Bchbq/Hg72EA7Hevs8+PNuENuQaZAzk3qeVjMqFMUxc="
|
||||
[mod."github.com/rjeczalik/notify"]
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-YLGNrHHM+mN4ElW/XWuylOnFrA/VjSY+eBuC4LN//5c="
|
||||
[mod."github.com/rs/cors"]
|
||||
version = "v1.8.2"
|
||||
hash = "sha256-FxBbQVb8zIoDGGaAJKfsYV0+POkh1tyX7P6A/Lk5Vsc="
|
||||
[mod."github.com/rs/zerolog"]
|
||||
version = "v1.27.0"
|
||||
hash = "sha256-BxQtP2TROeSSpj9l1irocuSfxn55UL4ugzB/og7r8eE="
|
||||
[mod."github.com/sasha-s/go-deadlock"]
|
||||
version = "v0.2.1-0.20190427202633-1595213edefa"
|
||||
hash = "sha256-BBOohTR+ktgJHAoYWh39/ui8MczcJECloc7tvxVBE50="
|
||||
[mod."github.com/shirou/gopsutil"]
|
||||
version = "v3.21.4-0.20210419000835-c7a38de76ee5+incompatible"
|
||||
hash = "sha256-oqIqyFquWabIE6DID6uTEc8oFEmM1rVu2ATn3toiCEg="
|
||||
[mod."github.com/spf13/afero"]
|
||||
version = "v1.8.2"
|
||||
hash = "sha256-ERuG4GK1LOn72DRbT9URpo1QoVIm2A3mPtlf+xSPgx8="
|
||||
[mod."github.com/spf13/cast"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-Pdp+wC5FWqyJKzyYHb7JCcV9BoJk/sxQw6nLyuLJvuQ="
|
||||
[mod."github.com/spf13/cobra"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-rcyHWrxshA5DVpxrSba5X4NjppqOGrJ64QkUKKnfW2E="
|
||||
[mod."github.com/spf13/jwalterweatherman"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-62BQtqTLF/eVrTOr7pUXE7AiHRjOVC8jQs3/Ehmflfs="
|
||||
[mod."github.com/spf13/pflag"]
|
||||
version = "v1.0.5"
|
||||
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
|
||||
[mod."github.com/spf13/viper"]
|
||||
version = "v1.13.0"
|
||||
hash = "sha256-yHviS3lMo1hB6jwyiU3zpyGtxP6v9AsyZUKiLeCVz+k="
|
||||
[mod."github.com/status-im/keycard-go"]
|
||||
version = "v0.0.0-20200402102358-957c09536969"
|
||||
hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk="
|
||||
[mod."github.com/stretchr/objx"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-W6ycaeD/okr4udpCAGDsByr3OmiR0fuBzJUXHaHEFC0="
|
||||
[mod."github.com/stretchr/testify"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-LDxBAebK+A06y4vbH7cd1sVBOameIY81Xm8/9OPZh7o="
|
||||
[mod."github.com/subosito/gotenv"]
|
||||
version = "v1.4.1"
|
||||
hash = "sha256-aHAUs8Gh+BREUulljWr7vBZQg1BLu/M/8UfNK8CWSn8="
|
||||
[mod."github.com/syndtr/goleveldb"]
|
||||
version = "v1.0.1-0.20210819022825-2ae1ddf74ef7"
|
||||
hash = "sha256-36a4hgVQfwtS2zhylKpQuFhrjdc/Y8pF0dxc26jcZIU="
|
||||
[mod."github.com/tendermint/btcd"]
|
||||
version = "v0.1.1"
|
||||
hash = "sha256-QQl2GWZaKQtd+LQrgx2unkTLI1qye57fCWwJcmCXT/0="
|
||||
[mod."github.com/tendermint/crypto"]
|
||||
version = "v0.0.0-20191022145703-50d29ede1e15"
|
||||
hash = "sha256-NkoZ3hKWZt5Hca49I+1g81x1m6aQGELZ/QGLdb3uHm4="
|
||||
[mod."github.com/tendermint/go-amino"]
|
||||
version = "v0.16.0"
|
||||
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
|
||||
[mod."github.com/tendermint/tendermint"]
|
||||
version = "v0.34.21"
|
||||
hash = "sha256-C1KW6Wd4TwsFC09IHt8Jo3dozEk/Q2ZVdTapM8btEJ0="
|
||||
[mod."github.com/tendermint/tm-db"]
|
||||
version = "v0.6.7"
|
||||
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
|
||||
[mod."github.com/tklauser/go-sysconf"]
|
||||
version = "v0.3.10"
|
||||
hash = "sha256-Zf2NsgM9+HeM949vCce4HQtSbfUiFpeiQ716yKcFyx4="
|
||||
[mod."github.com/tklauser/numcpus"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-ndE82nOb3agubhEV7aRzEqqTlN4DPbKFHEm2+XZLn8k="
|
||||
[mod."github.com/tyler-smith/go-bip39"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-3YhWBtSwRLGwm7vNwqumphZG3uLBW1vwT9QkQ8JuSjU="
|
||||
[mod."github.com/ulikunitz/xz"]
|
||||
version = "v0.5.8"
|
||||
hash = "sha256-bfG3dssBUn+mSOAuKL+a/DTGGLUA+eASgLoGv/Gkqs0="
|
||||
[mod."github.com/zondax/hid"]
|
||||
version = "v0.9.1-0.20220302062450-5552068d2266"
|
||||
hash = "sha256-IZea8SHuLQxlltm1avieRVI054TWZg2jEoplodvNtwk="
|
||||
[mod."go.etcd.io/bbolt"]
|
||||
version = "v1.3.6"
|
||||
hash = "sha256-DenVAmyN22xUiivk6fdJp4C9ZnUJXCMDUf8E0goRRV4="
|
||||
[mod."go.opencensus.io"]
|
||||
version = "v0.23.0"
|
||||
hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.0.0-20220622213112-05595931fe9d"
|
||||
hash = "sha256-2c4wvwiQ0DJSJsApfmNoxCxx1siRCiJvW9hhrGlcvds="
|
||||
[mod."golang.org/x/exp"]
|
||||
version = "v0.0.0-20220722155223-a9213eeb770e"
|
||||
hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.0.0-20220726230323-06994584191e"
|
||||
hash = "sha256-VFJB2BjvFZnp0zoJLX4iinV/P6Cn7XUlsKwBGCdVjlU="
|
||||
[mod."golang.org/x/oauth2"]
|
||||
version = "v0.0.0-20220622183110-fd043fe589d2"
|
||||
hash = "sha256-VLffpTpx3DlUzXB8mKiJfFzm4ZmgnLSUuLB5Ir0WQUg="
|
||||
[mod."golang.org/x/sync"]
|
||||
version = "v0.0.0-20220722155255-886fb9371eb4"
|
||||
hash = "sha256-ZZyIlxh+nqsOiWHstW7eHXN7RhHnbSL2eDIzcve07Q0="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.0.0-20220811171246-fbc7d0a398ab"
|
||||
hash = "sha256-acnc9aKY/SyebObLasV+gowfB0S+6ehz3hnUgAmQmSU="
|
||||
[mod."golang.org/x/term"]
|
||||
version = "v0.0.0-20220722155259-a9ba230a4035"
|
||||
hash = "sha256-9uM1OONzbsa6bz2iKk767hAaCuafi58bdTF7at03fWY="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.3.7"
|
||||
hash = "sha256-XH2pUzzQx95O0rak00grQvfACfL+EmZiV7ZzJBkX+XY="
|
||||
[mod."golang.org/x/xerrors"]
|
||||
version = "v0.0.0-20220609144429-65e65417b02f"
|
||||
hash = "sha256-tl8pv3oddbz2+KoIp7PFDKsxjQF8ocjPF8XPsY3sw38="
|
||||
[mod."google.golang.org/api"]
|
||||
version = "v0.93.0"
|
||||
hash = "sha256-W17B79osAhObMbrCHlgywEPg9yIPx0ZISDhp9JwFE5A="
|
||||
[mod."google.golang.org/appengine"]
|
||||
version = "v1.6.7"
|
||||
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
|
||||
[mod."google.golang.org/genproto"]
|
||||
version = "v0.0.0-20220815135757-37a418bb8959"
|
||||
hash = "sha256-uS60VVZDdn6kNV24bmOmSTuwz4lBqVM+9XK176GGL2s="
|
||||
[mod."google.golang.org/grpc"]
|
||||
version = "v1.49.0"
|
||||
hash = "sha256-x4+/XjxI2HY8fZYMiEV7Kv+2SrnlmaTJX3tBl+dPUoI="
|
||||
[mod."google.golang.org/protobuf"]
|
||||
version = "v1.28.1"
|
||||
hash = "sha256-sTJYgvlv5is7vHNxcuigF2lNASp0QonhUgnrguhfHSU="
|
||||
[mod."gopkg.in/ini.v1"]
|
||||
version = "v1.67.0"
|
||||
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
|
||||
[mod."gopkg.in/natefinch/npipe.v2"]
|
||||
version = "v2.0.0-20160621034901-c1b8fa8bdcce"
|
||||
hash = "sha256-ytqeVZqn4kd2uc65HvEjPlpPA2VnBmPfu5DsFlO0o+g="
|
||||
[mod."gopkg.in/yaml.v2"]
|
||||
version = "v2.4.0"
|
||||
hash = "sha256-uVEGglIedjOIGZzHW4YwN1VoRSTK8o0eGZqzd+TNdd0="
|
||||
[mod."gopkg.in/yaml.v3"]
|
||||
version = "v3.0.1"
|
||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||
[mod."nhooyr.io/websocket"]
|
||||
version = "v1.8.6"
|
||||
hash = "sha256-DyaiCc/1iELrl6JSpz6WYMtFwUiSCOSoNF8IhSyP1ag="
|
||||
[mod."sigs.k8s.io/yaml"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-RVp8vca2wxg8pcBDYospG7Z1dujoH7zXNu2rgZ1kky0="
|
@ -34,7 +34,7 @@ type queryResolver struct{ *Resolver }
|
||||
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*AuthorityRecord, error) {
|
||||
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*AuthorityRecord
|
||||
gqlResponse := []*AuthorityRecord{}
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.Whois(context.Background(), &nstypes.QueryWhoisRequest{Name: name})
|
||||
@ -125,7 +125,6 @@ func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueI
|
||||
All: (all != nil && *all),
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -142,7 +141,6 @@ func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueI
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
|
||||
}
|
||||
|
||||
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Record, error) {
|
||||
@ -150,7 +148,7 @@ func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Re
|
||||
gqlResponse := make([]*Record, len(ids))
|
||||
|
||||
for i, id := range ids {
|
||||
res, err := nsQueryClient.GetRecord(context.Background(), &nstypes.QueryRecordByIdRequest{Id: id})
|
||||
res, err := nsQueryClient.GetRecord(context.Background(), &nstypes.QueryRecordByIDRequest{Id: id})
|
||||
if err != nil {
|
||||
// Return nil for record not found.
|
||||
gqlResponse[i] = nil
|
||||
@ -231,7 +229,9 @@ func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account
|
||||
// Get the account balance
|
||||
bankQueryClient := banktypes.NewQueryClient(q.ctx)
|
||||
balance, err := bankQueryClient.AllBalances(ctx, &banktypes.QueryAllBalancesRequest{Address: address})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accNum := strconv.FormatUint(account.GetAccountNumber(), 10)
|
||||
seq := strconv.FormatUint(account.GetSequence(), 10)
|
||||
|
||||
@ -259,7 +259,7 @@ func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond
|
||||
|
||||
func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondById(context.Background(), &bondtypes.QueryGetBondByIdRequest{Id: id})
|
||||
bondResp, err := bondQueryClient.GetBondByID(context.Background(), &bondtypes.QueryGetBondByIDRequest{Id: id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -313,7 +313,8 @@ func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*Ow
|
||||
|
||||
ownerBonds := make([]*Bond, len(bondResp.GetBonds()))
|
||||
for i, bond := range bondResp.GetBonds() {
|
||||
bondObj, err := getGQLBond(&bond)
|
||||
// #nosec G601
|
||||
bondObj, err := getGQLBond(&bond) //nolint: all
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,12 +2,13 @@ package gql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/spf13/viper"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Server configures and starts the GQL server.
|
||||
@ -37,7 +38,7 @@ func Server(ctx client.Context) {
|
||||
http.Handle("/graphql", srv)
|
||||
|
||||
log.Info("Connect to GraphQL playground", "url", fmt.Sprintf("http://localhost:%s", port))
|
||||
err := http.ListenAndServe(":"+port, nil)
|
||||
err := http.ListenAndServe(":"+port, nil) //nolint: all
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func getNetInfo(client client.Context) (string, []*PeerInfo, error) {
|
||||
for index, peer := range netInfo.Peers {
|
||||
peersInfo[index] = &PeerInfo{
|
||||
Node: &NodeInfo{
|
||||
ID: string(peer.ID),
|
||||
ID: string(peer.NodeInfo.ID()),
|
||||
// Moniker: peer.Node.Moniker,
|
||||
// Network: peer.Node.Network,
|
||||
},
|
||||
@ -91,7 +91,7 @@ func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||
|
||||
// GetDiskUsage returns disk usage for the given path.
|
||||
func GetDiskUsage(dirPath string) (string, error) {
|
||||
out, err := exec.Command("du", "-sh", dirPath).Output()
|
||||
out, err := exec.Command("du", "-sh", dirPath).Output() // #nosec G204
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
37
gql/util.go
37
gql/util.go
@ -3,7 +3,8 @@ package gql
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"fmt"
|
||||
"reflect" // #nosec G702
|
||||
"strconv"
|
||||
|
||||
auctiontypes "github.com/cerc-io/laconicd/x/auction/types"
|
||||
@ -38,6 +39,7 @@ func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||
|
||||
return gqlCoins
|
||||
}
|
||||
|
||||
func GetGQLNameAuthorityRecord(record *nstypes.NameAuthority) (*AuthorityRecord, error) {
|
||||
if record == nil {
|
||||
return nil, nil
|
||||
@ -84,7 +86,7 @@ func getGQLRecord(ctx context.Context, resolver QueryResolver, record nstypes.Re
|
||||
|
||||
func getGQLNameRecord(record *nstypes.NameRecord) (*NameRecord, error) {
|
||||
if record == nil {
|
||||
return nil, nil
|
||||
return nil, fmt.Errorf("got nil record")
|
||||
}
|
||||
|
||||
records := make([]*NameRecordEntry, len(record.History))
|
||||
@ -118,26 +120,6 @@ func getGQLBond(bondObj *bondtypes.Bond) (*Bond, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func matchBondOnAttributes(bondObj *bondtypes.Bond, attributes []*KeyValueInput) bool {
|
||||
for _, attr := range attributes {
|
||||
switch attr.Key {
|
||||
case OwnerAttributeName:
|
||||
{
|
||||
if attr.Value.String == nil || bondObj.Owner != *attr.Value.String {
|
||||
return false
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Only attributes explicitly listed in the switch are queryable.
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||
return &AuctionBid{
|
||||
BidderAddress: bid.BidderAddress,
|
||||
@ -184,10 +166,12 @@ func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Au
|
||||
func getReferences(ctx context.Context, resolver QueryResolver, r *nstypes.RecordType) ([]*Record, error) {
|
||||
var ids []string
|
||||
|
||||
for _, value := range r.Attributes {
|
||||
switch value.(type) {
|
||||
// #nosec G705
|
||||
for key := range r.Attributes {
|
||||
//nolint: all
|
||||
switch r.Attributes[key].(type) {
|
||||
case interface{}:
|
||||
if obj, ok := value.(map[string]interface{}); ok {
|
||||
if obj, ok := r.Attributes[key].(map[string]interface{}); ok {
|
||||
if _, ok := obj["/"]; ok && len(obj) == 1 {
|
||||
if _, ok := obj["/"].(string); ok {
|
||||
ids = append(ids, obj["/"].(string))
|
||||
@ -205,11 +189,12 @@ func getAttributes(r *nstypes.RecordType) ([]*KeyValue, error) {
|
||||
}
|
||||
|
||||
func mapToKeyValuePairs(attrs map[string]interface{}) ([]*KeyValue, error) {
|
||||
var kvPairs []*KeyValue
|
||||
kvPairs := []*KeyValue{}
|
||||
|
||||
trueVal := true
|
||||
falseVal := false
|
||||
|
||||
// #nosec G705
|
||||
for key, value := range attrs {
|
||||
kvPair := &KeyValue{
|
||||
Key: key,
|
||||
|
230
indexer/kv_indexer.go
Normal file
230
indexer/kv_indexer.go
Normal file
@ -0,0 +1,230 @@
|
||||
package indexer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
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/ethereum/go-ethereum/common"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
)
|
||||
|
||||
const (
|
||||
KeyPrefixTxHash = 1
|
||||
KeyPrefixTxIndex = 2
|
||||
|
||||
// TxIndexKeyLength is the length of tx-index key
|
||||
TxIndexKeyLength = 1 + 8 + 8
|
||||
)
|
||||
|
||||
var _ ethermint.EVMTxIndexer = &KVIndexer{}
|
||||
|
||||
// KVIndexer implements a eth tx indexer on a KV db.
|
||||
type KVIndexer struct {
|
||||
db dbm.DB
|
||||
logger log.Logger
|
||||
clientCtx client.Context
|
||||
}
|
||||
|
||||
// NewKVIndexer creates the KVIndexer
|
||||
func NewKVIndexer(db dbm.DB, logger log.Logger, clientCtx client.Context) *KVIndexer {
|
||||
return &KVIndexer{db, logger, clientCtx}
|
||||
}
|
||||
|
||||
// IndexBlock index all the eth txs in a block through the following steps:
|
||||
// - Iterates over all of the Txs in Block
|
||||
// - Parses eth Tx infos from cosmos-sdk events for every TxResult
|
||||
// - Iterates over all the messages of the Tx
|
||||
// - Builds and stores a indexer.TxResult based on parsed events for every message
|
||||
func (kv *KVIndexer) IndexBlock(block *tmtypes.Block, txResults []*abci.ResponseDeliverTx) error {
|
||||
height := block.Header.Height
|
||||
|
||||
batch := kv.db.NewBatch()
|
||||
defer batch.Close()
|
||||
|
||||
// record index of valid eth tx during the iteration
|
||||
var ethTxIndex int32
|
||||
for txIndex, tx := range block.Txs {
|
||||
result := txResults[txIndex]
|
||||
if !rpctypes.TxSuccessOrExceedsBlockGasLimit(result) {
|
||||
continue
|
||||
}
|
||||
|
||||
tx, err := kv.clientCtx.TxConfig.TxDecoder()(tx)
|
||||
if err != nil {
|
||||
kv.logger.Error("Fail to decode tx", "err", err, "block", height, "txIndex", txIndex)
|
||||
continue
|
||||
}
|
||||
|
||||
if !isEthTx(tx) {
|
||||
continue
|
||||
}
|
||||
|
||||
txs, err := rpctypes.ParseTxResult(result, tx)
|
||||
if err != nil {
|
||||
kv.logger.Error("Fail to parse event", "err", err, "block", height, "txIndex", txIndex)
|
||||
continue
|
||||
}
|
||||
|
||||
var cumulativeGasUsed uint64
|
||||
for msgIndex, msg := range tx.GetMsgs() {
|
||||
ethMsg := msg.(*evmtypes.MsgEthereumTx)
|
||||
txHash := common.HexToHash(ethMsg.Hash)
|
||||
|
||||
txResult := ethermint.TxResult{
|
||||
Height: height,
|
||||
TxIndex: uint32(txIndex),
|
||||
MsgIndex: uint32(msgIndex),
|
||||
EthTxIndex: ethTxIndex,
|
||||
}
|
||||
if result.Code != abci.CodeTypeOK {
|
||||
// exceeds block gas limit scenario, set gas used to gas limit because that's what's charged by ante handler.
|
||||
// some old versions don't emit any events, so workaround here directly.
|
||||
txResult.GasUsed = ethMsg.GetGas()
|
||||
txResult.Failed = true
|
||||
} else {
|
||||
parsedTx := txs.GetTxByMsgIndex(msgIndex)
|
||||
if parsedTx == nil {
|
||||
kv.logger.Error("msg index not found in events", "msgIndex", msgIndex)
|
||||
continue
|
||||
}
|
||||
if parsedTx.EthTxIndex >= 0 && parsedTx.EthTxIndex != ethTxIndex {
|
||||
kv.logger.Error("eth tx index don't match", "expect", ethTxIndex, "found", parsedTx.EthTxIndex)
|
||||
}
|
||||
txResult.GasUsed = parsedTx.GasUsed
|
||||
txResult.Failed = parsedTx.Failed
|
||||
}
|
||||
|
||||
cumulativeGasUsed += txResult.GasUsed
|
||||
txResult.CumulativeGasUsed = cumulativeGasUsed
|
||||
ethTxIndex++
|
||||
|
||||
if err := saveTxResult(kv.clientCtx.Codec, batch, txHash, &txResult); err != nil {
|
||||
return sdkerrors.Wrapf(err, "IndexBlock %d", height)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := batch.Write(); err != nil {
|
||||
return sdkerrors.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LastIndexedBlock returns the latest indexed block number, returns -1 if db is empty
|
||||
func (kv *KVIndexer) LastIndexedBlock() (int64, error) {
|
||||
return LoadLastBlock(kv.db)
|
||||
}
|
||||
|
||||
// FirstIndexedBlock returns the first indexed block number, returns -1 if db is empty
|
||||
func (kv *KVIndexer) FirstIndexedBlock() (int64, error) {
|
||||
return LoadFirstBlock(kv.db)
|
||||
}
|
||||
|
||||
// GetByTxHash finds eth tx by eth tx hash
|
||||
func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) {
|
||||
bz, err := kv.db.Get(TxHashKey(hash))
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
}
|
||||
if len(bz) == 0 {
|
||||
return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex())
|
||||
}
|
||||
var txKey ethermint.TxResult
|
||||
if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
}
|
||||
return &txKey, nil
|
||||
}
|
||||
|
||||
// GetByBlockAndIndex finds eth tx by block number and eth tx index
|
||||
func (kv *KVIndexer) GetByBlockAndIndex(blockNumber int64, txIndex int32) (*ethermint.TxResult, error) {
|
||||
bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex))
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex)
|
||||
}
|
||||
if len(bz) == 0 {
|
||||
return nil, fmt.Errorf("tx not found, block: %d, eth-index: %d", blockNumber, txIndex)
|
||||
}
|
||||
return kv.GetByTxHash(common.BytesToHash(bz))
|
||||
}
|
||||
|
||||
// TxHashKey returns the key for db entry: `tx hash -> tx result struct`
|
||||
func TxHashKey(hash common.Hash) []byte {
|
||||
return append([]byte{KeyPrefixTxHash}, hash.Bytes()...)
|
||||
}
|
||||
|
||||
// TxIndexKey returns the key for db entry: `(block number, tx index) -> tx hash`
|
||||
func TxIndexKey(blockNumber int64, txIndex int32) []byte {
|
||||
bz1 := sdk.Uint64ToBigEndian(uint64(blockNumber))
|
||||
bz2 := sdk.Uint64ToBigEndian(uint64(txIndex))
|
||||
return append(append([]byte{KeyPrefixTxIndex}, bz1...), bz2...)
|
||||
}
|
||||
|
||||
// LoadLastBlock returns the latest indexed block number, returns -1 if db is empty
|
||||
func LoadLastBlock(db dbm.DB) (int64, error) {
|
||||
it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(err, "LoadLastBlock")
|
||||
}
|
||||
defer it.Close()
|
||||
if !it.Valid() {
|
||||
return -1, nil
|
||||
}
|
||||
return parseBlockNumberFromKey(it.Key())
|
||||
}
|
||||
|
||||
// LoadFirstBlock loads the first indexed block, returns -1 if db is empty
|
||||
func LoadFirstBlock(db dbm.DB) (int64, error) {
|
||||
it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(err, "LoadFirstBlock")
|
||||
}
|
||||
defer it.Close()
|
||||
if !it.Valid() {
|
||||
return -1, nil
|
||||
}
|
||||
return parseBlockNumberFromKey(it.Key())
|
||||
}
|
||||
|
||||
// isEthTx check if the tx is an eth tx
|
||||
func isEthTx(tx sdk.Tx) bool {
|
||||
extTx, ok := tx.(authante.HasExtensionOptionsTx)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
opts := extTx.GetExtensionOptions()
|
||||
if len(opts) != 1 || opts[0].GetTypeUrl() != "/ethermint.evm.v1.ExtensionOptionsEthereumTx" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// saveTxResult index the txResult into the kv db batch
|
||||
func saveTxResult(codec codec.Codec, batch dbm.Batch, txHash common.Hash, txResult *ethermint.TxResult) error {
|
||||
bz := codec.MustMarshal(txResult)
|
||||
if err := batch.Set(TxHashKey(txHash), bz); err != nil {
|
||||
return sdkerrors.Wrap(err, "set tx-hash key")
|
||||
}
|
||||
if err := batch.Set(TxIndexKey(txResult.Height, txResult.EthTxIndex), txHash.Bytes()); err != nil {
|
||||
return sdkerrors.Wrap(err, "set tx-index key")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseBlockNumberFromKey(key []byte) (int64, error) {
|
||||
if len(key) != TxIndexKeyLength {
|
||||
return 0, fmt.Errorf("wrong tx index key length, expect: %d, got: %d", TxIndexKeyLength, len(key))
|
||||
}
|
||||
|
||||
return int64(sdk.BigEndianToUint64(key[1:9])), nil
|
||||
}
|
189
indexer/kv_indexer_test.go
Normal file
189
indexer/kv_indexer_test.go
Normal file
@ -0,0 +1,189 @@
|
||||
package indexer_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/cerc-io/laconicd/app"
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
evmenc "github.com/cerc-io/laconicd/encoding"
|
||||
"github.com/cerc-io/laconicd/indexer"
|
||||
"github.com/cerc-io/laconicd/tests"
|
||||
"github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
func TestKVIndexer(t *testing.T) {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
require.NoError(t, err)
|
||||
from := common.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
signer := tests.NewSigner(priv)
|
||||
ethSigner := ethtypes.LatestSignerForChainID(nil)
|
||||
|
||||
to := common.BigToAddress(big.NewInt(1))
|
||||
tx := types.NewTx(
|
||||
nil, 0, &to, big.NewInt(1000), 21000, nil, nil, nil, nil, nil,
|
||||
)
|
||||
tx.From = from.Hex()
|
||||
require.NoError(t, tx.Sign(ethSigner, signer))
|
||||
txHash := tx.AsTransaction().Hash()
|
||||
|
||||
encodingConfig := MakeEncodingConfig()
|
||||
clientCtx := client.Context{}.WithTxConfig(encodingConfig.TxConfig).WithCodec(encodingConfig.Codec)
|
||||
|
||||
// build cosmos-sdk wrapper tx
|
||||
tmTx, err := tx.BuildTx(clientCtx.TxConfig.NewTxBuilder(), "aphoton")
|
||||
require.NoError(t, err)
|
||||
txBz, err := clientCtx.TxConfig.TxEncoder()(tmTx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// build an invalid wrapper tx
|
||||
builder := clientCtx.TxConfig.NewTxBuilder()
|
||||
require.NoError(t, builder.SetMsgs(tx))
|
||||
tmTx2 := builder.GetTx()
|
||||
txBz2, err := clientCtx.TxConfig.TxEncoder()(tmTx2)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
block *tmtypes.Block
|
||||
blockResult []*abci.ResponseDeliverTx
|
||||
expSuccess bool
|
||||
}{
|
||||
{
|
||||
"success, format 1",
|
||||
&tmtypes.Block{Header: tmtypes.Header{Height: 1}, Data: tmtypes.Data{Txs: []tmtypes.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: types.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success, format 2",
|
||||
&tmtypes.Block{Header: tmtypes.Header{Height: 1}, Data: tmtypes.Data{Txs: []tmtypes.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{
|
||||
{Type: types.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("ethereumTxHash"), Value: []byte(txHash.Hex())},
|
||||
{Key: []byte("txIndex"), Value: []byte("0")},
|
||||
}},
|
||||
{Type: types.EventTypeEthereumTx, Attributes: []abci.EventAttribute{
|
||||
{Key: []byte("amount"), Value: []byte("1000")},
|
||||
{Key: []byte("txGasUsed"), Value: []byte("21000")},
|
||||
{Key: []byte("txHash"), Value: []byte("14A84ED06282645EFBF080E0B7ED80D8D8D6A36337668A12B5F229F81CDD3F57")},
|
||||
{Key: []byte("recipient"), Value: []byte("0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7")},
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"success, exceed block gas limit",
|
||||
&tmtypes.Block{Header: tmtypes.Header{Height: 1}, Data: tmtypes.Data{Txs: []tmtypes.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 11,
|
||||
Log: "out of gas in location: block gas meter; gasWanted: 21000",
|
||||
Events: []abci.Event{},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"fail, failed eth tx",
|
||||
&tmtypes.Block{Header: tmtypes.Header{Height: 1}, Data: tmtypes.Data{Txs: []tmtypes.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 15,
|
||||
Log: "nonce mismatch",
|
||||
Events: []abci.Event{},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail, invalid events",
|
||||
&tmtypes.Block{Header: tmtypes.Header{Height: 1}, Data: tmtypes.Data{Txs: []tmtypes.Tx{txBz}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"fail, not eth tx",
|
||||
&tmtypes.Block{Header: tmtypes.Header{Height: 1}, Data: tmtypes.Data{Txs: []tmtypes.Tx{txBz2}}},
|
||||
[]*abci.ResponseDeliverTx{
|
||||
{
|
||||
Code: 0,
|
||||
Events: []abci.Event{},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
idxer := indexer.NewKVIndexer(db, tmlog.NewNopLogger(), clientCtx)
|
||||
|
||||
err = idxer.IndexBlock(tc.block, tc.blockResult)
|
||||
require.NoError(t, err)
|
||||
if !tc.expSuccess {
|
||||
first, err := idxer.FirstIndexedBlock()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(-1), first)
|
||||
|
||||
last, err := idxer.LastIndexedBlock()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(-1), last)
|
||||
} else {
|
||||
first, err := idxer.FirstIndexedBlock()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.block.Header.Height, first)
|
||||
|
||||
last, err := idxer.LastIndexedBlock()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.block.Header.Height, last)
|
||||
|
||||
res1, err := idxer.GetByTxHash(txHash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res1)
|
||||
res2, err := idxer.GetByBlockAndIndex(1, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, res1, res2)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// MakeEncodingConfig creates the EncodingConfig
|
||||
func MakeEncodingConfig() params.EncodingConfig {
|
||||
return evmenc.MakeConfig(app.ModuleBasics)
|
||||
}
|
6
init.bat
6
init.bat
@ -1,5 +1,5 @@
|
||||
|
||||
rem laconic compile on windows
|
||||
rem ethermint compile on windows
|
||||
rem install golang , gcc, sed for windows
|
||||
rem 1. install msys2 : https://www.msys2.org/
|
||||
rem 2. pacman -S mingw-w64-x86_64-toolchain
|
||||
@ -9,7 +9,7 @@ rem 3. add path C:\msys64\mingw64\bin
|
||||
rem C:\msys64\usr\bin
|
||||
|
||||
set KEY="mykey"
|
||||
set CHAINID="laconic_9000-1"
|
||||
set CHAINID="ethermint_9000-1"
|
||||
set MONIKER="localtestnet"
|
||||
set KEYRING="test"
|
||||
set KEYALGO="eth_secp256k1"
|
||||
@ -35,7 +35,7 @@ laconicd config chain-id %CHAINID%
|
||||
|
||||
laconicd keys add %KEY% --keyring-backend %KEYRING% --algo %KEYALGO%
|
||||
|
||||
rem Set moniker and chain-id for laconic (Moniker can be anything, chain-id must be an integer)
|
||||
rem Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
|
||||
laconicd init %MONIKER% --chain-id %CHAINID%
|
||||
|
||||
rem Change parameter token denominations to aphoton
|
||||
|
6
init.sh
6
init.sh
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
KEY="mykey"
|
||||
CHAINID="laconic_9000-1"
|
||||
CHAINID="ethermint_9000-1"
|
||||
MONIKER="localtestnet"
|
||||
KEYRING="test"
|
||||
KEYALGO="eth_secp256k1"
|
||||
@ -24,7 +24,7 @@ laconicd config chain-id $CHAINID
|
||||
# if $KEY exists it should be deleted
|
||||
laconicd keys add $KEY --keyring-backend $KEYRING --algo $KEYALGO
|
||||
|
||||
# Set moniker and chain-id for laconic (Moniker can be anything, chain-id must be an integer)
|
||||
# Set moniker and chain-id for Ethermint (Moniker can be anything, chain-id must be an integer)
|
||||
laconicd init $MONIKER --chain-id $CHAINID
|
||||
|
||||
# Change parameter token denominations to aphoton
|
||||
@ -111,4 +111,4 @@ if [[ $1 == "pending" ]]; then
|
||||
fi
|
||||
|
||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
||||
laconicd start --mode validator --pruning=nothing --evm.tracer=json $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable --gql-server --gql-playground
|
||||
laconicd start --pruning=nothing --evm.tracer=json $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --json-rpc.api eth,txpool,personal,net,debug,web3,miner --api.enable
|
||||
|
@ -1,4 +1,4 @@
|
||||
all:
|
||||
docker build --no-cache --tag laconicd/node ../.. -f laconicnode/Dockerfile
|
||||
docker build --no-cache --tag laconicd/node ../.. -f ethermintnode/Dockerfile
|
||||
|
||||
.PHONY: all
|
||||
|
@ -1,11 +1,9 @@
|
||||
FROM golang:alpine AS build-env
|
||||
FROM golang:stretch as build-env
|
||||
|
||||
# Install minimum necessary dependencies,
|
||||
ENV PACKAGES curl make git libc-dev bash gcc linux-headers eudev-dev python3
|
||||
RUN apk add --no-cache $PACKAGES
|
||||
|
||||
# Set up dependencies
|
||||
ENV PACKAGES git build-base
|
||||
# Install minimum necessary dependencies
|
||||
ENV PACKAGES curl make git libc-dev bash gcc
|
||||
RUN apt-get update && apt-get upgrade -y && \
|
||||
apt-get install -y $PACKAGES
|
||||
|
||||
# Set working directory for the build
|
||||
WORKDIR /go/src/github.com/cerc-io/laconicd
|
||||
@ -13,22 +11,21 @@ WORKDIR /go/src/github.com/cerc-io/laconicd
|
||||
# Add source files
|
||||
COPY . .
|
||||
|
||||
# build binary
|
||||
# RUN make build-linux
|
||||
RUN COSMOS_BUILD_OPTIONS=badgerdb make build
|
||||
|
||||
# build Ethermint
|
||||
RUN make build-linux
|
||||
|
||||
# Final image
|
||||
FROM alpine:edge
|
||||
FROM golang:1.18 as final
|
||||
|
||||
# Install ca-certificates
|
||||
RUN apk add --update ca-certificates jq
|
||||
WORKDIR /
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
# Copy over binaries from the build-env
|
||||
COPY --from=build-env /go/src/github.com/cerc-io/laconicd/build/laconicd /usr/bin/laconicd
|
||||
COPY --from=build-env /go/src/github.com/cerc-io/laconicd/build/laconicd /
|
||||
COPY --from=build-env /go/src/github.com/cerc-io/laconicd/scripts/start-docker.sh /
|
||||
|
||||
EXPOSE 26656 26657 1317 9090 8545 8546
|
||||
EXPOSE 26656 26657 1317 8545 8546
|
||||
|
||||
# Run ethermintd by default
|
||||
CMD ["laconicd","start","--gql-playground","--gql-server","--home","/laconic","--mode","validator","--db-backend","badgerdb"]
|
||||
# Run laconicd by default, omit entrypoint to ease using container with laconicd
|
||||
ENTRYPOINT ["/bin/bash", "-c"]
|
43
nix/default.nix
Normal file
43
nix/default.nix
Normal file
@ -0,0 +1,43 @@
|
||||
{ sources ? import ./sources.nix, system ? builtins.currentSystem, ... }:
|
||||
|
||||
import sources.nixpkgs {
|
||||
overlays = [
|
||||
(_: pkgs: {
|
||||
go = pkgs.go_1_18;
|
||||
go-ethereum = pkgs.callPackage ./go-ethereum.nix {
|
||||
inherit (pkgs.darwin) libobjc;
|
||||
inherit (pkgs.darwin.apple_sdk.frameworks) IOKit;
|
||||
buildGoModule = pkgs.buildGo118Module;
|
||||
};
|
||||
}) # update to a version that supports eip-1559
|
||||
# https://github.com/NixOS/nixpkgs/pull/179622
|
||||
(import ./go_1_18_overlay.nix)
|
||||
(final: prev:
|
||||
(import "${sources.gomod2nix}/overlay.nix")
|
||||
(final // {
|
||||
inherit (final.darwin.apple_sdk_11_0) callPackage;
|
||||
})
|
||||
prev)
|
||||
(pkgs: _:
|
||||
import ./scripts.nix {
|
||||
inherit pkgs;
|
||||
config = {
|
||||
ethermint-config = ../scripts/ethermint-devnet.yaml;
|
||||
geth-genesis = ../scripts/geth-genesis.json;
|
||||
dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; };
|
||||
};
|
||||
})
|
||||
(_: pkgs: { test-env = import ./testenv.nix { inherit pkgs; }; })
|
||||
(_: pkgs: {
|
||||
cosmovisor = pkgs.buildGo118Module rec {
|
||||
name = "cosmovisor";
|
||||
src = sources.cosmos-sdk + "/cosmovisor";
|
||||
subPackages = [ "./cmd/cosmovisor" ];
|
||||
vendorSha256 = "sha256-OAXWrwpartjgSP7oeNvDJ7cTR9lyYVNhEM8HUnv3acE=";
|
||||
doCheck = false;
|
||||
};
|
||||
})
|
||||
];
|
||||
config = { };
|
||||
inherit system;
|
||||
}
|
60
nix/go-ethereum.nix
Normal file
60
nix/go-ethereum.nix
Normal file
@ -0,0 +1,60 @@
|
||||
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit }:
|
||||
|
||||
let
|
||||
# A list of binaries to put into separate outputs
|
||||
bins = [
|
||||
"geth"
|
||||
"clef"
|
||||
];
|
||||
|
||||
in
|
||||
buildGoModule rec {
|
||||
pname = "go-ethereum";
|
||||
version = "1.10.19";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ethereum";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "0f6n9rg42ph47mvykc9f0lf99yzwqy4jm7mlzyks4l6i6fl1g3q1";
|
||||
};
|
||||
|
||||
vendorSha256 = "1s5yfpk2yn7f3zwjl2fdrh6c63ki2b8rlmnlss27yxibsidaj0yd";
|
||||
|
||||
doCheck = false;
|
||||
|
||||
outputs = [ "out" ] ++ bins;
|
||||
|
||||
# Move binaries to separate outputs and symlink them back to $out
|
||||
postInstall = lib.concatStringsSep "\n" (
|
||||
builtins.map (bin: "mkdir -p \$${bin}/bin && mv $out/bin/${bin} \$${bin}/bin/ && ln -s \$${bin}/bin/${bin} $out/bin/") bins
|
||||
);
|
||||
|
||||
subPackages = [
|
||||
"cmd/abidump"
|
||||
"cmd/abigen"
|
||||
"cmd/bootnode"
|
||||
"cmd/checkpoint-admin"
|
||||
"cmd/clef"
|
||||
"cmd/devp2p"
|
||||
"cmd/ethkey"
|
||||
"cmd/evm"
|
||||
"cmd/faucet"
|
||||
"cmd/geth"
|
||||
"cmd/p2psim"
|
||||
"cmd/puppeth"
|
||||
"cmd/rlpdump"
|
||||
"cmd/utils"
|
||||
];
|
||||
|
||||
# Fix for usb-related segmentation faults on darwin
|
||||
propagatedBuildInputs =
|
||||
lib.optionals stdenv.isDarwin [ libobjc IOKit ];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://geth.ethereum.org/";
|
||||
description = "Official golang implementation of the Ethereum protocol";
|
||||
license = with licenses; [ lgpl3Plus gpl3Plus ];
|
||||
maintainers = with maintainers; [ adisbladis lionello RaghavSood ];
|
||||
};
|
||||
}
|
10
nix/go_1_18_overlay.nix
Normal file
10
nix/go_1_18_overlay.nix
Normal file
@ -0,0 +1,10 @@
|
||||
final: prev: {
|
||||
go_1_18 = prev.go_1_18.override ({
|
||||
inherit (final.darwin.apple_sdk_11_0.frameworks) Security Foundation;
|
||||
xcbuild = prev.xcbuild.override {
|
||||
inherit (final.darwin.apple_sdk_11_0) stdenv;
|
||||
};
|
||||
} // final.lib.optionalAttrs final.stdenv.isDarwin {
|
||||
inherit (final.darwin.apple_sdk_11_0) stdenv;
|
||||
});
|
||||
}
|
19
nix/scripts.nix
Normal file
19
nix/scripts.nix
Normal file
@ -0,0 +1,19 @@
|
||||
{ pkgs
|
||||
, config
|
||||
, ethermint ? (import ../. { inherit pkgs; })
|
||||
}: rec {
|
||||
start-ethermint = pkgs.writeShellScriptBin "start-ethermint" ''
|
||||
# rely on environment to provide laconicd
|
||||
export PATH=${pkgs.test-env}/bin:$PATH
|
||||
${../scripts/start-ethermint.sh} ${config.ethermint-config} ${config.dotenv} $@
|
||||
'';
|
||||
start-geth = pkgs.writeShellScriptBin "start-geth" ''
|
||||
export PATH=${pkgs.test-env}/bin:${pkgs.go-ethereum}/bin:$PATH
|
||||
source ${config.dotenv}
|
||||
${../scripts/start-geth.sh} ${config.geth-genesis} $@
|
||||
'';
|
||||
start-scripts = pkgs.symlinkJoin {
|
||||
name = "start-scripts";
|
||||
paths = [ start-ethermint start-geth ];
|
||||
};
|
||||
}
|
174
nix/sources.nix
Normal file
174
nix/sources.nix
Normal file
@ -0,0 +1,174 @@
|
||||
# This file has been generated by Niv.
|
||||
|
||||
let
|
||||
|
||||
#
|
||||
# The fetchers. fetch_<type> fetches specs of type <type>.
|
||||
#
|
||||
|
||||
fetch_file = pkgs: name: spec:
|
||||
let
|
||||
name' = sanitizeName name + "-src";
|
||||
in
|
||||
if spec.builtin or true then
|
||||
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
|
||||
else
|
||||
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
|
||||
|
||||
fetch_tarball = pkgs: name: spec:
|
||||
let
|
||||
name' = sanitizeName name + "-src";
|
||||
in
|
||||
if spec.builtin or true then
|
||||
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
|
||||
else
|
||||
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
|
||||
|
||||
fetch_git = name: spec:
|
||||
let
|
||||
ref =
|
||||
if spec ? ref then spec.ref else
|
||||
if spec ? branch then "refs/heads/${spec.branch}" else
|
||||
if spec ? tag then "refs/tags/${spec.tag}" else
|
||||
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
|
||||
in
|
||||
builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
|
||||
|
||||
fetch_local = spec: spec.path;
|
||||
|
||||
fetch_builtin-tarball = name: throw
|
||||
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
|
||||
$ niv modify ${name} -a type=tarball -a builtin=true'';
|
||||
|
||||
fetch_builtin-url = name: throw
|
||||
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
|
||||
$ niv modify ${name} -a type=file -a builtin=true'';
|
||||
|
||||
#
|
||||
# Various helpers
|
||||
#
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
|
||||
sanitizeName = name:
|
||||
(
|
||||
concatMapStrings (s: if builtins.isList s then "-" else s)
|
||||
(
|
||||
builtins.split "[^[:alnum:]+._?=-]+"
|
||||
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
|
||||
)
|
||||
);
|
||||
|
||||
# The set of packages used when specs are fetched using non-builtins.
|
||||
mkPkgs = sources: system:
|
||||
let
|
||||
sourcesNixpkgs =
|
||||
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
|
||||
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
|
||||
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
|
||||
in
|
||||
if builtins.hasAttr "nixpkgs" sources
|
||||
then sourcesNixpkgs
|
||||
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
|
||||
import <nixpkgs> {}
|
||||
else
|
||||
abort
|
||||
''
|
||||
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
|
||||
add a package called "nixpkgs" to your sources.json.
|
||||
'';
|
||||
|
||||
# The actual fetching function.
|
||||
fetch = pkgs: name: spec:
|
||||
|
||||
if ! builtins.hasAttr "type" spec then
|
||||
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
|
||||
else if spec.type == "file" then fetch_file pkgs name spec
|
||||
else if spec.type == "tarball" then fetch_tarball pkgs name spec
|
||||
else if spec.type == "git" then fetch_git name spec
|
||||
else if spec.type == "local" then fetch_local spec
|
||||
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
|
||||
else if spec.type == "builtin-url" then fetch_builtin-url name
|
||||
else
|
||||
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
|
||||
|
||||
# If the environment variable NIV_OVERRIDE_${name} is set, then use
|
||||
# the path directly as opposed to the fetched source.
|
||||
replace = name: drv:
|
||||
let
|
||||
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
|
||||
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
|
||||
in
|
||||
if ersatz == "" then drv else
|
||||
# this turns the string into an actual Nix path (for both absolute and
|
||||
# relative paths)
|
||||
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
|
||||
|
||||
# Ports of functions for older nix versions
|
||||
|
||||
# a Nix version of mapAttrs if the built-in doesn't exist
|
||||
mapAttrs = builtins.mapAttrs or (
|
||||
f: set: with builtins;
|
||||
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
|
||||
);
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
|
||||
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
|
||||
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
|
||||
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
|
||||
concatMapStrings = f: list: concatStrings (map f list);
|
||||
concatStrings = builtins.concatStringsSep "";
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
|
||||
optionalAttrs = cond: as: if cond then as else {};
|
||||
|
||||
# fetchTarball version that is compatible between all the versions of Nix
|
||||
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
|
||||
let
|
||||
inherit (builtins) lessThan nixVersion fetchTarball;
|
||||
in
|
||||
if lessThan nixVersion "1.12" then
|
||||
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
|
||||
else
|
||||
fetchTarball attrs;
|
||||
|
||||
# fetchurl version that is compatible between all the versions of Nix
|
||||
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
|
||||
let
|
||||
inherit (builtins) lessThan nixVersion fetchurl;
|
||||
in
|
||||
if lessThan nixVersion "1.12" then
|
||||
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
|
||||
else
|
||||
fetchurl attrs;
|
||||
|
||||
# Create the final "sources" from the config
|
||||
mkSources = config:
|
||||
mapAttrs (
|
||||
name: spec:
|
||||
if builtins.hasAttr "outPath" spec
|
||||
then abort
|
||||
"The values in sources.json should not have an 'outPath' attribute"
|
||||
else
|
||||
spec // { outPath = replace name (fetch config.pkgs name spec); }
|
||||
) config.sources;
|
||||
|
||||
# The "config" used by the fetchers
|
||||
mkConfig =
|
||||
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
|
||||
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
|
||||
, system ? builtins.currentSystem
|
||||
, pkgs ? mkPkgs sources system
|
||||
}: rec {
|
||||
# The sources, i.e. the attribute set of spec name to spec
|
||||
inherit sources;
|
||||
|
||||
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
|
||||
inherit pkgs;
|
||||
};
|
||||
|
||||
in
|
||||
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
|
18
nix/testenv.nix
Normal file
18
nix/testenv.nix
Normal file
@ -0,0 +1,18 @@
|
||||
{ pkgs }:
|
||||
pkgs.poetry2nix.mkPoetryEnv {
|
||||
projectDir = ../tests/integration_tests;
|
||||
python = pkgs.python39;
|
||||
overrides = pkgs.poetry2nix.overrides.withDefaults (self: super: {
|
||||
eth-bloom = super.eth-bloom.overridePythonAttrs {
|
||||
preConfigure = ''
|
||||
substituteInPlace setup.py --replace \'setuptools-markdown\' ""
|
||||
'';
|
||||
};
|
||||
|
||||
pystarport = super.pystarport.overridePythonAttrs (
|
||||
old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.poetry ];
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
@ -18,6 +18,9 @@ message Params {
|
||||
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
|
||||
// chain config defines the EVM chain configuration parameters
|
||||
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
|
||||
// Allow unprotected transactions defines if replay-protected (i.e non EIP155
|
||||
// signed) transactions can be executed on the state machine.
|
||||
bool allow_unprotected_txs = 6;
|
||||
}
|
||||
|
||||
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
|
||||
@ -101,10 +104,18 @@ message ChainConfig {
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"arrow_glacier_block\""
|
||||
];
|
||||
// EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in merge proceedings)
|
||||
string merge_fork_block = 19 [
|
||||
// DEPRECATED: merge fork block was deprecated: https://github.com/ethereum/go-ethereum/pull/24904
|
||||
reserved 19;
|
||||
reserved "merge_fork_block";
|
||||
// EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
|
||||
string gray_glacier_block = 20 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"merge_fork_block\""
|
||||
(gogoproto.moretags) = "yaml:\"gray_glacier_block\""
|
||||
];
|
||||
// Virtual fork after The Merge to use as a network splitter
|
||||
string merge_netsplit_block = 21 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"merge_netsplit_block\""
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,12 @@ service Query {
|
||||
rpc TraceBlock(QueryTraceBlockRequest) returns (QueryTraceBlockResponse) {
|
||||
option (google.api.http).get = "/ethermint/evm/v1/trace_block";
|
||||
}
|
||||
|
||||
// BaseFee queries the base fee of the parent block of the current block,
|
||||
// it's similar to feemarket module's method, but also checks london hardfork status.
|
||||
rpc BaseFee(QueryBaseFeeRequest) returns (QueryBaseFeeResponse) {
|
||||
option (google.api.http).get = "/ethermint/evm/v1/base_fee";
|
||||
}
|
||||
}
|
||||
|
||||
// QueryAccountRequest is the request type for the Query/Account RPC method.
|
||||
@ -227,8 +233,9 @@ message EstimateGasResponse {
|
||||
message QueryTraceTxRequest {
|
||||
// msgEthereumTx for the requested transaction
|
||||
MsgEthereumTx msg = 1;
|
||||
// transaction index
|
||||
uint64 tx_index = 2;
|
||||
// tx_index is not necessary anymore
|
||||
reserved 2;
|
||||
reserved "tx_index";
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
TraceConfig trace_config = 3;
|
||||
// the predecessor transactions included in the same block
|
||||
@ -266,3 +273,12 @@ message QueryTraceBlockRequest {
|
||||
message QueryTraceBlockResponse {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
// QueryBaseFeeRequest defines the request type for querying the EIP1559 base
|
||||
// fee.
|
||||
message QueryBaseFeeRequest {}
|
||||
|
||||
// BaseFeeResponse returns the EIP1559 base fee.
|
||||
message QueryBaseFeeResponse {
|
||||
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ message MsgEthereumTx {
|
||||
google.protobuf.Any data = 1;
|
||||
// caches
|
||||
|
||||
// encoded storage size of the transaction
|
||||
// DEPRECATED: encoded storage size of the transaction
|
||||
double size = 2 [(gogoproto.jsontag) = "-"];
|
||||
// transaction hash in hex format
|
||||
string hash = 3 [(gogoproto.moretags) = "rlp:\"-\""];
|
||||
@ -36,6 +36,8 @@ message MsgEthereumTx {
|
||||
}
|
||||
|
||||
// LegacyTx is the transaction data of regular Ethereum transactions.
|
||||
// NOTE: All non-protected transactions (i.e non EIP155 signed) will fail if the
|
||||
// AllowUnprotectedTxs parameter is disabled.
|
||||
message LegacyTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "TxData";
|
||||
|
@ -22,4 +22,11 @@ message Params {
|
||||
int64 enable_height = 5;
|
||||
// base fee for EIP-1559 blocks.
|
||||
string base_fee = 6 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
||||
}
|
||||
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
|
||||
string min_gas_price = 7
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||
// min gas denominator bounds the minimum gasUsed to be charged
|
||||
// to senders based on GasLimit
|
||||
string min_gas_multiplier = 8
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ message GenesisState {
|
||||
// Zero by default.
|
||||
reserved 2;
|
||||
reserved "base_fee";
|
||||
// block gas is the amount of gas used on the last block before the upgrade.
|
||||
// block gas is the amount of gas wanted on the last block before the upgrade.
|
||||
// Zero by default.
|
||||
uint64 block_gas = 3;
|
||||
}
|
@ -12,17 +12,17 @@ option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
|
||||
service Query {
|
||||
// Params queries the parameters of x/feemarket module.
|
||||
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
|
||||
option (google.api.http).get = "/feemarket/evm/v1/params";
|
||||
option (google.api.http).get = "/ethermint/feemarket/v1/params";
|
||||
}
|
||||
|
||||
// BaseFee queries the base fee of the parent block of the current block.
|
||||
rpc BaseFee(QueryBaseFeeRequest) returns (QueryBaseFeeResponse) {
|
||||
option (google.api.http).get = "/feemarket/evm/v1/base_fee";
|
||||
option (google.api.http).get = "/ethermint/feemarket/v1/base_fee";
|
||||
}
|
||||
|
||||
// BlockGas queries the gas used at a given block height
|
||||
rpc BlockGas(QueryBlockGasRequest) returns (QueryBlockGasResponse) {
|
||||
option (google.api.http).get = "/feemarket/evm/v1/block_gas";
|
||||
option (google.api.http).get = "/ethermint/feemarket/v1/block_gas";
|
||||
}
|
||||
}
|
||||
|
||||
|
13
proto/ethermint/types/v1/dynamic_fee.proto
Normal file
13
proto/ethermint/types/v1/dynamic_fee.proto
Normal file
@ -0,0 +1,13 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.types.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/cerc-io/laconicd/types";
|
||||
|
||||
// ExtensionOptionDynamicFeeTx is an extension option that specify the maxPrioPrice for cosmos tx
|
||||
message ExtensionOptionDynamicFeeTx {
|
||||
// the same as `max_priority_fee_per_gas` in eip-1559 spec
|
||||
string max_priority_price = 1
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
|
||||
}
|
29
proto/ethermint/types/v1/indexer.proto
Normal file
29
proto/ethermint/types/v1/indexer.proto
Normal file
@ -0,0 +1,29 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.types.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/cerc-io/laconicd/types";
|
||||
|
||||
// TxResult is the value stored in eth tx indexer
|
||||
message TxResult {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// the block height
|
||||
int64 height = 1;
|
||||
// cosmos tx index
|
||||
uint32 tx_index = 2;
|
||||
// the msg index in a batch tx
|
||||
uint32 msg_index = 3;
|
||||
|
||||
// eth tx index, the index in the list of valid eth tx in the block,
|
||||
// aka. the transaction list returned by eth_getBlock api.
|
||||
int32 eth_tx_index = 4;
|
||||
// if the eth tx is failed
|
||||
bool failed = 5;
|
||||
// gas used by tx, if exceeds block gas limit,
|
||||
// it's set to gas limit which is what's actually deducted by ante handler.
|
||||
uint64 gas_used = 6;
|
||||
// the cumulative gas used within current batch tx
|
||||
uint64 cumulative_gas_used = 7;
|
||||
}
|
@ -22,7 +22,7 @@ service Query {
|
||||
}
|
||||
|
||||
// GetBondById
|
||||
rpc GetBondById(QueryGetBondByIdRequest) returns (QueryGetBondByIdResponse) {
|
||||
rpc GetBondByID(QueryGetBondByIDRequest) returns (QueryGetBondByIDResponse) {
|
||||
option (google.api.http).get = "/vulcanize/bond/v1beta1/bonds/{id}";
|
||||
}
|
||||
|
||||
@ -58,13 +58,13 @@ message QueryGetBondsResponse {
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
}
|
||||
|
||||
// QueryGetBondById
|
||||
message QueryGetBondByIdRequest {
|
||||
// QueryGetBondByID
|
||||
message QueryGetBondByIDRequest {
|
||||
string id = 1 [(gogoproto.moretags) = "json:\"id\" yaml:\"id\""];
|
||||
}
|
||||
|
||||
// QueryGetBondByIdResponse returns QueryGetBondById query response
|
||||
message QueryGetBondByIdResponse {
|
||||
// QueryGetBondByIDResponse returns QueryGetBondByID query response
|
||||
message QueryGetBondByIDResponse {
|
||||
Bond bond = 1 [(gogoproto.moretags) = "json:\"bond\" yaml:\"bond\""];
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,11 @@ service Query {
|
||||
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/records";
|
||||
}
|
||||
// Get record by id
|
||||
rpc GetRecord(QueryRecordByIdRequest) returns (QueryRecordByIdResponse) {
|
||||
rpc GetRecord(QueryRecordByIDRequest) returns (QueryRecordByIDResponse) {
|
||||
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/records/{id}";
|
||||
}
|
||||
// Get records by bond id
|
||||
rpc GetRecordByBondId(QueryRecordByBondIdRequest) returns (QueryRecordByBondIdResponse) {
|
||||
rpc GetRecordByBondID(QueryRecordByBondIDRequest) returns (QueryRecordByBondIDResponse) {
|
||||
option (google.api.http).get = "/vulcanize/nameservice/v1beta1/records-by-bond-id/{id}";
|
||||
}
|
||||
// Get nameservice module balance
|
||||
@ -98,25 +98,25 @@ message QueryListRecordsResponse {
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
}
|
||||
|
||||
// QueryRecordByIdRequest is request type for nameservice records by id
|
||||
message QueryRecordByIdRequest {
|
||||
// QueryRecordByIDRequest is request type for nameservice records by id
|
||||
message QueryRecordByIDRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
// QueryRecordByIdResponse is response type for nameservice records by id
|
||||
message QueryRecordByIdResponse {
|
||||
// QueryRecordByIDResponse is response type for nameservice records by id
|
||||
message QueryRecordByIDResponse {
|
||||
Record record = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
// QueryRecordByBondIdRequest is request type for get the records by bond-id
|
||||
message QueryRecordByBondIdRequest {
|
||||
message QueryRecordByBondIDRequest {
|
||||
string id = 1;
|
||||
// pagination defines an optional pagination for the request.
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 2;
|
||||
}
|
||||
|
||||
// QueryRecordByBondIdResponse is response type for records list by bond-id
|
||||
message QueryRecordByBondIdResponse {
|
||||
message QueryRecordByBondIDResponse {
|
||||
repeated Record records = 1 [(gogoproto.nullable) = false];
|
||||
// pagination defines the pagination in the response.
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
|
111
rpc/apis.go
111
rpc/apis.go
@ -10,22 +10,28 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/backend"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/debug"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/eth"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/eth/filters"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/miner"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/net"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/personal"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/txpool"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/namespaces/web3"
|
||||
"github.com/cerc-io/laconicd/rpc/ethereum/types"
|
||||
"github.com/cerc-io/laconicd/rpc/backend"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/debug"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/eth"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/eth/filters"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/miner"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/net"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/personal"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/txpool"
|
||||
"github.com/cerc-io/laconicd/rpc/namespaces/ethereum/web3"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
|
||||
)
|
||||
|
||||
// RPC namespaces and API version
|
||||
const (
|
||||
// Cosmos namespaces
|
||||
|
||||
CosmosNamespace = "cosmos"
|
||||
|
||||
// Ethereum namespaces
|
||||
|
||||
Web3Namespace = "web3"
|
||||
EthNamespace = "eth"
|
||||
PersonalNamespace = "personal"
|
||||
@ -37,22 +43,32 @@ const (
|
||||
apiVersion = "1.0"
|
||||
)
|
||||
|
||||
// APICreator creates the json-rpc api implementations.
|
||||
type APICreator = func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API
|
||||
// APICreator creates the JSON-RPC API implementations.
|
||||
type APICreator = func(
|
||||
ctx *server.Context,
|
||||
clientCtx client.Context,
|
||||
tendermintWebsocketClient *rpcclient.WSClient,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
) []rpc.API
|
||||
|
||||
// apiCreators defines the json-rpc api namespaces.
|
||||
// apiCreators defines the JSON-RPC API namespaces.
|
||||
var apiCreators map[string]APICreator
|
||||
|
||||
func init() {
|
||||
apiCreators = map[string]APICreator{
|
||||
EthNamespace: func(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient) []rpc.API {
|
||||
nonceLock := new(types.AddrLocker)
|
||||
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||
EthNamespace: func(ctx *server.Context,
|
||||
clientCtx client.Context,
|
||||
tmWSClient *rpcclient.WSClient,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
) []rpc.API {
|
||||
evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer)
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: EthNamespace,
|
||||
Version: apiVersion,
|
||||
Service: eth.NewPublicAPI(ctx.Logger, clientCtx, evmBackend, nonceLock),
|
||||
Service: eth.NewPublicAPI(ctx.Logger, evmBackend),
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
@ -63,7 +79,7 @@ func init() {
|
||||
},
|
||||
}
|
||||
},
|
||||
Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API {
|
||||
Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient, bool, ethermint.EVMTxIndexer) []rpc.API {
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: Web3Namespace,
|
||||
@ -73,7 +89,7 @@ func init() {
|
||||
},
|
||||
}
|
||||
},
|
||||
NetNamespace: func(_ *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||
NetNamespace: func(_ *server.Context, clientCtx client.Context, _ *rpcclient.WSClient, _ bool, _ ethermint.EVMTxIndexer) []rpc.API {
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: NetNamespace,
|
||||
@ -83,18 +99,23 @@ func init() {
|
||||
},
|
||||
}
|
||||
},
|
||||
PersonalNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||
PersonalNamespace: func(ctx *server.Context,
|
||||
clientCtx client.Context,
|
||||
_ *rpcclient.WSClient,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
) []rpc.API {
|
||||
evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer)
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: PersonalNamespace,
|
||||
Version: apiVersion,
|
||||
Service: personal.NewAPI(ctx.Logger, clientCtx, evmBackend),
|
||||
Service: personal.NewAPI(ctx.Logger, evmBackend),
|
||||
Public: false,
|
||||
},
|
||||
}
|
||||
},
|
||||
TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||
TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient, _ bool, _ ethermint.EVMTxIndexer) []rpc.API {
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: TxPoolNamespace,
|
||||
@ -104,24 +125,34 @@ func init() {
|
||||
},
|
||||
}
|
||||
},
|
||||
DebugNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||
DebugNamespace: func(ctx *server.Context,
|
||||
clientCtx client.Context,
|
||||
_ *rpcclient.WSClient,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
) []rpc.API {
|
||||
evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer)
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: DebugNamespace,
|
||||
Version: apiVersion,
|
||||
Service: debug.NewAPI(ctx, evmBackend, clientCtx),
|
||||
Service: debug.NewAPI(ctx, evmBackend),
|
||||
Public: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
MinerNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||
MinerNamespace: func(ctx *server.Context,
|
||||
clientCtx client.Context,
|
||||
_ *rpcclient.WSClient,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
) []rpc.API {
|
||||
evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer)
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: MinerNamespace,
|
||||
Version: apiVersion,
|
||||
Service: miner.NewPrivateAPI(ctx, clientCtx, evmBackend),
|
||||
Service: miner.NewPrivateAPI(ctx, evmBackend),
|
||||
Public: false,
|
||||
},
|
||||
}
|
||||
@ -129,25 +160,19 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func unique(intSlice []string) []string {
|
||||
keys := make(map[string]bool)
|
||||
var list []string
|
||||
for _, entry := range intSlice {
|
||||
if _, value := keys[entry]; !value {
|
||||
keys[entry] = true
|
||||
list = append(list, entry)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// GetRPCAPIs returns the list of all APIs
|
||||
func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API {
|
||||
func GetRPCAPIs(ctx *server.Context,
|
||||
clientCtx client.Context,
|
||||
tmWSClient *rpcclient.WSClient,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
selectedAPIs []string,
|
||||
) []rpc.API {
|
||||
var apis []rpc.API
|
||||
|
||||
for _, ns := range selectedAPIs {
|
||||
if creator, ok := apiCreators[ns]; ok {
|
||||
apis = append(apis, creator(ctx, clientCtx, tmWSClient)...)
|
||||
apis = append(apis, creator(ctx, clientCtx, tmWSClient, allowUnprotectedTxs, indexer)...)
|
||||
} else {
|
||||
ctx.Logger.Error("invalid namespace value", "namespace", ns)
|
||||
}
|
||||
|
206
rpc/backend/account_info.go
Normal file
206
rpc/backend/account_info.go
Normal file
@ -0,0 +1,206 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GetCode returns the contract code at the given address and block number.
|
||||
func (b *Backend) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||
blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := &evmtypes.QueryCodeRequest{
|
||||
Address: address.String(),
|
||||
}
|
||||
|
||||
res, err := b.queryClient.Code(rpctypes.ContextWithHeight(blockNum.Int64()), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.Code, nil
|
||||
}
|
||||
|
||||
// GetProof returns an account object with proof and any storage proofs
|
||||
func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccountResult, error) {
|
||||
blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
height := blockNum.Int64()
|
||||
_, err = b.TendermintBlockByNumber(blockNum)
|
||||
if err != nil {
|
||||
// the error message imitates geth behavior
|
||||
return nil, errors.New("header not found")
|
||||
}
|
||||
ctx := rpctypes.ContextWithHeight(height)
|
||||
|
||||
// if the height is equal to zero, meaning the query condition of the block is either "pending" or "latest"
|
||||
if height == 0 {
|
||||
bn, err := b.BlockNumber()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if bn > math.MaxInt64 {
|
||||
return nil, fmt.Errorf("not able to query block number greater than MaxInt64")
|
||||
}
|
||||
|
||||
height = int64(bn)
|
||||
}
|
||||
|
||||
clientCtx := b.clientCtx.WithHeight(height)
|
||||
|
||||
// query storage proofs
|
||||
storageProofs := make([]rpctypes.StorageResult, len(storageKeys))
|
||||
|
||||
for i, key := range storageKeys {
|
||||
hexKey := common.HexToHash(key)
|
||||
valueBz, proof, err := b.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for proof
|
||||
var proofStr string
|
||||
if proof != nil {
|
||||
proofStr = proof.String()
|
||||
}
|
||||
|
||||
storageProofs[i] = rpctypes.StorageResult{
|
||||
Key: key,
|
||||
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
|
||||
Proof: []string{proofStr},
|
||||
}
|
||||
}
|
||||
|
||||
// query EVM account
|
||||
req := &evmtypes.QueryAccountRequest{
|
||||
Address: address.String(),
|
||||
}
|
||||
|
||||
res, err := b.queryClient.Account(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// query account proofs
|
||||
accountKey := authtypes.AddressStoreKey(sdk.AccAddress(address.Bytes()))
|
||||
_, proof, err := b.queryClient.GetProof(clientCtx, authtypes.StoreKey, accountKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for proof
|
||||
var accProofStr string
|
||||
if proof != nil {
|
||||
accProofStr = proof.String()
|
||||
}
|
||||
|
||||
balance, ok := sdkmath.NewIntFromString(res.Balance)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid balance")
|
||||
}
|
||||
|
||||
return &rpctypes.AccountResult{
|
||||
Address: address,
|
||||
AccountProof: []string{accProofStr},
|
||||
Balance: (*hexutil.Big)(balance.BigInt()),
|
||||
CodeHash: common.HexToHash(res.CodeHash),
|
||||
Nonce: hexutil.Uint64(res.Nonce),
|
||||
StorageHash: common.Hash{}, // NOTE: Ethermint doesn't have a storage hash. TODO: implement?
|
||||
StorageProof: storageProofs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetStorageAt returns the contract storage at the given address, block number, and key.
|
||||
func (b *Backend) GetStorageAt(address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) {
|
||||
blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := &evmtypes.QueryStorageRequest{
|
||||
Address: address.String(),
|
||||
Key: key,
|
||||
}
|
||||
|
||||
res, err := b.queryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value := common.HexToHash(res.Value)
|
||||
return value.Bytes(), nil
|
||||
}
|
||||
|
||||
// GetBalance returns the provided account's balance up to the provided block number.
|
||||
func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Big, error) {
|
||||
blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := &evmtypes.QueryBalanceRequest{
|
||||
Address: address.String(),
|
||||
}
|
||||
|
||||
_, err = b.TendermintBlockByNumber(blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := b.queryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val, ok := sdkmath.NewIntFromString(res.Balance)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid balance")
|
||||
}
|
||||
|
||||
// balance can only be negative in case of pruned node
|
||||
if val.IsNegative() {
|
||||
return nil, errors.New("couldn't fetch balance. Node state is pruned")
|
||||
}
|
||||
|
||||
return (*hexutil.Big)(val.BigInt()), nil
|
||||
}
|
||||
|
||||
// GetTransactionCount returns the number of transactions at the given address up to the given block number.
|
||||
func (b *Backend) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) {
|
||||
// Get nonce (sequence) from account
|
||||
from := sdk.AccAddress(address.Bytes())
|
||||
accRet := b.clientCtx.AccountRetriever
|
||||
|
||||
err := accRet.EnsureExists(b.clientCtx, from)
|
||||
if err != nil {
|
||||
// account doesn't exist yet, return 0
|
||||
n := hexutil.Uint64(0)
|
||||
return &n, nil
|
||||
}
|
||||
|
||||
includePending := blockNum == rpctypes.EthPendingBlockNumber
|
||||
nonce, err := b.getAccountNonce(address, includePending, blockNum.Int64(), b.logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n := hexutil.Uint64(nonce)
|
||||
return &n, nil
|
||||
}
|
192
rpc/backend/backend.go
Normal file
192
rpc/backend/backend.go
Normal file
@ -0,0 +1,192 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/hd"
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
"github.com/cerc-io/laconicd/server/config"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"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"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
// BackendI implements the Cosmos and EVM backend.
|
||||
type BackendI interface { //nolint: revive
|
||||
CosmosBackend
|
||||
EVMBackend
|
||||
}
|
||||
|
||||
// CosmosBackend implements the functionality shared within cosmos namespaces
|
||||
// as defined by Wallet Connect V2: https://docs.walletconnect.com/2.0/json-rpc/cosmos.
|
||||
// Implemented by Backend.
|
||||
type CosmosBackend interface { // TODO: define
|
||||
// GetAccounts()
|
||||
// SignDirect()
|
||||
// SignAmino()
|
||||
}
|
||||
|
||||
// EVMBackend implements the functionality shared within ethereum namespaces
|
||||
// as defined by EIP-1474: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1474.md
|
||||
// Implemented by Backend.
|
||||
type EVMBackend interface {
|
||||
// Node specific queries
|
||||
Accounts() ([]common.Address, error)
|
||||
Syncing() (interface{}, error)
|
||||
SetEtherbase(etherbase common.Address) bool
|
||||
SetGasPrice(gasPrice hexutil.Big) bool
|
||||
ImportRawKey(privkey, password string) (common.Address, error)
|
||||
ListAccounts() ([]common.Address, error)
|
||||
NewMnemonic(uid string, language keyring.Language, hdPath, bip39Passphrase string, algo keyring.SignatureAlgo) (*keyring.Record, error)
|
||||
UnprotectedAllowed() bool
|
||||
RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection
|
||||
RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection
|
||||
RPCTxFeeCap() float64 // RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for send-transaction variants. The unit is ether.
|
||||
RPCMinGasPrice() int64
|
||||
|
||||
// Sign Tx
|
||||
Sign(address common.Address, data hexutil.Bytes) (hexutil.Bytes, error)
|
||||
SendTransaction(args evmtypes.TransactionArgs) (common.Hash, error)
|
||||
SignTypedData(address common.Address, typedData apitypes.TypedData) (hexutil.Bytes, error)
|
||||
|
||||
// Blocks Info
|
||||
BlockNumber() (hexutil.Uint64, error)
|
||||
GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
||||
GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
|
||||
GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint
|
||||
GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint
|
||||
TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error)
|
||||
TendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error)
|
||||
TendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error)
|
||||
BlockNumberFromTendermint(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error)
|
||||
BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.Int, error)
|
||||
EthMsgsFromTendermintBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx
|
||||
BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error)
|
||||
HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error)
|
||||
HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
|
||||
RPCBlockFromTendermintBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool) (map[string]interface{}, error)
|
||||
EthBlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Block, error)
|
||||
EthBlockFromTendermintBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error)
|
||||
|
||||
// Account Info
|
||||
GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error)
|
||||
GetBalance(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Big, error)
|
||||
GetStorageAt(address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error)
|
||||
GetProof(address common.Address, storageKeys []string, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccountResult, error)
|
||||
GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error)
|
||||
|
||||
// Chain Info
|
||||
ChainID() (*hexutil.Big, error)
|
||||
ChainConfig() *params.ChainConfig
|
||||
GlobalMinGasPrice() (sdk.Dec, error)
|
||||
BaseFee(blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error)
|
||||
CurrentHeader() *ethtypes.Header
|
||||
PendingTransactions() ([]*sdk.Tx, error)
|
||||
GetCoinbase() (sdk.AccAddress, error)
|
||||
FeeHistory(blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*rpctypes.FeeHistoryResult, error)
|
||||
SuggestGasTipCap(baseFee *big.Int) (*big.Int, error)
|
||||
|
||||
// Tx Info
|
||||
GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransaction, error)
|
||||
GetTxByEthHash(txHash common.Hash) (*ethermint.TxResult, error)
|
||||
GetTxByTxIndex(height int64, txIndex uint) (*ethermint.TxResult, error)
|
||||
GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error)
|
||||
GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error)
|
||||
GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error)
|
||||
GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error)
|
||||
|
||||
// Send Transaction
|
||||
Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error)
|
||||
SendRawTransaction(data hexutil.Bytes) (common.Hash, error)
|
||||
SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error)
|
||||
EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error)
|
||||
DoCall(args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber) (*evmtypes.MsgEthereumTxResponse, error)
|
||||
GasPrice() (*hexutil.Big, error)
|
||||
|
||||
// Filter API
|
||||
GetLogs(hash common.Hash) ([][]*ethtypes.Log, error)
|
||||
GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error)
|
||||
BloomStatus() (uint64, uint64)
|
||||
|
||||
// Tracing
|
||||
TraceTransaction(hash common.Hash, config *evmtypes.TraceConfig) (interface{}, error)
|
||||
TraceBlock(height rpctypes.BlockNumber, config *evmtypes.TraceConfig, block *tmrpctypes.ResultBlock) ([]*evmtypes.TxTraceResult, error)
|
||||
}
|
||||
|
||||
var _ BackendI = (*Backend)(nil)
|
||||
|
||||
var bAttributeKeyEthereumBloom = []byte(evmtypes.AttributeKeyEthereumBloom)
|
||||
|
||||
// Backend implements the BackendI interface
|
||||
type Backend struct {
|
||||
ctx context.Context
|
||||
clientCtx client.Context
|
||||
queryClient *rpctypes.QueryClient // gRPC query client
|
||||
logger log.Logger
|
||||
chainID *big.Int
|
||||
cfg config.Config
|
||||
allowUnprotectedTxs bool
|
||||
indexer ethermint.EVMTxIndexer
|
||||
}
|
||||
|
||||
// NewBackend creates a new Backend instance for cosmos and ethereum namespaces
|
||||
func NewBackend(
|
||||
ctx *server.Context,
|
||||
logger log.Logger,
|
||||
clientCtx client.Context,
|
||||
allowUnprotectedTxs bool,
|
||||
indexer ethermint.EVMTxIndexer,
|
||||
) *Backend {
|
||||
chainID, err := ethermint.ParseChainID(clientCtx.ChainID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
appConf, err := config.GetConfig(ctx.Viper)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
algos, _ := clientCtx.Keyring.SupportedAlgorithms()
|
||||
if !algos.Contains(hd.EthSecp256k1) {
|
||||
kr, err := keyring.New(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
clientCtx.KeyringDir,
|
||||
clientCtx.Input,
|
||||
clientCtx.Codec,
|
||||
hd.EthSecp256k1Option(),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
clientCtx = clientCtx.WithKeyring(kr)
|
||||
}
|
||||
|
||||
return &Backend{
|
||||
ctx: context.Background(),
|
||||
clientCtx: clientCtx,
|
||||
queryClient: rpctypes.NewQueryClient(clientCtx),
|
||||
logger: logger.With("module", "backend"),
|
||||
chainID: chainID,
|
||||
cfg: appConf,
|
||||
allowUnprotectedTxs: allowUnprotectedTxs,
|
||||
indexer: indexer,
|
||||
}
|
||||
}
|
147
rpc/backend/backend_suite_test.go
Normal file
147
rpc/backend/backend_suite_test.go
Normal file
@ -0,0 +1,147 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
|
||||
"github.com/cerc-io/laconicd/app"
|
||||
"github.com/cerc-io/laconicd/crypto/hd"
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
"github.com/cerc-io/laconicd/indexer"
|
||||
"github.com/cerc-io/laconicd/rpc/backend/mocks"
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
)
|
||||
|
||||
type BackendTestSuite struct {
|
||||
suite.Suite
|
||||
backend *Backend
|
||||
}
|
||||
|
||||
func TestBackendTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(BackendTestSuite))
|
||||
}
|
||||
|
||||
// SetupTest is executed before every BackendTestSuite test
|
||||
func (suite *BackendTestSuite) SetupTest() {
|
||||
ctx := server.NewDefaultContext()
|
||||
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
||||
|
||||
baseDir := suite.T().TempDir()
|
||||
nodeDirName := fmt.Sprintf("node")
|
||||
clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli")
|
||||
keyRing, err := suite.generateTestKeyring(clientDir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||
clientCtx := client.Context{}.WithChainID("ethermint_9000-1").
|
||||
WithHeight(1).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithKeyringDir(clientDir).
|
||||
WithKeyring(keyRing)
|
||||
|
||||
allowUnprotectedTxs := false
|
||||
|
||||
idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx)
|
||||
|
||||
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer)
|
||||
suite.backend.queryClient.QueryClient = mocks.NewQueryClient(suite.T())
|
||||
suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
|
||||
suite.backend.ctx = rpctypes.ContextWithHeight(1)
|
||||
}
|
||||
|
||||
// buildEthereumTx returns an example legacy Ethereum transaction
|
||||
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
|
||||
msgEthereumTx := evmtypes.NewTx(
|
||||
big.NewInt(1),
|
||||
uint64(0),
|
||||
&common.Address{},
|
||||
big.NewInt(0),
|
||||
100000,
|
||||
big.NewInt(1),
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
// A valid msg should have empty `From`
|
||||
msgEthereumTx.From = ""
|
||||
|
||||
txBuilder := suite.backend.clientCtx.TxConfig.NewTxBuilder()
|
||||
err := txBuilder.SetMsgs(msgEthereumTx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
bz, err := suite.backend.clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
suite.Require().NoError(err)
|
||||
return msgEthereumTx, bz
|
||||
}
|
||||
|
||||
// buildFormattedBlock returns a formatted block for testing
|
||||
func (suite *BackendTestSuite) buildFormattedBlock(
|
||||
blockRes *tmrpctypes.ResultBlockResults,
|
||||
resBlock *tmrpctypes.ResultBlock,
|
||||
fullTx bool,
|
||||
tx *evmtypes.MsgEthereumTx,
|
||||
validator sdk.AccAddress,
|
||||
baseFee *big.Int,
|
||||
) map[string]interface{} {
|
||||
header := resBlock.Block.Header
|
||||
gasLimit := int64(^uint32(0)) // for `MaxGas = -1` (DefaultConsensusParams)
|
||||
gasUsed := new(big.Int).SetUint64(uint64(blockRes.TxsResults[0].GasUsed))
|
||||
|
||||
root := common.Hash{}.Bytes()
|
||||
receipt := ethtypes.NewReceipt(root, false, gasUsed.Uint64())
|
||||
bloom := ethtypes.CreateBloom(ethtypes.Receipts{receipt})
|
||||
|
||||
ethRPCTxs := []interface{}{}
|
||||
if tx != nil {
|
||||
if fullTx {
|
||||
rpcTx, err := rpctypes.NewRPCTransaction(
|
||||
tx.AsTransaction(),
|
||||
common.BytesToHash(header.Hash()),
|
||||
uint64(header.Height),
|
||||
uint64(0),
|
||||
baseFee,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
ethRPCTxs = []interface{}{rpcTx}
|
||||
} else {
|
||||
ethRPCTxs = []interface{}{common.HexToHash(tx.Hash)}
|
||||
}
|
||||
}
|
||||
|
||||
return rpctypes.FormatBlock(
|
||||
header,
|
||||
resBlock.Block.Size(),
|
||||
gasLimit,
|
||||
gasUsed,
|
||||
ethRPCTxs,
|
||||
bloom,
|
||||
common.BytesToAddress(validator.Bytes()),
|
||||
baseFee,
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Keyring, error) {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||
return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...)
|
||||
}
|
491
rpc/backend/blocks.go
Normal file
491
rpc/backend/blocks.go
Normal file
@ -0,0 +1,491 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/pkg/errors"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
// BlockNumber returns the current block number in abci app state. Because abci
|
||||
// app state could lag behind from tendermint latest block, it's more stable for
|
||||
// the client to use the latest block number in abci app state than tendermint
|
||||
// rpc.
|
||||
func (b *Backend) BlockNumber() (hexutil.Uint64, error) {
|
||||
// do any grpc query, ignore the response and use the returned block height
|
||||
var header metadata.MD
|
||||
_, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header))
|
||||
if err != nil {
|
||||
return hexutil.Uint64(0), err
|
||||
}
|
||||
|
||||
blockHeightHeader := header.Get(grpctypes.GRPCBlockHeightHeader)
|
||||
if headerLen := len(blockHeightHeader); headerLen != 1 {
|
||||
return 0, fmt.Errorf("unexpected '%s' gRPC header length; got %d, expected: %d", grpctypes.GRPCBlockHeightHeader, headerLen, 1)
|
||||
}
|
||||
|
||||
height, err := strconv.ParseUint(blockHeightHeader[0], 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse block height: %w", err)
|
||||
}
|
||||
|
||||
return hexutil.Uint64(height), nil
|
||||
}
|
||||
|
||||
// GetBlockByNumber returns the JSON-RPC compatible Ethereum block identified by
|
||||
// block number. Depending on fullTx it either returns the full transaction
|
||||
// objects or if false only the hashes of the transactions.
|
||||
func (b *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
||||
resBlock, err := b.TendermintBlockByNumber(blockNum)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// return if requested block height is greater than the current one
|
||||
if resBlock == nil || resBlock.Block == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||
if err != nil {
|
||||
b.logger.Debug("failed to fetch block result from Tendermint", "height", blockNum, "error", err.Error())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
res, err := b.RPCBlockFromTendermintBlock(resBlock, blockRes, fullTx)
|
||||
if err != nil {
|
||||
b.logger.Debug("GetEthBlockFromTendermint failed", "height", blockNum, "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetBlockByHash returns the JSON-RPC compatible Ethereum block identified by
|
||||
// hash.
|
||||
func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
||||
resBlock, err := b.TendermintBlockByHash(hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resBlock == nil {
|
||||
// block not found
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||
if err != nil {
|
||||
b.logger.Debug("failed to fetch block result from Tendermint", "block-hash", hash.String(), "error", err.Error())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
res, err := b.RPCBlockFromTendermintBlock(resBlock, blockRes, fullTx)
|
||||
if err != nil {
|
||||
b.logger.Debug("GetEthBlockFromTendermint failed", "hash", hash, "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetBlockTransactionCountByHash returns the number of Ethereum transactions in
|
||||
// the block identified by hash.
|
||||
func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint {
|
||||
block, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes())
|
||||
if err != nil {
|
||||
b.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
if block.Block == nil {
|
||||
b.logger.Debug("block not found", "hash", hash.Hex())
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.GetBlockTransactionCount(block)
|
||||
}
|
||||
|
||||
// GetBlockTransactionCountByNumber returns the number of Ethereum transactions
|
||||
// in the block identified by number.
|
||||
func (b *Backend) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint {
|
||||
block, err := b.TendermintBlockByNumber(blockNum)
|
||||
if err != nil {
|
||||
b.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
if block.Block == nil {
|
||||
b.logger.Debug("block not found", "height", blockNum.Int64())
|
||||
return nil
|
||||
}
|
||||
|
||||
return b.GetBlockTransactionCount(block)
|
||||
}
|
||||
|
||||
// GetBlockTransactionCount returns the number of Ethereum transactions in a
|
||||
// given block.
|
||||
func (b *Backend) GetBlockTransactionCount(block *tmrpctypes.ResultBlock) *hexutil.Uint {
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ethMsgs := b.EthMsgsFromTendermintBlock(block, blockRes)
|
||||
n := hexutil.Uint(len(ethMsgs))
|
||||
return &n
|
||||
}
|
||||
|
||||
// TendermintBlockByNumber returns a Tendermint-formatted block for a given
|
||||
// block number
|
||||
func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error) {
|
||||
height := blockNum.Int64()
|
||||
if height <= 0 {
|
||||
// fetch the latest block number from the app state, more accurate than the tendermint block store state.
|
||||
n, err := b.BlockNumber()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
height = int64(n)
|
||||
}
|
||||
resBlock, err := b.clientCtx.Client.Block(b.ctx, &height)
|
||||
if err != nil {
|
||||
b.logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resBlock.Block == nil {
|
||||
b.logger.Debug("TendermintBlockByNumber block not found", "height", height)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return resBlock, nil
|
||||
}
|
||||
|
||||
// TendermintBlockResultByNumber returns a Tendermint-formatted block result
|
||||
// by block number
|
||||
func (b *Backend) TendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) {
|
||||
return b.clientCtx.Client.BlockResults(b.ctx, height)
|
||||
}
|
||||
|
||||
// TendermintBlockByHash returns a Tendermint-formatted block by block number
|
||||
func (b *Backend) TendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) {
|
||||
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes())
|
||||
if err != nil {
|
||||
b.logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resBlock == nil || resBlock.Block == nil {
|
||||
b.logger.Debug("TendermintBlockByHash block not found", "blockHash", blockHash.Hex())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return resBlock, nil
|
||||
}
|
||||
|
||||
// BlockNumberFromTendermint returns the BlockNumber from BlockNumberOrHash
|
||||
func (b *Backend) BlockNumberFromTendermint(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error) {
|
||||
switch {
|
||||
case blockNrOrHash.BlockHash == nil && blockNrOrHash.BlockNumber == nil:
|
||||
return rpctypes.EthEarliestBlockNumber, fmt.Errorf("types BlockHash and BlockNumber cannot be both nil")
|
||||
case blockNrOrHash.BlockHash != nil:
|
||||
blockNumber, err := b.BlockNumberFromTendermintByHash(*blockNrOrHash.BlockHash)
|
||||
if err != nil {
|
||||
return rpctypes.EthEarliestBlockNumber, err
|
||||
}
|
||||
return rpctypes.NewBlockNumber(blockNumber), nil
|
||||
case blockNrOrHash.BlockNumber != nil:
|
||||
return *blockNrOrHash.BlockNumber, nil
|
||||
default:
|
||||
return rpctypes.EthEarliestBlockNumber, nil
|
||||
}
|
||||
}
|
||||
|
||||
// BlockNumberFromTendermintByHash returns the block height of given block hash
|
||||
func (b *Backend) BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.Int, error) {
|
||||
resBlock, err := b.TendermintBlockByHash(blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resBlock == nil {
|
||||
return nil, errors.Errorf("block not found for hash %s", blockHash.Hex())
|
||||
}
|
||||
return big.NewInt(resBlock.Block.Height), nil
|
||||
}
|
||||
|
||||
// EthMsgsFromTendermintBlock returns all real MsgEthereumTxs from a
|
||||
// Tendermint block. It also ensures consistency over the correct txs indexes
|
||||
// across RPC endpoints
|
||||
func (b *Backend) EthMsgsFromTendermintBlock(
|
||||
resBlock *tmrpctypes.ResultBlock,
|
||||
blockRes *tmrpctypes.ResultBlockResults,
|
||||
) []*evmtypes.MsgEthereumTx {
|
||||
var result []*evmtypes.MsgEthereumTx
|
||||
block := resBlock.Block
|
||||
|
||||
txResults := blockRes.TxsResults
|
||||
|
||||
for i, tx := range block.Txs {
|
||||
// Check if tx exists on EVM by cross checking with blockResults:
|
||||
// - Include unsuccessful tx that exceeds block gas limit
|
||||
// - Exclude unsuccessful tx with any other error but ExceedBlockGasLimit
|
||||
if !rpctypes.TxSuccessOrExceedsBlockGasLimit(txResults[i]) {
|
||||
b.logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash()))
|
||||
continue
|
||||
}
|
||||
|
||||
tx, err := b.clientCtx.TxConfig.TxDecoder()(tx)
|
||||
if err != nil {
|
||||
b.logger.Debug("failed to decode transaction in block", "height", block.Height, "error", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
ethMsg.Hash = ethMsg.AsTransaction().Hash().Hex()
|
||||
result = append(result, ethMsg)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// HeaderByNumber returns the block header identified by height.
|
||||
func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) {
|
||||
resBlock, err := b.TendermintBlockByNumber(blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resBlock == nil {
|
||||
return nil, errors.Errorf("block not found for height %d", blockNum)
|
||||
}
|
||||
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height)
|
||||
}
|
||||
|
||||
bloom, err := b.BlockBloom(blockRes)
|
||||
if err != nil {
|
||||
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height)
|
||||
}
|
||||
|
||||
baseFee, err := b.BaseFee(blockRes)
|
||||
if err != nil {
|
||||
// handle the error for pruned node.
|
||||
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err)
|
||||
}
|
||||
|
||||
ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee)
|
||||
return ethHeader, nil
|
||||
}
|
||||
|
||||
// HeaderByHash returns the block header identified by hash.
|
||||
func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) {
|
||||
resBlock, err := b.TendermintBlockByHash(blockHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resBlock == nil {
|
||||
return nil, errors.Errorf("block not found for hash %s", blockHash.Hex())
|
||||
}
|
||||
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("block result not found for height %d", resBlock.Block.Height)
|
||||
}
|
||||
|
||||
bloom, err := b.BlockBloom(blockRes)
|
||||
if err != nil {
|
||||
b.logger.Debug("HeaderByHash BlockBloom failed", "height", resBlock.Block.Height)
|
||||
}
|
||||
|
||||
baseFee, err := b.BaseFee(blockRes)
|
||||
if err != nil {
|
||||
// handle the error for pruned node.
|
||||
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err)
|
||||
}
|
||||
|
||||
ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee)
|
||||
return ethHeader, nil
|
||||
}
|
||||
|
||||
// BlockBloom query block bloom filter from block results
|
||||
func (b *Backend) BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) {
|
||||
for _, event := range blockRes.EndBlockEvents {
|
||||
if event.Type != evmtypes.EventTypeBlockBloom {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, attr := range event.Attributes {
|
||||
if bytes.Equal(attr.Key, bAttributeKeyEthereumBloom) {
|
||||
return ethtypes.BytesToBloom(attr.Value), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return ethtypes.Bloom{}, errors.New("block bloom event is not found")
|
||||
}
|
||||
|
||||
// RPCBlockFromTendermintBlock returns a JSON-RPC compatible Ethereum block from a
|
||||
// given Tendermint block and its block result.
|
||||
func (b *Backend) RPCBlockFromTendermintBlock(
|
||||
resBlock *tmrpctypes.ResultBlock,
|
||||
blockRes *tmrpctypes.ResultBlockResults,
|
||||
fullTx bool,
|
||||
) (map[string]interface{}, error) {
|
||||
ethRPCTxs := []interface{}{}
|
||||
block := resBlock.Block
|
||||
|
||||
baseFee, err := b.BaseFee(blockRes)
|
||||
if err != nil {
|
||||
// handle the error for pruned node.
|
||||
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Height, "error", err)
|
||||
}
|
||||
|
||||
msgs := b.EthMsgsFromTendermintBlock(resBlock, blockRes)
|
||||
for txIndex, ethMsg := range msgs {
|
||||
if !fullTx {
|
||||
hash := common.HexToHash(ethMsg.Hash)
|
||||
ethRPCTxs = append(ethRPCTxs, hash)
|
||||
continue
|
||||
}
|
||||
|
||||
tx := ethMsg.AsTransaction()
|
||||
rpcTx, err := rpctypes.NewRPCTransaction(
|
||||
tx,
|
||||
common.BytesToHash(block.Hash()),
|
||||
uint64(block.Height),
|
||||
uint64(txIndex),
|
||||
baseFee,
|
||||
)
|
||||
if err != nil {
|
||||
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
|
||||
continue
|
||||
}
|
||||
ethRPCTxs = append(ethRPCTxs, rpcTx)
|
||||
}
|
||||
|
||||
bloom, err := b.BlockBloom(blockRes)
|
||||
if err != nil {
|
||||
b.logger.Debug("failed to query BlockBloom", "height", block.Height, "error", err.Error())
|
||||
}
|
||||
|
||||
req := &evmtypes.QueryValidatorAccountRequest{
|
||||
ConsAddress: sdk.ConsAddress(block.Header.ProposerAddress).String(),
|
||||
}
|
||||
|
||||
var validatorAccAddr sdk.AccAddress
|
||||
|
||||
ctx := rpctypes.ContextWithHeight(block.Height)
|
||||
res, err := b.queryClient.ValidatorAccount(ctx, req)
|
||||
if err != nil {
|
||||
b.logger.Debug(
|
||||
"failed to query validator operator address",
|
||||
"height", block.Height,
|
||||
"cons-address", req.ConsAddress,
|
||||
"error", err.Error(),
|
||||
)
|
||||
// use zero address as the validator operator address
|
||||
validatorAccAddr = sdk.AccAddress(common.Address{}.Bytes())
|
||||
} else {
|
||||
validatorAccAddr, err = sdk.AccAddressFromBech32(res.AccountAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
validatorAddr := common.BytesToAddress(validatorAccAddr)
|
||||
|
||||
gasLimit, err := rpctypes.BlockMaxGasFromConsensusParams(ctx, b.clientCtx, block.Height)
|
||||
if err != nil {
|
||||
b.logger.Error("failed to query consensus params", "error", err.Error())
|
||||
}
|
||||
|
||||
gasUsed := uint64(0)
|
||||
|
||||
for _, txsResult := range blockRes.TxsResults {
|
||||
// workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832
|
||||
if ShouldIgnoreGasUsed(txsResult) {
|
||||
// block gas limit has exceeded, other txs must have failed with same reason.
|
||||
break
|
||||
}
|
||||
gasUsed += uint64(txsResult.GetGasUsed())
|
||||
}
|
||||
|
||||
formattedBlock := rpctypes.FormatBlock(
|
||||
block.Header, block.Size(),
|
||||
gasLimit, new(big.Int).SetUint64(gasUsed),
|
||||
ethRPCTxs, bloom, validatorAddr, baseFee,
|
||||
)
|
||||
return formattedBlock, nil
|
||||
}
|
||||
|
||||
// EthBlockByNumber returns the Ethereum Block identified by number.
|
||||
func (b *Backend) EthBlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Block, error) {
|
||||
resBlock, err := b.TendermintBlockByNumber(blockNum)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resBlock == nil {
|
||||
// block not found
|
||||
return nil, fmt.Errorf("block not found for height %d", blockNum)
|
||||
}
|
||||
|
||||
blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height)
|
||||
}
|
||||
|
||||
return b.EthBlockFromTendermintBlock(resBlock, blockRes)
|
||||
}
|
||||
|
||||
// EthBlockFromTendermintBlock returns an Ethereum Block type from Tendermint block
|
||||
// EthBlockFromTendermintBlock
|
||||
func (b *Backend) EthBlockFromTendermintBlock(
|
||||
resBlock *tmrpctypes.ResultBlock,
|
||||
blockRes *tmrpctypes.ResultBlockResults,
|
||||
) (*ethtypes.Block, error) {
|
||||
block := resBlock.Block
|
||||
height := block.Height
|
||||
bloom, err := b.BlockBloom(blockRes)
|
||||
if err != nil {
|
||||
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", height)
|
||||
}
|
||||
|
||||
baseFee, err := b.BaseFee(blockRes)
|
||||
if err != nil {
|
||||
// handle error for pruned node and log
|
||||
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", height, "error", err)
|
||||
}
|
||||
|
||||
ethHeader := rpctypes.EthHeaderFromTendermint(block.Header, bloom, baseFee)
|
||||
msgs := b.EthMsgsFromTendermintBlock(resBlock, blockRes)
|
||||
|
||||
txs := make([]*ethtypes.Transaction, len(msgs))
|
||||
for i, ethMsg := range msgs {
|
||||
txs[i] = ethMsg.AsTransaction()
|
||||
}
|
||||
|
||||
// TODO: add tx receipts
|
||||
ethBlock := ethtypes.NewBlock(ethHeader, txs, nil, nil, trie.NewStackTrie(nil))
|
||||
return ethBlock, nil
|
||||
}
|
1611
rpc/backend/blocks_test.go
Normal file
1611
rpc/backend/blocks_test.go
Normal file
File diff suppressed because it is too large
Load Diff
398
rpc/backend/call_tx.go
Normal file
398
rpc/backend/call_tx.go
Normal file
@ -0,0 +1,398 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Resend accepts an existing transaction and a new gas price and limit. It will remove
|
||||
// the given transaction from the pool and reinsert it with the new gas price and limit.
|
||||
func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
|
||||
if args.Nonce == nil {
|
||||
return common.Hash{}, fmt.Errorf("missing transaction nonce in transaction spec")
|
||||
}
|
||||
|
||||
args, err := b.SetTxDefaults(args)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
// The signer used should always be the 'latest' known one because we expect
|
||||
// signers to be backwards-compatible with old transactions.
|
||||
eip155ChainID, err := ethermint.ParseChainID(b.clientCtx.ChainID)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
cfg := b.ChainConfig()
|
||||
if cfg == nil {
|
||||
cfg = evmtypes.DefaultChainConfig().EthereumConfig(eip155ChainID)
|
||||
}
|
||||
|
||||
signer := ethtypes.LatestSigner(cfg)
|
||||
|
||||
matchTx := args.ToTransaction().AsTransaction()
|
||||
|
||||
// Before replacing the old transaction, ensure the _new_ transaction fee is reasonable.
|
||||
price := matchTx.GasPrice()
|
||||
if gasPrice != nil {
|
||||
price = gasPrice.ToInt()
|
||||
}
|
||||
gas := matchTx.Gas()
|
||||
if gasLimit != nil {
|
||||
gas = uint64(*gasLimit)
|
||||
}
|
||||
if err := rpctypes.CheckTxFee(price, gas, b.RPCTxFeeCap()); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
pending, err := b.PendingTransactions()
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
for _, tx := range pending {
|
||||
// FIXME does Resend api possible at all? https://github.com/cerc-io/laconicd/issues/905
|
||||
p, err := evmtypes.UnwrapEthereumMsg(tx, common.Hash{})
|
||||
if err != nil {
|
||||
// not valid ethereum tx
|
||||
continue
|
||||
}
|
||||
|
||||
pTx := p.AsTransaction()
|
||||
|
||||
wantSigHash := signer.Hash(matchTx)
|
||||
pFrom, err := ethtypes.Sender(signer, pTx)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if pFrom == *args.From && signer.Hash(pTx) == wantSigHash {
|
||||
// Match. Re-sign and send the transaction.
|
||||
if gasPrice != nil && (*big.Int)(gasPrice).Sign() != 0 {
|
||||
args.GasPrice = gasPrice
|
||||
}
|
||||
if gasLimit != nil && *gasLimit != 0 {
|
||||
args.Gas = gasLimit
|
||||
}
|
||||
|
||||
return b.SendTransaction(args) // TODO: this calls SetTxDefaults again, refactor to avoid calling it twice
|
||||
}
|
||||
}
|
||||
|
||||
return common.Hash{}, fmt.Errorf("transaction %#x not found", matchTx.Hash())
|
||||
}
|
||||
|
||||
// SendRawTransaction send a raw Ethereum transaction.
|
||||
func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) {
|
||||
// RLP decode raw transaction bytes
|
||||
tx := ðtypes.Transaction{}
|
||||
if err := tx.UnmarshalBinary(data); err != nil {
|
||||
b.logger.Error("transaction decoding failed", "error", err.Error())
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
// check the local node config in case unprotected txs are disabled
|
||||
if !b.UnprotectedAllowed() && !tx.Protected() {
|
||||
// Ensure only eip155 signed transactions are submitted if EIP155Required is set.
|
||||
return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC")
|
||||
}
|
||||
|
||||
ethereumTx := &evmtypes.MsgEthereumTx{}
|
||||
if err := ethereumTx.FromEthereumTx(tx); err != nil {
|
||||
b.logger.Error("transaction converting failed", "error", err.Error())
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
if err := ethereumTx.ValidateBasic(); err != nil {
|
||||
b.logger.Debug("tx failed basic validation", "error", err.Error())
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
// Query params to use the EVM denomination
|
||||
res, err := b.queryClient.QueryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{})
|
||||
if err != nil {
|
||||
b.logger.Error("failed to query evm params", "error", err.Error())
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
cosmosTx, err := ethereumTx.BuildTx(b.clientCtx.TxConfig.NewTxBuilder(), res.Params.EvmDenom)
|
||||
if err != nil {
|
||||
b.logger.Error("failed to build cosmos tx", "error", err.Error())
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
// Encode transaction by default Tx encoder
|
||||
txBytes, err := b.clientCtx.TxConfig.TxEncoder()(cosmosTx)
|
||||
if err != nil {
|
||||
b.logger.Error("failed to encode eth tx using default encoder", "error", err.Error())
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
txHash := ethereumTx.AsTransaction().Hash()
|
||||
|
||||
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
|
||||
rsp, err := syncCtx.BroadcastTx(txBytes)
|
||||
if rsp != nil && rsp.Code != 0 {
|
||||
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
|
||||
}
|
||||
if err != nil {
|
||||
b.logger.Error("failed to broadcast tx", "error", err.Error())
|
||||
return txHash, err
|
||||
}
|
||||
|
||||
return txHash, nil
|
||||
}
|
||||
|
||||
// SetTxDefaults populates tx message with default values in case they are not
|
||||
// provided on the args
|
||||
func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error) {
|
||||
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
||||
return args, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||
}
|
||||
|
||||
head := b.CurrentHeader()
|
||||
if head == nil {
|
||||
return args, errors.New("latest header is nil")
|
||||
}
|
||||
|
||||
// If user specifies both maxPriorityfee and maxFee, then we do not
|
||||
// need to consult the chain for defaults. It's definitely a London tx.
|
||||
if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil {
|
||||
// In this clause, user left some fields unspecified.
|
||||
if head.BaseFee != nil && args.GasPrice == nil {
|
||||
if args.MaxPriorityFeePerGas == nil {
|
||||
tip, err := b.SuggestGasTipCap(head.BaseFee)
|
||||
if err != nil {
|
||||
return args, err
|
||||
}
|
||||
args.MaxPriorityFeePerGas = (*hexutil.Big)(tip)
|
||||
}
|
||||
|
||||
if args.MaxFeePerGas == nil {
|
||||
gasFeeCap := new(big.Int).Add(
|
||||
(*big.Int)(args.MaxPriorityFeePerGas),
|
||||
new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
|
||||
)
|
||||
args.MaxFeePerGas = (*hexutil.Big)(gasFeeCap)
|
||||
}
|
||||
|
||||
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
|
||||
return args, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
|
||||
}
|
||||
} else {
|
||||
if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil {
|
||||
return args, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
|
||||
}
|
||||
|
||||
if args.GasPrice == nil {
|
||||
price, err := b.SuggestGasTipCap(head.BaseFee)
|
||||
if err != nil {
|
||||
return args, err
|
||||
}
|
||||
if head.BaseFee != nil {
|
||||
// The legacy tx gas price suggestion should not add 2x base fee
|
||||
// because all fees are consumed, so it would result in a spiral
|
||||
// upwards.
|
||||
price.Add(price, head.BaseFee)
|
||||
}
|
||||
args.GasPrice = (*hexutil.Big)(price)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Both maxPriorityfee and maxFee set by caller. Sanity-check their internal relation
|
||||
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
|
||||
return args, fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
|
||||
}
|
||||
}
|
||||
|
||||
if args.Value == nil {
|
||||
args.Value = new(hexutil.Big)
|
||||
}
|
||||
if args.Nonce == nil {
|
||||
// get the nonce from the account retriever
|
||||
// ignore error in case tge account doesn't exist yet
|
||||
nonce, _ := b.getAccountNonce(*args.From, true, 0, b.logger)
|
||||
args.Nonce = (*hexutil.Uint64)(&nonce)
|
||||
}
|
||||
|
||||
if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
|
||||
return args, errors.New("both 'data' and 'input' are set and not equal. Please use 'input' to pass transaction call data")
|
||||
}
|
||||
|
||||
if args.To == nil {
|
||||
// Contract creation
|
||||
var input []byte
|
||||
if args.Data != nil {
|
||||
input = *args.Data
|
||||
} else if args.Input != nil {
|
||||
input = *args.Input
|
||||
}
|
||||
|
||||
if len(input) == 0 {
|
||||
return args, errors.New("contract creation without any data provided")
|
||||
}
|
||||
}
|
||||
|
||||
if args.Gas == nil {
|
||||
// For backwards-compatibility reason, we try both input and data
|
||||
// but input is preferred.
|
||||
input := args.Input
|
||||
if input == nil {
|
||||
input = args.Data
|
||||
}
|
||||
|
||||
callArgs := evmtypes.TransactionArgs{
|
||||
From: args.From,
|
||||
To: args.To,
|
||||
Gas: args.Gas,
|
||||
GasPrice: args.GasPrice,
|
||||
MaxFeePerGas: args.MaxFeePerGas,
|
||||
MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
|
||||
Value: args.Value,
|
||||
Data: input,
|
||||
AccessList: args.AccessList,
|
||||
}
|
||||
|
||||
blockNr := rpctypes.NewBlockNumber(big.NewInt(0))
|
||||
estimated, err := b.EstimateGas(callArgs, &blockNr)
|
||||
if err != nil {
|
||||
return args, err
|
||||
}
|
||||
args.Gas = &estimated
|
||||
b.logger.Debug("estimate gas usage automatically", "gas", args.Gas)
|
||||
}
|
||||
|
||||
if args.ChainID == nil {
|
||||
args.ChainID = (*hexutil.Big)(b.chainID)
|
||||
}
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// EstimateGas returns an estimate of gas usage for the given smart contract call.
|
||||
func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error) {
|
||||
blockNr := rpctypes.EthPendingBlockNumber
|
||||
if blockNrOptional != nil {
|
||||
blockNr = *blockNrOptional
|
||||
}
|
||||
|
||||
bz, err := json.Marshal(&args)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
req := evmtypes.EthCallRequest{
|
||||
Args: bz,
|
||||
GasCap: b.RPCGasCap(),
|
||||
}
|
||||
|
||||
_, err = b.TendermintBlockByNumber(blockNr)
|
||||
if err != nil {
|
||||
// the error message imitates geth behavior
|
||||
return 0, errors.New("header not found")
|
||||
}
|
||||
|
||||
// From ContextWithHeight: if the provided height is 0,
|
||||
// it will return an empty context and the gRPC query will use
|
||||
// the latest block height for querying.
|
||||
res, err := b.queryClient.EstimateGas(rpctypes.ContextWithHeight(blockNr.Int64()), &req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return hexutil.Uint64(res.Gas), nil
|
||||
}
|
||||
|
||||
// DoCall performs a simulated call operation through the evmtypes. It returns the
|
||||
// estimated gas used on the operation or an error if fails.
|
||||
func (b *Backend) DoCall(
|
||||
args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber,
|
||||
) (*evmtypes.MsgEthereumTxResponse, error) {
|
||||
bz, err := json.Marshal(&args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := evmtypes.EthCallRequest{
|
||||
Args: bz,
|
||||
GasCap: b.RPCGasCap(),
|
||||
}
|
||||
|
||||
// From ContextWithHeight: if the provided height is 0,
|
||||
// it will return an empty context and the gRPC query will use
|
||||
// the latest block height for querying.
|
||||
ctx := rpctypes.ContextWithHeight(blockNr.Int64())
|
||||
timeout := b.RPCEVMTimeout()
|
||||
|
||||
// Setup context so it may be canceled the call has completed
|
||||
// or, in case of unmetered gas, setup a context with a timeout.
|
||||
var cancel context.CancelFunc
|
||||
if timeout > 0 {
|
||||
ctx, cancel = context.WithTimeout(ctx, timeout)
|
||||
} else {
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
}
|
||||
|
||||
// Make sure the context is canceled when the call has completed
|
||||
// this makes sure resources are cleaned up.
|
||||
defer cancel()
|
||||
|
||||
res, err := b.queryClient.EthCall(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.Failed() {
|
||||
if res.VmError != vm.ErrExecutionReverted.Error() {
|
||||
return nil, status.Error(codes.Internal, res.VmError)
|
||||
}
|
||||
return nil, evmtypes.NewExecErrorWithReason(res.Ret)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GasPrice returns the current gas price based on Ethermint's gas price oracle.
|
||||
func (b *Backend) GasPrice() (*hexutil.Big, error) {
|
||||
var (
|
||||
result *big.Int
|
||||
err error
|
||||
)
|
||||
if head := b.CurrentHeader(); head.BaseFee != nil {
|
||||
result, err = b.SuggestGasTipCap(head.BaseFee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = result.Add(result, head.BaseFee)
|
||||
} else {
|
||||
result = big.NewInt(b.RPCMinGasPrice())
|
||||
}
|
||||
|
||||
// return at least GlobalMinGasPrice from FeeMarket module
|
||||
minGasPrice, err := b.GlobalMinGasPrice()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
minGasPriceInt := minGasPrice.TruncateInt().BigInt()
|
||||
if result.Cmp(minGasPriceInt) < 0 {
|
||||
result = minGasPriceInt
|
||||
}
|
||||
|
||||
return (*hexutil.Big)(result), nil
|
||||
}
|
265
rpc/backend/chain_info.go
Normal file
265
rpc/backend/chain_info.go
Normal file
@ -0,0 +1,265 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
feemarkettypes "github.com/cerc-io/laconicd/x/feemarket/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
|
||||
// ChainID is the EIP-155 replay-protection chain id for the current ethereum chain config.
|
||||
func (b *Backend) ChainID() (*hexutil.Big, error) {
|
||||
eip155ChainID, err := ethermint.ParseChainID(b.clientCtx.ChainID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// if current block is at or past the EIP-155 replay-protection fork block, return chainID from config
|
||||
bn, err := b.BlockNumber()
|
||||
if err != nil {
|
||||
b.logger.Debug("failed to fetch latest block number", "error", err.Error())
|
||||
return (*hexutil.Big)(eip155ChainID), nil
|
||||
}
|
||||
|
||||
if config := b.ChainConfig(); config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) {
|
||||
return (*hexutil.Big)(config.ChainID), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("chain not synced beyond EIP-155 replay-protection fork block")
|
||||
}
|
||||
|
||||
// ChainConfig returns the latest ethereum chain configuration
|
||||
func (b *Backend) ChainConfig() *params.ChainConfig {
|
||||
params, err := b.queryClient.Params(b.ctx, &evmtypes.QueryParamsRequest{})
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return params.Params.ChainConfig.EthereumConfig(b.chainID)
|
||||
}
|
||||
|
||||
// GlobalMinGasPrice returns MinGasPrice param from FeeMarket
|
||||
func (b *Backend) GlobalMinGasPrice() (sdk.Dec, error) {
|
||||
res, err := b.queryClient.FeeMarket.Params(b.ctx, &feemarkettypes.QueryParamsRequest{})
|
||||
if err != nil {
|
||||
return sdk.ZeroDec(), err
|
||||
}
|
||||
return res.Params.MinGasPrice, nil
|
||||
}
|
||||
|
||||
// BaseFee returns the base fee tracked by the Fee Market module.
|
||||
// If the base fee is not enabled globally, the query returns nil.
|
||||
// If the London hard fork is not activated at the current height, the query will
|
||||
// return nil.
|
||||
func (b *Backend) BaseFee(blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error) {
|
||||
// return BaseFee if London hard fork is activated and feemarket is enabled
|
||||
res, err := b.queryClient.BaseFee(rpctypes.ContextWithHeight(blockRes.Height), &evmtypes.QueryBaseFeeRequest{})
|
||||
if err != nil || res.BaseFee == nil {
|
||||
// we can't tell if it's london HF not enabled or the state is pruned,
|
||||
// in either case, we'll fallback to parsing from begin blocker event,
|
||||
// faster to iterate reversely
|
||||
for i := len(blockRes.BeginBlockEvents) - 1; i >= 0; i-- {
|
||||
evt := blockRes.BeginBlockEvents[i]
|
||||
if evt.Type == feemarkettypes.EventTypeFeeMarket && len(evt.Attributes) > 0 {
|
||||
baseFee, err := strconv.ParseInt(string(evt.Attributes[0].Value), 10, 64)
|
||||
if err == nil {
|
||||
return big.NewInt(baseFee), nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.BaseFee == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return res.BaseFee.BigInt(), nil
|
||||
}
|
||||
|
||||
// CurrentHeader returns the latest block header
|
||||
func (b *Backend) CurrentHeader() *ethtypes.Header {
|
||||
header, _ := b.HeaderByNumber(rpctypes.EthLatestBlockNumber)
|
||||
return header
|
||||
}
|
||||
|
||||
// PendingTransactions returns the transactions that are in the transaction pool
|
||||
// and have a from address that is one of the accounts this node manages.
|
||||
func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) {
|
||||
res, err := b.clientCtx.Client.UnconfirmedTxs(b.ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*sdk.Tx, 0, len(res.Txs))
|
||||
for _, txBz := range res.Txs {
|
||||
tx, err := b.clientCtx.TxConfig.TxDecoder()(txBz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, &tx)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetCoinbase is the address that staking rewards will be send to (alias for Etherbase).
|
||||
func (b *Backend) GetCoinbase() (sdk.AccAddress, error) {
|
||||
node, err := b.clientCtx.GetNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status, err := node.Status(b.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := &evmtypes.QueryValidatorAccountRequest{
|
||||
ConsAddress: sdk.ConsAddress(status.ValidatorInfo.Address).String(),
|
||||
}
|
||||
|
||||
res, err := b.queryClient.ValidatorAccount(b.ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
address, _ := sdk.AccAddressFromBech32(res.AccountAddress)
|
||||
return address, nil
|
||||
}
|
||||
|
||||
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
|
||||
func (b *Backend) FeeHistory(
|
||||
userBlockCount rpc.DecimalOrHex, // number blocks to fetch, maximum is 100
|
||||
lastBlock rpc.BlockNumber, // the block to start search , to oldest
|
||||
rewardPercentiles []float64, // percentiles to fetch reward
|
||||
) (*rpctypes.FeeHistoryResult, error) {
|
||||
blockEnd := int64(lastBlock)
|
||||
|
||||
if blockEnd <= 0 {
|
||||
blockNumber, err := b.BlockNumber()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockEnd = int64(blockNumber)
|
||||
}
|
||||
userBlockCountInt := int64(userBlockCount)
|
||||
maxBlockCount := int64(b.cfg.JSONRPC.FeeHistoryCap)
|
||||
if userBlockCountInt > maxBlockCount {
|
||||
return nil, fmt.Errorf("FeeHistory user block count %d higher than %d", userBlockCountInt, maxBlockCount)
|
||||
}
|
||||
blockStart := blockEnd - userBlockCountInt
|
||||
if blockStart < 0 {
|
||||
blockStart = 0
|
||||
}
|
||||
|
||||
blockCount := blockEnd - blockStart
|
||||
|
||||
oldestBlock := (*hexutil.Big)(big.NewInt(blockStart))
|
||||
|
||||
// prepare space
|
||||
reward := make([][]*hexutil.Big, blockCount)
|
||||
rewardCount := len(rewardPercentiles)
|
||||
for i := 0; i < int(blockCount); i++ {
|
||||
reward[i] = make([]*hexutil.Big, rewardCount)
|
||||
}
|
||||
thisBaseFee := make([]*hexutil.Big, blockCount)
|
||||
thisGasUsedRatio := make([]float64, blockCount)
|
||||
|
||||
// rewards should only be calculated if reward percentiles were included
|
||||
calculateRewards := rewardCount != 0
|
||||
|
||||
// fetch block
|
||||
for blockID := blockStart; blockID < blockEnd; blockID++ {
|
||||
index := int32(blockID - blockStart)
|
||||
// tendermint block
|
||||
tendermintblock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(blockID))
|
||||
if tendermintblock == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// eth block
|
||||
ethBlock, err := b.GetBlockByNumber(rpctypes.BlockNumber(blockID), true)
|
||||
if ethBlock == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// tendermint block result
|
||||
tendermintBlockResult, err := b.TendermintBlockResultByNumber(&tendermintblock.Block.Height)
|
||||
if tendermintBlockResult == nil {
|
||||
b.logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oneFeeHistory := rpctypes.OneFeeHistory{}
|
||||
err = b.processBlock(tendermintblock, ðBlock, rewardPercentiles, tendermintBlockResult, &oneFeeHistory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// copy
|
||||
thisBaseFee[index] = (*hexutil.Big)(oneFeeHistory.BaseFee)
|
||||
thisGasUsedRatio[index] = oneFeeHistory.GasUsedRatio
|
||||
if calculateRewards {
|
||||
for j := 0; j < rewardCount; j++ {
|
||||
reward[index][j] = (*hexutil.Big)(oneFeeHistory.Reward[j])
|
||||
if reward[index][j] == nil {
|
||||
reward[index][j] = (*hexutil.Big)(big.NewInt(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
feeHistory := rpctypes.FeeHistoryResult{
|
||||
OldestBlock: oldestBlock,
|
||||
BaseFee: thisBaseFee,
|
||||
GasUsedRatio: thisGasUsedRatio,
|
||||
}
|
||||
|
||||
if calculateRewards {
|
||||
feeHistory.Reward = reward
|
||||
}
|
||||
|
||||
return &feeHistory, nil
|
||||
}
|
||||
|
||||
// SuggestGasTipCap returns the suggested tip cap
|
||||
// Although we don't support tx prioritization yet, but we return a positive value to help client to
|
||||
// mitigate the base fee changes.
|
||||
func (b *Backend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) {
|
||||
if baseFee == nil {
|
||||
// london hardfork not enabled or feemarket not enabled
|
||||
return big.NewInt(0), nil
|
||||
}
|
||||
|
||||
params, err := b.queryClient.FeeMarket.Params(b.ctx, &feemarkettypes.QueryParamsRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// calculate the maximum base fee delta in current block, assuming all block gas limit is consumed
|
||||
// ```
|
||||
// GasTarget = GasLimit / ElasticityMultiplier
|
||||
// Delta = BaseFee * (GasUsed - GasTarget) / GasTarget / Denominator
|
||||
// ```
|
||||
// The delta is at maximum when `GasUsed` is equal to `GasLimit`, which is:
|
||||
// ```
|
||||
// MaxDelta = BaseFee * (GasLimit - GasLimit / ElasticityMultiplier) / (GasLimit / ElasticityMultiplier) / Denominator
|
||||
// = BaseFee * (ElasticityMultiplier - 1) / Denominator
|
||||
// ```
|
||||
maxDelta := baseFee.Int64() * (int64(params.Params.ElasticityMultiplier) - 1) / int64(params.Params.BaseFeeChangeDenominator)
|
||||
if maxDelta < 0 {
|
||||
// impossible if the parameter validation passed.
|
||||
maxDelta = 0
|
||||
}
|
||||
return big.NewInt(maxDelta), nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user