Compare commits

..

No commits in common. "main" and "docs" have entirely different histories.
main ... docs

707 changed files with 31904 additions and 93030 deletions

View File

@ -1,6 +1,115 @@
---
Language: Proto
BasedOnStyle: google
ColumnLimit: 120
IndentWidth: 2
Language: Proto
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
RawStringFormats:
- Delimiters:
- pb
Language: TextProto
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

View File

@ -1,7 +1,5 @@
Dockerfile
# localnet-setup
localnet-setup
**/node_modules
init.sh
build
localnet-setup
# build
build

View File

@ -1,5 +0,0 @@
[flake8]
ignore = BLK100, W503
max-line-length = 88
extend-ignore = E203
exclude = .git,__pycache__,node_modules,.direnv

View File

@ -1,17 +0,0 @@
name: Build
on:
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.21
check-latest: true
- run: |
make build

View File

@ -1,20 +0,0 @@
name: Deploy Contract
on:
pull_request:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.21
check-latest: true
- name: Test contract
run: |
make contract-tools
# This seems to be an empty placeholder.
make test-contract

View File

@ -1,28 +0,0 @@
name: Publish on 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.CICD_PUBLISH_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}}

View File

@ -1,28 +0,0 @@
name: Protobuf
# Protobuf runs buf (https://buf.build/) lint and check-breakage
# This workflow is only run when a .proto file has been changed
on:
pull_request:
paths:
- "proto/**"
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v3
- uses: bufbuild/buf-setup-action@v1.9.0
- uses: bufbuild/buf-lint-action@v1
with:
input: "proto"
break-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: bufbuild/buf-setup-action@v1.9.0
- uses: bufbuild/buf-breaking-action@v1
with:
input: "proto"
against: "https://github.com/${{ github.repository }}.git#branch=${{ github.event.pull_request.base.ref }},ref=HEAD~1,subdir=proto"

View File

@ -1,21 +0,0 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
test-importer:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.21
check-latest: true
- uses: actions/checkout@v3
- name: test-importer
run: |
make test-import

View File

@ -1,21 +0,0 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
test-rpc:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.21
check-latest: true
- uses: actions/checkout@v3
- name: Test rpc endpoint
run: |
make test-rpc

View File

@ -1,40 +0,0 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
sdk_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout laconic-sdk
uses: actions/checkout@v3
with:
path: "./laconic-sdk/"
repository: cerc-io/laconic-sdk
fetch-depth: 0
ref: main
- name: Environment
run: ls -tlh && env
- name: Build laconicd container
working-directory: tests/sdk_tests
run: ./build-laconicd-container.sh
- name: Build laconic-sdk container
working-directory: laconic-sdk
run: ./scripts/build-sdk-test-container.sh
- name: Start containers (auctions enabled)
working-directory: tests/sdk_tests
env:
TEST_AUCTION_ENABLED: true
run: docker compose up -d
- name: Run auction tests
working-directory: tests/sdk_tests
run: ./run-tests.sh test:auctions

View File

@ -1,40 +0,0 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
sdk_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout laconic-sdk
uses: actions/checkout@v3
with:
path: "./laconic-sdk/"
repository: cerc-io/laconic-sdk
fetch-depth: 0
ref: main
- name: Environment
run: ls -tlh && env
- name: Build laconicd container
working-directory: tests/sdk_tests
run: ./build-laconicd-container.sh
- name: Build laconic-sdk container
working-directory: laconic-sdk
run: ./scripts/build-sdk-test-container.sh
- name: Start containers (expiry enabled)
working-directory: tests/sdk_tests
env:
TEST_REGISTRY_EXPIRY: true
run: docker compose up -d
- name: Run nameservice expiry tests
working-directory: tests/sdk_tests
run: ./run-tests.sh test:nameservice-expiry

View File

@ -1,38 +0,0 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
sdk_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout laconic-sdk
uses: actions/checkout@v3
with:
path: "./laconic-sdk/"
repository: cerc-io/laconic-sdk
fetch-depth: 0
ref: main
- name: Environment
run: ls -tlh && env
- name: Build laconicd container
working-directory: tests/sdk_tests
run: ./build-laconicd-container.sh
- name: Build laconic-sdk container
working-directory: laconic-sdk
run: ./scripts/build-sdk-test-container.sh
- name: Start containers
working-directory: tests/sdk_tests
run: docker compose up -d
- name: Run tests
working-directory: tests/sdk_tests
run: ./run-tests.sh

View File

@ -1,23 +0,0 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
test-unit:
# This test case doesn't work in CI, run as root.
env:
SKIP_UNIT_TESTS: TestInitConfigNonNotExistError
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.21
check-latest: true
- uses: actions/checkout@v3
- name: Test
run: |
make test-unit

4
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,4 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
# Primary repo maintainers
* @fedekunze @khoslaventures @jolube

18
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@ -0,0 +1,18 @@
---
name: Bug Report
about: create a bug report
---
__System info:__ [Include Ethermint commit, operating system name, and other relevant details]
__Steps to reproduce:__
1. [First Step]
2. [Second Step]
3. [and so on...]
__Expected behavior:__ [What you expected to happen]
__Actual behavior:__ [What actually happened]
__Additional info:__ [Include gist of relevant config, logs, etc.]

View File

@ -0,0 +1,15 @@
---
name: Feature request
about: Opening a feature request kicks off a discussion
---
__Proposal:__ [Description of the feature]
__Current behavior:__ [What currently happens]
__Desired behavior:__ [What you would like to happen]
__Use case:__ [Why is this important (helps with prioritizing requests)]
Requests may be closed if we're not actively planning to work on them.

34
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,34 @@
<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺
v ✰ Thanks for creating a PR! ✰
v Before smashing the submit button please review the checkboxes.
v If a checkbox is n/a - please still include it but + a little note why
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -->
Closes: #XXX
## Description
<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review.
-->
______
For contributor use:
- [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
- [ ] Code follows the [module structure standards](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/structure.md).
- [ ] Wrote unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] Updated relevant documentation (`docs/`) or specification (`x/<module>/spec/`)
- [ ] Added relevant `godoc` [comments](https://blog.golang.org/godoc-documenting-go-code).
- [ ] Added a relevant changelog entry to the `Unreleased` section in `CHANGELOG.md`
- [ ] Re-reviewed `Files changed` in the Github PR explorer
______
For admin use:
- [ ] Added appropriate labels to PR (ex. `WIP`, `R4R`, `docs`, etc)
- [ ] Reviewers assigned
- [ ] Squashed all commits, uses message "Merge pull request #XYZ: [title]" ([coding standards](https://github.com/tendermint/coding/blob/master/README.md#merging-a-pr))

28
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,28 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
time: "10:00"
open-pull-requests-limit: 10
reviewers:
- fedekunze
- khoslaventures
labels:
- dependencies
- package-ecosystem: docker
directory: "/"
schedule:
interval: daily
time: "10:00"
open-pull-requests-limit: 10
reviewers:
- fedekunze
- khoslaventures
- package-ecosystem: gomod
directory: "/"
schedule:
interval: daily
time: "10:00"
open-pull-requests-limit: 10

37
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,37 @@
"C:Crypto":
- crypto/**/*
"C:Encoding":
- encoding/**/*
"C:JSON-RPC":
- ethereum/rpc/**/*
"C:Proto":
- proto/**/*
- third_party/**/*
- /**/*.pb.go
- /**/*.pb.gw.go
"C:Types":
- types/**/*
"C:x/evm":
- x/evm/**/*/
"Type: Build":
- Makefile
- Dockerfile
- docker-compose.yml
- scripts/*
- config.yml
"Type: CI":
- .github/**/*.yml
- buf.yaml
- .mergify.yml
- .golangci.yml
"C:CLI":
- client/**/*
- x/*/client/**/*
"Type: Tests":
- tests/**/*
- /**/*/*_test.go
"Type: Docs":
- docs/**/*
- x/*/spec/**/*
"Type: ADR":
- docs/architecture/**/*

32
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Build
on:
pull_request:
branches:
- main
jobs:
cleanup-runs:
runs-on: ubuntu-latest
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'"
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v2
with:
go-version: 1.17
- uses: technote-space/get-diff-action@v6.0.1
id: git_diff
with:
SUFFIX_FILTER: |
.go
.mod
.sum
- run: |
make build
if: env.GIT_DIFF

71
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '37 21 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go', 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

38
.github/workflows/deploy-contract.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: Deploy Contract
on:
pull_request:
branches:
- main
jobs:
cleanup-runs:
runs-on: ubuntu-latest
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/main'"
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '12.x'
- name: Install dependencies
run: npm install
- uses: technote-space/get-diff-action@v6.0.1
id: git_diff
with:
SUFFIX_FILTER: |
.go
.mod
.sum
.sol
- name: Test contract
run: |
sudo make contract-tools
sudo make test-contract
if: env.GIT_DIFF

View File

@ -13,16 +13,15 @@ jobs:
with:
submodules: true
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v2
with:
go-version: 1.21
check-latest: true
go-version: 1.17
- name: release dry run
run: make release-dry-run
- name: setup release environment
env:
GITHUB_TOKEN: ${{ secrets.CICD_PUBLISH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |-
echo 'GITHUB_TOKEN=${{secrets.CICD_PUBLISH_TOKEN}}' > .release-env
echo 'GITHUB_TOKEN=${{secrets.GITHUB_TOKEN}}' > .release-env
- name: release publish
run: make release
run: make release

View File

@ -0,0 +1,29 @@
name: Notion Sync
on:
workflow_dispatch:
issues:
types:
[
opened,
edited,
labeled,
unlabeled,
assigned,
unassigned,
milestoned,
demilestoned,
reopened,
closed,
]
jobs:
notion_job:
runs-on: ubuntu-latest
name: Add GitHub Issues to Notion
steps:
- name: Add GitHub Issues to Notion
uses: vulcanize/notion-github-action@v1.2.4-issueid
with:
notion-token: ${{ secrets.NOTION_TOKEN }}
notion-db: ${{ secrets.NOTION_DATABASE }}

14
.github/workflows/labeler.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: "Pull Request Labeler"
on:
pull_request:
push:
branches:
- main
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"

12
.github/workflows/linkchecker.yml vendored Normal file
View File

@ -0,0 +1,12 @@
name: Check Markdown links
on:
schedule:
- cron: "* */24 * * *"
jobs:
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: gaurav-nelson/github-action-markdown-link-check@1.0.14
with:
folder-path: "docs"

View File

@ -13,30 +13,18 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# Required: setup-go, for all versions v3.0.0+ of golangci-lint
- uses: actions/setup-go@v3
with:
go-version: 1.21
check-latest: true
- uses: actions/checkout@v3
- uses: golangci/golangci-lint-action@v3.3.1
- uses: technote-space/get-diff-action@v6.0.1
with:
SUFFIX_FILTER: |
.go
.mod
.sum
- uses: golangci/golangci-lint-action@v2.5.2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: latest
version: v1.42.1
args: --timeout 10m
github-token: ${{ secrets.github_token }}
python-lint:
# For compatibility with Gitea
env:
USER: root
name: Run flake8 on python integration tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v20
- uses: cachix/cachix-action@v12
with:
name: ethermint
- run: |
nix-shell -I nixpkgs=./nix -p test-env --run "make lint-py"
# Check only if there are differences in the source code
if: "env.GIT_DIFF"

30
.github/workflows/proto.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: Protobuf
# Protobuf runs buf (https://buf.build/) lint and check-breakage
# This workflow is only run when a .proto file has been changed
on:
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.proto
- name: lint
run: make proto-lint
if: env.GIT_DIFF
breakage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.proto
- name: check-breakage
run: make proto-check-breaking
if: env.GIT_DIFF

34
.github/workflows/security.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Run Gosec
on:
pull_request:
push:
branches:
- main
jobs:
Gosec:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Checkout Source
uses: actions/checkout@v3
- name: Get Diff
uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/*.go
go.mod
go.sum
- name: Run Gosec Security Scanner
uses: informalsystems/gosec@master
with:
# we let the report trigger content trigger a failure using the GitHub Security features.
args: '-no-fail -fmt sarif -out results.sarif ./...'
if: "env.GIT_DIFF_FILTERED != ''"
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
# Path to SARIF file relative to the root of the repository
sarif_file: results.sarif
if: "env.GIT_DIFF_FILTERED != ''"

41
.github/workflows/semgrep.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Semgrep
on:
# Scan changed files in PRs, block on new issues only (existing issues ignored)
pull_request: {}
push:
branches:
- main
paths:
- .github/workflows/semgrep.yml
schedule:
- cron: '0 0 * * 0'
jobs:
semgrep:
name: Scan
runs-on: ubuntu-latest
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@v3
- name: Get Diff
uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/*.go
**/*.js
**/*.ts
**/*.sol
go.mod
go.sum
- uses: returntocorp/semgrep-action@v1
with:
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
# Upload findings to GitHub Advanced Security Dashboard [step 1/2]
# See also the next step.
generateSarif: "1"
if: "env.GIT_DIFF_FILTERED != ''"
# Upload findings to GitHub Advanced Security Dashboard [step 2/2]
- name: Upload SARIF file for GitHub Advanced Security Dashboard
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: semgrep.sarif
if: "env.GIT_DIFF_FILTERED != ''"

172
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,172 @@
name: Tests
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
cleanup-runs:
runs-on: ubuntu-latest
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
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
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.sol
**/**.go
go.mod
go.sum
- name: Test and Create Coverage Report
run: |
make test-unit-cover
if: env.GIT_DIFF
- uses: codecov/codecov-action@v2.1.0
with:
file: ./coverage.txt
fail_ci_if_error: true
if: env.GIT_DIFF
test-importer:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
id: git_diff
with:
SUFFIX_FILTER: |
.go
.mod
.sum
- name: test-importer
run: |
make test-import
if: env.GIT_DIFF
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
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.sol
**/**.go
go.mod
go.sum
- name: Test rpc endpoint
run: |
make test-rpc
if: env.GIT_DIFF
test-e2e:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v2.1.4
with:
go-version: 1.17
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1
with:
PATTERNS: |
**/**.sol
**/**.go
go.mod
go.sum
- name: Test e2e
run: |
make test-integration
if: env.GIT_DIFF

15
.gitignore vendored
View File

@ -13,7 +13,6 @@
*.dll
*.so
*.dylib
.dccache
# Build
*.test
@ -35,14 +34,10 @@ keyring_test_cosmos
./**/node_modules
./**/dist
secret.yml
artifacts/*
tmp-swagger-gen
github.com/
# vue/
# Local docker volume mappings
localnet-setup
.testnets
# Testing
coverage.txt
@ -50,7 +45,6 @@ coverage.txt
sim_log_file
tests/**/tmp/*
yarn.lock
x/auction/client/testutil/bidder-bafyre*
# Vagrant
.vagrant/
@ -61,7 +55,6 @@ vagrant
# IDE
.idea/
*.iml
*.code-workspace
# Graphviz
dependency-graph.png
@ -76,8 +69,6 @@ dependency-graph.png
*.abi
# Node.js
**/node_modules
# OpenZeppelin contracts
contracts/@openzeppelin/*
tests/**/node_modules/*
tests-solidity/**/node_modules/*
**/**.json

File diff suppressed because it is too large Load Diff

View File

@ -6,34 +6,45 @@ run:
linters:
enable:
- bodyclose
# - depguard # 20231120 disable until https://github.com/golangci/golangci-lint/issues/3906 is released
- deadcode
- depguard
- dogsled
- dupl
- errcheck
- goconst
- gocritic
- gofumpt
# - revive # 20231120 overly sensitive unused detection
- gofmt
- goimports
- revive
- gosec
- gosimple
- govet
- ineffassign
- lll
# - lll TODO: enable
- misspell
- nakedret
- prealloc
- exportloopref
- staticcheck
- structcheck
- stylecheck
- typecheck
# - typecheck #TODO: enable
- unconvert
- unparam
- unused
- varcheck
- nolintlint
- asciicheck
# - exhaustive
- exportloopref
- gofumpt
- gomodguard
- whitespace
# - nestif
# - nlreturn
- noctx
- rowserrcheck
# - whitespace
# - wsl
issues:
exclude-rules:
@ -46,8 +57,6 @@ issues:
max-same-issues: 50
linters-settings:
lll:
line-length: 150
dogsled:
max-blank-identifiers: 3
golint:
@ -62,7 +71,7 @@ linters-settings:
require-explanation: false
require-specific: false
gofumpt:
lang-version: "1.19"
lang-version: "1.17"
gomodguard:
blocked:
versions: # List of blocked module version constraints

View File

@ -1,21 +0,0 @@
"default": true
"MD001": false
"MD004": false
"MD007":
"indent": 4
"MD013": false
"MD024":
"siblings_only": true
"MD025": false
"MD026":
"punctuation": ".;:"
"MD029": false
"MD033": false
"MD034": false
"MD036": false
"MD040": false
"MD041": false
"MD051": false
"MD049":
"style": "asterisk"
"no-hard-tabs": false

View File

@ -1,3 +0,0 @@
CHANGELOG.md
docs/api/proto-docs.md
docs/node_modules

View File

@ -4,7 +4,7 @@ queue_rules:
- "#approved-reviews-by>1"
pull_request_rules:
- name: automerge to main with label "automerge" and branch protection passing
- name: automerge to the base branch with label automerge and branch protection passing
conditions:
- "#approved-reviews-by>1"
- base=main
@ -12,30 +12,22 @@ pull_request_rules:
actions:
queue:
name: default
merge:
method: squash
commit_message_template: |
{{ title }} (#{{ number }})
{{ body }}
- name: backport patches to main branch
conditions:
- label=backport/main
actions:
backport:
branches:
- main
- name: backport patches to v0.20.x branch
commit_message: title+body
- name: backport patches to v0.9.x branch
conditions:
- base=main
- label=backport/0.20.x
- label=backport/0.9.x
actions:
backport:
branches:
- release/v0.20.x
- name: backport patches to v0.19.x branch
- release/v0.9.x
- name: backport patches to v0.7.x branch
conditions:
- base=main
- label=backport/0.19.x
- label=backport/0.7.x
actions:
backport:
branches:
- release/v0.19.x
- release/v0.7.x

View File

@ -1,174 +0,0 @@
---
# Lint directives.
lint:
# # Linter files to ignore.
# ignores:
# - id: MESSAGE_NAMES_UPPER_CAMEL_CASE
# files:
# # NOTE: UNIX paths will be properly accepted by both UNIX and Windows.
# - _example/proto/simple.proto
# - id: ENUM_NAMES_UPPER_CAMEL_CASE
# files:
# - path/to/foo.proto
# # Linter files to walk.
# files:
# # The specific files to exclude.
# exclude:
# # NOTE: UNIX paths will be properly accepted by both UNIX and Windows.
# - path/to/file
# # Linter directories to walk.
# directories:
# # The specific directories to exclude.
# exclude:
# # NOTE: UNIX paths will be properly accepted by both UNIX and Windows.
# - path/to/dir
# Linter rules.
# Run `protolint list` to see all available rules.
rules:
# Determines whether or not to include the default set of linters.
no_default: true
# Set the default to all linters. This option works the other way around as no_default does.
# If you want to enable this option, delete the comment out below and no_default.
# all_default: true
# The specific linters to add.
add:
- FIELD_NAMES_LOWER_SNAKE_CASE
- MESSAGE_NAMES_UPPER_CAMEL_CASE
- MAX_LINE_LENGTH
- INDENT
# - SERVICE_NAMES_END_WITH
- FIELD_NAMES_EXCLUDE_PREPOSITIONS
- MESSAGE_NAMES_EXCLUDE_PREPOSITIONS
- FILE_NAMES_LOWER_SNAKE_CASE
- IMPORTS_SORTED
- PACKAGE_NAME_LOWER_CASE
- ORDER
- MESSAGES_HAVE_COMMENT
- SERVICES_HAVE_COMMENT
- RPCS_HAVE_COMMENT
- FIELDS_HAVE_COMMENT
- PROTO3_FIELDS_AVOID_REQUIRED
- PROTO3_GROUPS_AVOID
# - REPEATED_FIELD_NAMES_PLURALIZED
- ENUMS_HAVE_COMMENT
- ENUM_FIELDS_HAVE_COMMENT
- SYNTAX_CONSISTENT
- RPC_NAMES_UPPER_CAMEL_CASE
# - FILE_HAS_COMMENT
- QUOTE_CONSISTENT
# # The specific linters to remove.
# remove:
# - RPC_NAMES_UPPER_CAMEL_CASE
# Linter rules option.
rules_option:
# MAX_LINE_LENGTH rule option.
max_line_length:
# Enforces a maximum line length
max_chars: 120
# Specifies the character count for tab characters
tab_chars: 2
# INDENT rule option.
indent:
# Available styles are 4(4-spaces), 2(2-spaces) or tab.
style: 2
# Specifies if it should stop considering and inserting new lines at the appropriate positions
# when the inner elements are on the same line. Default is false.
not_insert_newline: true
# # FILE_NAMES_LOWER_SNAKE_CASE rule option.
# file_names_lower_snake_case:
# excludes:
# - ../proto/invalidFileName.proto
# QUOTE_CONSISTENT rule option.
quote_consistent:
# Available quote are "double" or "single".
quote: double
# ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH rule option.
enum_field_names_zero_value_end_with:
suffix: INVALID
# # SERVICE_NAMES_END_WITH rule option.
# service_names_end_with:
# text: Service
# FIELD_NAMES_EXCLUDE_PREPOSITIONS rule option.
field_names_exclude_prepositions:
# The specific prepositions to determine if the field name includes.
prepositions:
- for
- at
- of
# The specific keywords including prepositions to ignore. E.g. end_of_support is a term you would like to use, and skip checking.
excludes:
- duration_of_decay
# # REPEATED_FIELD_NAMES_PLURALIZED rule option.
# ## The spec for each rules follows the implementation of https://github.com/gertd/go-pluralize.
# ## Plus, you can refer to this rule's test code.
# repeated_field_names_pluralized:
# uncountable_rules:
# - paper
# irregular_rules:
# Irregular: Regular
# MESSAGE_NAMES_EXCLUDE_PREPOSITIONS rule option.
message_names_exclude_prepositions:
# The specific prepositions to determine if the message name includes.
prepositions:
- With
- For
- Of
# # The specific keywords including prepositions to ignore. E.g. EndOfSupport is a term you would like to use, and skip checking.
# excludes:
# - EndOfSupport
# # RPC_NAMES_CASE rule option.
# rpc_names_case:
# # The specific convention the name should conforms to.
# ## Available conventions are "lower_camel_case", "upper_snake_case", or "lower_snake_case".
# convention: upper_snake_case
# MESSAGES_HAVE_COMMENT rule option.
messages_have_comment:
# Comments need to begin with the name of the thing being described. default is false.
should_follow_golang_style: true
# SERVICES_HAVE_COMMENT rule option.
services_have_comment:
# Comments need to begin with the name of the thing being described. default is false.
should_follow_golang_style: true
# RPCS_HAVE_COMMENT rule option.
rpcs_have_comment:
# Comments need to begin with the name of the thing being described. default is false.
should_follow_golang_style: true
# FIELDS_HAVE_COMMENT rule option.
fields_have_comment:
# Comments need to begin with the name of the thing being described. default is false.
should_follow_golang_style: true
# ENUMS_HAVE_COMMENT rule option.
enums_have_comment:
# Comments need to begin with the name of the thing being described. default is false.
should_follow_golang_style: true
# ENUM_FIELDS_HAVE_COMMENT rule option.
enum_fields_have_comment:
# Comments need to begin with the name of the thing being described. default is false.
should_follow_golang_style: true
# # SYNTAX_CONSISTENT rule option.
# syntax_consistent:
# # Default is proto3.
# version: proto2

View File

@ -19,9 +19,6 @@ test/
tests/
*_test.go
# false positive; TODO: https://github.com/cerc-io/laconicd/issues/104
testutil/network/network.go
# Semgrep rules folder
.semgrep

View File

@ -1,3 +0,0 @@
{
"extends": "solhint:default"
}

View File

@ -1,31 +0,0 @@
---
yaml-files:
- '*.yaml'
- '*.yml'
- '.yamllint'
rules:
braces: enable
brackets: enable
colons: enable
commas: enable
comments:
level: warning
comments-indentation: disable
document-end: disable
document-start: disable
empty-lines: disable
empty-values: disable
float-values: disable
hyphens: enable
indentation: enable
key-duplicates: enable
key-ordering: disable
line-length: disable
new-line-at-end-of-file: enable
new-lines: enable
octal-values: disable
quoted-strings: disable
trailing-spaces: disable
truthy: disable

View File

@ -36,603 +36,317 @@ Ref: https://keepachangelog.com/en/1.0.0/
# Changelog
## [v0.20.0] - 2022-12-28
### State Machine Breaking
* (deps) [#1564](https://github.com/evmos/ethermint/pull/1564) Bump ibc-go to [`v5.2.0`](https://github.com/cosmos/ibc-go/releases/tag/v5.2.0)
* (evm) [\#1272](https://github.com/evmos/ethermint/pull/1272) Implement modular interface for the EVM.
* (deps) [#1551](https://github.com/evmos/ethermint/pull/1551) Upgrade Cosmos SDK to [`v0.46.7`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.7).
* (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.
* (evm) [#1452](https://github.com/evmos/ethermint/pull/1452) Simplify Gas Math in `ApplyTransaction`.
* (eth) [#1430](https://github.com/evmos/ethermint/pull/1430) Added support for array of type `Any` on eip712. 
* (ante) [1460](https://github.com/evmos/ethermint/pull/1460) Add KV Gas config on ethereum Txs.
* (eth) [#1459](https://github.com/evmos/ethermint/pull/1459) Added support for messages with optional types omitted on eip712.
* (geth) [#1413](https://github.com/evmos/ethermint/pull/1413) Update go-ethereum version to [`v1.10.26`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.26).
* (deps) [#1419](https://github.com/evmos/ethermint/pull/1419) Add ics23 patch for dragonberry and bump iavl to v0.19.4
### API Breaking
* (ante) [#1521](https://github.com/evmos/ethermint/pull/1521) Deprecate support for legacy EIP-712 signature verification implementation via AnteHandler decorator.
* (ante) [#1214](https://github.com/evmos/ethermint/pull/1214) Set mempool priority to EVM transactions.
* (evm) [#1405](https://github.com/evmos/ethermint/pull/1405) Add parameter `chainID` to evm keeper's `EVMConfig` method, so caller can choose to not use the cached `eip155ChainID`.
### Features
* (ci) [#1528](https://github.com/evmos/ethermint/pull/1528) Add Golang dependency vulnerability checker.
* (app) [#1501](https://github.com/evmos/ethermint/pull/1501) Set default File store listener for application from [ADR38](https://docs.cosmos.network/v0.47/architecture/adr-038-state-listening)
### Improvements
* (tests) [#1507](https://github.com/evmos/ethermint/pull/1507) Remove legacy sim tests
* (feemarket) [#1508](https://github.com/evmos/ethermint/pull/1508) Remove old x/params migration logic
* (evm) [#1499](https://github.com/evmos/ethermint/pull/1499) Add Shanghai and Cancun block
* (ante) [#1455](https://github.com/evmos/ethermint/pull/1455) Refactor `AnteHandler` logic
* (evm) [#1444](https://github.com/evmos/ethermint/pull/1444) Improve performance of `eth_estimateGas`
* (ante) [\#1388](https://github.com/evmos/ethermint/pull/1388) Optimize AnteHandler gas consumption
* (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.
* (cli) [#1360](https://github.com/evmos/ethermint/pull/1360) Introduce a new `grpc-only` flag, such that when enabled, will start the node in a query-only mode. Note, gRPC MUST be enabled with this flag.
* (rpc) [#1378](https://github.com/evmos/ethermint/pull/1378) Add support for EVM RPC metrics
* (ante) [#1390](https://github.com/evmos/ethermint/pull/1390) Added multisig tx support.
* (test) [#1396](https://github.com/evmos/ethermint/pull/1396) Increase test coverage for the EVM module `keeper`
* (ante) [#1397](https://github.com/evmos/ethermint/pull/1397) Refactor EIP-712 signature verification to support EIP-712 multi-signing.
* (deps) [#1416](https://github.com/evmos/ethermint/pull/1416) Bump Go version to `1.19`
* (cmd) [\#1417](https://github.com/evmos/ethermint/pull/1417) Apply Google CLI Syntax for required and optional args.
* (deps) [#1456](https://github.com/evmos/ethermint/pull/1456) Migrate errors-related functionality from "github.com/cosmos/cosmos-sdk/types/errors" (deprecated) to "cosmossdk.io/errors"
### 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) [#1561](https://github.com/evmos/ethermint/pull/1561) Fix call to `NewMnemonic` in `personal_newAccount`
* (cli) [#1550](https://github.com/evmos/ethermint/pull/1550) Fix signature algorithm validation and default for Ledger.
* (eip712) [#1543](https://github.com/evmos/ethermint/pull/1543) Improve error handling for EIP-712 encoding config initialization.
* (app) [#1505](https://github.com/evmos/ethermint/pull/1505) Setup gRPC node service with the application.
* (server) [#1497](https://github.com/evmos/ethermint/pull/1497) Fix telemetry server setup for observability
* (rpc) [#1442](https://github.com/evmos/ethermint/pull/1442) Fix decoding of `finalized` block number.
* (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.
* (state) [#1320](https://github.com/evmos/ethermint/pull/1320) Fix codehash check mismatch when the code has been deleted in the evm state.
* (rpc) [#1392](https://github.com/evmos/ethermint/pull/1392) Allow fill the proposer address in json-rpc through tendermint api, and pass explicitly to grpc query handler.
* (rpc) [#1431](https://github.com/evmos/ethermint/pull/1431) Align hex-strings proof fields in `eth_getProof` as Ethereum.
* (proto) [#1466](https://github.com/evmos/ethermint/pull/1466) Fix proto scripts and upgrade them to mirror current cosmos-sdk scripts
* (rpc) [#1405](https://github.com/evmos/ethermint/pull/1405) Fix uninitialized chain ID field in gRPC requests.
* (analytics) [#1434](https://github.com/evmos/ethermint/pull/1434) Remove unbound labels from custom tendermint metrics.
* (rpc) [#1484](https://github.com/evmos/ethermint/pull/1484) Align empty account result for old blocks as ethereum instead of return account not found error.
* (rpc) [#1503](https://github.com/evmos/ethermint/pull/1503) Fix block hashes returned on JSON-RPC filter `eth_newBlockFilter`.
* (ante) [#1566](https://github.com/evmos/ethermint/pull/1566) Fix `gasWanted` on `EthGasConsumeDecorator` ante handler when running transaction in `ReCheckMode`
## [v0.19.3] - 2022-10-14
* (deps) [1381](https://github.com/evmos/ethermint/pull/1381) Bump sdk to `v0.45.9`
## [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/evmos/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/evmos/ethermint/pull/1021) Fix fee market migration.
* (feemarket) [tharsis#1021](https://github.com/tharsis/ethermint/pull/1021) Fix fee market migration.
## [v0.12.1] - 2022-03-29
### Bug Fixes
* (evm) [tharsis#1016](https://github.com/evmos/ethermint/pull/1016) Update validate basic check for storage state.
* (evm) [tharsis#1016](https://github.com/tharsis/ethermint/pull/1016) Update validate basic check for storage state.
## [v0.12.0] - 2022-03-24
### Bug Fixes
* (rpc) [tharsis#1012](https://github.com/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`.
* (rpc) [tharsis#1012](https://github.com/tharsis/ethermint/pull/1012) fix the tx hash in filter entries created by `eth_newPendingTransactionFilter`.
* (rpc) [tharsis#1006](https://github.com/tharsis/ethermint/pull/1006) Use `string` as the parameters type to correct ambiguous results.
* (ante) [tharsis#1004](https://github.com/tharsis/ethermint/pull/1004) Make `MaxTxGasWanted` configurable.
* (ante) [tharsis#991](https://github.com/tharsis/ethermint/pull/991) Set an upper bound to gasWanted to prevent DoS attack.
* (rpc) [tharsis#990](https://github.com/tharsis/ethermint/pull/990) Calculate reward values from all `MsgEthereumTx` from a block in `eth_feeHistory`.
## [v0.11.0] - 2022-03-06
### State Machine Breaking
* (ante) [tharsis#964](https://github.com/evmos/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/tharsis/ethermint/pull/964) add NewInfiniteGasMeterWithLimit for storing the user provided gas limit. Fixes block's consumed gas calculation in the block creation phase.
### Bug Fixes
* (rpc) [tharsis#975](https://github.com/evmos/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/tharsis/ethermint/pull/975) Fix unexpected `nil` values for `reward`, returned by `EffectiveGasTipValue(blockBaseFee)` in the `eth_feeHistory` RPC method.
### Improvements
* (rpc) [tharsis#979](https://github.com/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
- (rpc) [tharsis#979](https://github.com/tharsis/ethermint/pull/979) Add configurable timeouts to http server
- (rpc) [tharsis#988](https://github.com/tharsis/ethermint/pull/988) json-rpc server always use local rpc client
## [v0.10.1] - 2022-03-04
### Bug Fixes
* (rpc) [tharsis#970](https://github.com/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.
* (rpc) [tharsis#970](https://github.com/tharsis/ethermint/pull/970) Fix unexpected nil reward values on `eth_feeHistory` response
* (evm) [tharsis#529](https://github.com/tharsis/ethermint/issues/529) Add support return value on trace tx response.
### Improvements
* (rpc) [tharsis#968](https://github.com/evmos/ethermint/pull/968) Add some buffer to returned gas price to provide better default UX for client.
* (rpc) [tharsis#968](https://github.com/tharsis/ethermint/pull/968) Add some buffer to returned gas price to provide better default UX for client.
## [v0.10.0] - 2022-02-26
### API Breaking
* (ante) [tharsis#866](https://github.com/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.
* (ante) [tharsis#866](https://github.com/tharsis/ethermint/pull/866) `NewAnteHandler` constructor now receives a `HandlerOptions` field.
* (evm) [tharsis#849](https://github.com/tharsis/ethermint/pull/849) `PostTxProcessing` hook now takes an Ethereum tx `Receipt` and a `from` `Address` as arguments.
* (ante) [tharsis#916](https://github.com/tharsis/ethermint/pull/916) Don't check min-gas-price for eth tx if london hardfork enabled and feemarket enabled.
### State Machine Breaking
* (deps) [tharsis#912](https://github.com/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).
* (deps) [tharsis#912](https://github.com/tharsis/ethermint/pull/912) Bump Cosmos SDK version to [`v0.45.1`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.1)
* (evm) [tharsis#840](https://github.com/tharsis/ethermint/pull/840) Store empty topics as empty array rather than nil.
* (feemarket) [tharsis#822](https://github.com/tharsis/ethermint/pull/822) Update EIP1559 base fee in `BeginBlock`.
* (evm) [tharsis#817](https://github.com/tharsis/ethermint/pull/817) Use `effectiveGasPrice` in ante handler, add `effectiveGasPrice` to tx receipt.
* (evm) [tharsis#808](https://github.com/tharsis/ethermint/issues/808) increase nonce in ante handler for contract creation transaction.
* (evm) [tharsis#851](https://github.com/tharsis/ethermint/pull/851) fix contract address used in EVM, this issue is caused by [tharsis#808](https://github.com/tharsis/ethermint/issues/808).
* (evm) Reject invalid `MsgEthereumTx` wrapping tx
* (evm) Fix `SelfDestruct` opcode by deleting account code and state.
* (feemarket) [tharsis#855](https://github.com/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)
* (feemarket) [tharsis#855](https://github.com/tharsis/ethermint/pull/855) Consistent `BaseFee` check logic.
* (evm) [tharsis#729](https://github.com/tharsis/ethermint/pull/729) Refactor EVM `StateDB` implementation.
* (evm) [tharsis#945](https://github.com/tharsis/ethermint/pull/945) Bumb Go-ethereum version to [`v1.10.16`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.16)
### Features
* (ante) [tharsis#950](https://github.com/evmos/ethermint/pull/950) Add support for EIP712 signed Cosmos transactions
* (ante) [tharsis#950](https://github.com/tharsis/ethermint/pull/950) Add support for EIP712 signed Cosmos transactions
### Improvements
* (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.
* (types) [tharsis#884](https://github.com/tharsis/ethermint/pull/884) Introduce a new `EthAccountI` interface for EVM-compatible account types.
* (types) [tharsis#849](https://github.com/tharsis/ethermint/pull/849) Add `Type` function to distinguish EOAs from Contract accounts.
* (evm) [tharsis#826](https://github.com/tharsis/ethermint/issues/826) Improve allocation of bytes of `tx.To` address.
* (evm) [tharsis#827](https://github.com/tharsis/ethermint/issues/827) Speed up creation of event logs by using the slice insertion idiom with indices.
* (ante) [tharsis#819](https://github.com/tharsis/ethermint/pull/819) Remove redundant ante handlers
* (app) [tharsis#873](https://github.com/tharsis/ethermint/pull/873) Validate code hash in GenesisAccount
* (evm) [tharsis#901](https://github.com/tharsis/ethermint/pull/901) Support multiple `MsgEthereumTx` in single tx.
* (config) [tharsis#908](https://github.com/tharsis/ethermint/pull/908) Add `api.enable` flag for Cosmos SDK Rest server
* (feemarket) [tharsis#919](https://github.com/tharsis/ethermint/pull/919) Initialize baseFee in default genesis state.
* (feemarket) [tharsis#943](https://github.com/tharsis/ethermint/pull/943) Store the base fee as a module param instead of using state storage.
### Bug Fixes
* (rpc) [tharsis#955](https://github.com/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.
* (rpc) [tharsis#955](https://github.com/tharsis/ethermint/pull/955) Fix websocket server push duplicated messages to subscriber.
* (rpc) [tharsis#953](https://github.com/tharsis/ethermint/pull/953) Add `eth_signTypedData` api support.
* (log) [tharsis#948](https://github.com/tharsis/ethermint/pull/948) Redirect go-ethereum's logs to cosmos-sdk logger.
* (evm) [tharsis#884](https://github.com/tharsis/ethermint/pull/884) Support multiple account types on the EVM `StateDB`.
* (rpc) [tharsis#831](https://github.com/tharsis/ethermint/pull/831) Fix BaseFee value when height is specified.
* (evm) [tharsis#838](https://github.com/tharsis/ethermint/pull/838) Fix splitting of trace.Memory into 32 chunks.
* (rpc) [tharsis#860](https://github.com/tharsis/ethermint/pull/860) Fix `eth_getLogs` when specify blockHash without address/topics, and limit the response size.
* (rpc) [tharsis#865](https://github.com/tharsis/ethermint/pull/865) Fix RPC Filter parameters being ignored
* (evm) [tharsis#871](https://github.com/tharsis/ethermint/pull/871) Set correct nonce in `EthCall` and `EstimateGas` grpc query.
* (rpc) [tharsis#878](https://github.com/tharsis/ethermint/pull/878) Workaround to make GetBlock RPC api report correct block gas used.
* (rpc) [tharsis#900](https://github.com/tharsis/ethermint/pull/900) `newPendingTransactions` filter return ethereum tx hash.
* (rpc) [tharsis#933](https://github.com/tharsis/ethermint/pull/933) Fix `newPendingTransactions` subscription deadlock when a Websocket client exits without unsubscribing and the node errors.
* (evm) [tharsis#932](https://github.com/tharsis/ethermint/pull/932) Fix base fee check logic in state transition.
## [v0.9.0] - 2021-12-01
### State Machine Breaking
* (evm) [tharsis#802](https://github.com/evmos/ethermint/pull/802) Clear access list for each transaction
* (evm) [tharsis#802](https://github.com/tharsis/ethermint/pull/802) Clear access list for each transaction
### Improvements
* (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
* (app) [tharsis#794](https://github.com/tharsis/ethermint/pull/794) Setup in-place store migrators.
* (ci) [tharsis#784](https://github.com/tharsis/ethermint/pull/784) Enable automatic backport of PRs.
* (rpc) [tharsis#786](https://github.com/tharsis/ethermint/pull/786) Improve error message of `SendTransaction`/`SendRawTransaction` JSON-RPC APIs.
* (rpc) [tharsis#810](https://github.com/tharsis/ethermint/pull/810) Optimize tx index lookup in web3 rpc
### Bug Fixes
* (license) [tharsis#800](https://github.com/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
* (license) [tharsis#800](https://github.com/tharsis/ethermint/pull/800) Re-license project to [LGPLv3](https://choosealicense.com/licenses/lgpl-3.0/#) to comply with go-ethereum.
* (evm) [tharsis#794](https://github.com/tharsis/ethermint/pull/794) Register EVM gRPC `Msg` server.
* (rpc) [tharsis#781](https://github.com/tharsis/ethermint/pull/781) Fix get block invalid transactions filter.
* (rpc) [tharsis#782](https://github.com/tharsis/ethermint/pull/782) Fix wrong block gas limit returned by JSON-RPC.
* (evm) [tharsis#798](https://github.com/tharsis/ethermint/pull/798) Fix the semantic of `ForEachStorage` callback's return value
## [v0.8.1] - 2021-11-23
### Bug Fixes
* (feemarket) [tharsis#770](https://github.com/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.
* (feemarket) [tharsis#770](https://github.com/tharsis/ethermint/pull/770) Enable fee market (EIP1559) by default.
* (rpc) [tharsis#769](https://github.com/tharsis/ethermint/pull/769) Fix default Ethereum signer for JSON-RPC.
## [v0.8.0] - 2021-11-17
### State Machine Breaking
* (evm, ante) [tharsis#620](https://github.com/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
* (evm, ante) [tharsis#620](https://github.com/tharsis/ethermint/pull/620) Add fee market field to EVM `Keeper` and `AnteHandler`.
* (all) [tharsis#231](https://github.com/tharsis/ethermint/pull/231) Bump go-ethereum version to [`v1.10.9`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.9)
* (ante) [tharsis#703](https://github.com/tharsis/ethermint/pull/703) Fix some fields in transaction are not authenticated by signature.
* (evm) [tharsis#751](https://github.com/tharsis/ethermint/pull/751) don't revert gas refund logic when transaction reverted
### Features
* (rpc, evm) [tharsis#673](https://github.com/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`
* (rpc, evm) [tharsis#673](https://github.com/tharsis/ethermint/pull/673) Use tendermint events to store fee market basefee.
* (rpc) [tharsis#624](https://github.com/tharsis/ethermint/pull/624) Implement new JSON-RPC endpoints from latest geth version
* (evm) [tharsis#662](https://github.com/tharsis/ethermint/pull/662) Disable basefee for non london blocks
* (cmd) [tharsis#712](https://github.com/tharsis/ethermint/pull/712) add tx cli to build evm transaction
* (rpc) [tharsis#733](https://github.com/tharsis/ethermint/pull/733) add JSON_RPC endpoint `personal_unpair`
* (rpc) [tharsis#734](https://github.com/tharsis/ethermint/pull/734) add JSON_RPC endpoint `eth_feeHistory`
* (rpc) [tharsis#740](https://github.com/tharsis/ethermint/pull/740) add JSON_RPC endpoint `personal_initializeWallet`
* (rpc) [tharsis#743](https://github.com/tharsis/ethermint/pull/743) add JSON_RPC endpoint `debug_traceBlockByHash`
* (rpc) [tharsis#748](https://github.com/tharsis/ethermint/pull/748) add JSON_RPC endpoint `personal_listWallets`
* (rpc) [tharsis#754](https://github.com/tharsis/ethermint/pull/754) add JSON_RPC endpoint `debug_intermediateRoots`
### Bug Fixes
* (evm) [tharsis#746](https://github.com/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
* (evm) [tharsis#746](https://github.com/tharsis/ethermint/pull/746) Set EVM debugging based on tracer configuration.
* (app,cli) [tharsis#725](https://github.com/tharsis/ethermint/pull/725) Fix cli-config for `keys` command.
* (rpc) [tharsis#727](https://github.com/tharsis/ethermint/pull/727) Decode raw transaction using RLP.
* (rpc) [tharsis#661](https://github.com/tharsis/ethermint/pull/661) Fix OOM bug when creating too many filters using JSON-RPC.
* (evm) [tharsis#660](https://github.com/tharsis/ethermint/pull/660) Fix `nil` pointer panic in `ApplyNativeMessage`.
* (evm, test) [tharsis#649](https://github.com/tharsis/ethermint/pull/649) Test DynamicFeeTx.
* (evm) [tharsis#702](https://github.com/tharsis/ethermint/pull/702) Fix panic in web3 RPC handlers
* (rpc) [tharsis#720](https://github.com/tharsis/ethermint/pull/720) Fix `debug_traceTransaction` failure
* (rpc) [tharsis#741](https://github.com/tharsis/ethermint/pull/741) Fix `eth_getBlockByNumberAndHash` return with non eth txs
* (rpc) [tharsis#743](https://github.com/tharsis/ethermint/pull/743) Fix debug JSON RPC handler crash on non-existing block
### Improvements
* (tests) [tharsis#704](https://github.com/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
* (tests) [tharsis#704](https://github.com/tharsis/ethermint/pull/704) Introduce E2E testing framework for clients
* (deps) [tharsis#737](https://github.com/tharsis/ethermint/pull/737) Bump ibc-go to [`v2.0.0`](https://github.com/cosmos/ibc-go/releases/tag/v2.0.0)
* (rpc) [tharsis#671](https://github.com/tharsis/ethermint/pull/671) Don't pass base fee externally for `EthCall`/`EthEstimateGas` apis.
* (evm) [tharsis#674](https://github.com/tharsis/ethermint/pull/674) Refactor `ApplyMessage`, remove
`ApplyNativeMessage`.
* (rpc) [tharsis#714](https://github.com/evmos/ethermint/pull/714) remove `MsgEthereumTx` support in `TxConfig`
* (rpc) [tharsis#714](https://github.com/tharsis/ethermint/pull/714) remove `MsgEthereumTx` support in `TxConfig`
## [v0.7.2] - 2021-10-24
### Improvements
* (deps) [tharsis#692](https://github.com/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).
* (deps) [tharsis#692](https://github.com/tharsis/ethermint/pull/692) Bump Cosmos SDK version to [`v0.44.3`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.44.3).
* (rpc) [tharsis#679](https://github.com/tharsis/ethermint/pull/679) Fix file close handle.
* (deps) [tharsis#668](https://github.com/tharsis/ethermint/pull/668) Bump Tendermint version to [`v0.34.14`](https://github.com/tendermint/tendermint/releases/tag/v0.34.14).
### Bug Fixes
* (rpc) [tharsis#667](https://github.com/evmos/ethermint/issues/667) Fix `ExpandHome` restrictions bypass
* (rpc) [tharsis#667](https://github.com/tharsis/ethermint/issues/667) Fix `ExpandHome` restrictions bypass
## [v0.7.1] - 2021-10-08
### Bug Fixes
* (evm) [tharsis#650](https://github.com/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.
* (evm) [tharsis#650](https://github.com/tharsis/ethermint/pull/650) Fix panic when flattening the cache context in case transaction is reverted.
* (rpc, test) [tharsis#608](https://github.com/tharsis/ethermint/pull/608) Fix rpc test.
## [v0.7.0] - 2021-10-07
### API Breaking
* (rpc) [tharsis#400](https://github.com/evmos/ethermint/issues/400) Restructure JSON-RPC directory and rename server config
* (rpc) [tharsis#400](https://github.com/tharsis/ethermint/issues/400) Restructure JSON-RPC directory and rename server config
### Improvements
* (deps) [tharsis#621](https://github.com/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).
* (deps) [tharsis#621](https://github.com/tharsis/ethermint/pull/621) Bump IBC-go to [`v1.2.1`](https://github.com/cosmos/ibc-go/releases/tag/v1.2.1)
* (evm) [tharsis#613](https://github.com/tharsis/ethermint/pull/613) Refactor `traceTx`
* (deps) [tharsis#610](https://github.com/tharsis/ethermint/pull/610) Bump Cosmos SDK to [v0.44.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.44.1).
### Bug Fixes
* (rpc) [tharsis#642](https://github.com/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.
* (rpc) [tharsis#642](https://github.com/tharsis/ethermint/issues/642) Fix `eth_getLogs` when string is specified in filter's from or to fields
* (evm) [tharsis#616](https://github.com/tharsis/ethermint/issues/616) Fix halt on deeply nested stack of cache context. Stack is now flattened before iterating over the tx logs.
* (rpc, evm) [tharsis#614](https://github.com/tharsis/ethermint/issues/614) Use JSON for (un)marshaling tx `Log`s from events.
* (rpc) [tharsis#611](https://github.com/tharsis/ethermint/pull/611) Fix panic on JSON-RPC when querying for an invalid block height.
* (cmd) [tharsis#483](https://github.com/tharsis/ethermint/pull/483) Use config values on genesis accounts.
## [v0.6.0] - 2021-09-29
### State Machine Breaking
* (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
* (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
### API Breaking
* (evm) [tharsis#469](https://github.com/evmos/ethermint/pull/469) Deprecate `YoloV3Block` and `EWASMBlock` from `ChainConfig`
* (evm) [tharsis#469](https://github.com/tharsis/ethermint/pull/469) Deprecate `YoloV3Block` and `EWASMBlock` from `ChainConfig`
### Features
* (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
* (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
### Bug Fixes
* (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.
* (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.
### Improvements
* (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
* (evm) [tharsis#461](https://github.com/tharsis/ethermint/pull/461) Increase performance of `StateDB` transaction log storage (r/w).
* (evm) [tharsis#566](https://github.com/tharsis/ethermint/pull/566) Introduce `stateErr` store in `StateDB` to avoid meaningless operations if any error happened before
* (rpc, evm) [tharsis#587](https://github.com/tharsis/ethermint/pull/587) Apply bloom filter when query ethlogs with range of blocks
* (evm) [tharsis#586](https://github.com/tharsis/ethermint/pull/586) Benchmark evm keeper
## [v0.5.0] - 2021-08-20
### State Machine Breaking
* (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>`
* (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>`
in order to clearly distinguish permanent vs impermanent components.
* (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
* (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
the Tracer type used to collect execution traces from the EVM transaction execution.
* (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
* (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
different tx state and events.
* (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
* (evm) [tharsis#342](https://github.com/tharsis/ethermint/issues/342) Don't clear balance when resetting the account.
* (evm) [tharsis#334](https://github.com/tharsis/ethermint/pull/334) Log index changed to the index in block rather than
tx.
* (evm) [tharsis#399](https://github.com/evmos/ethermint/pull/399) Exception in sub-message call reverts the call if it's not propagated.
* (evm) [tharsis#399](https://github.com/tharsis/ethermint/pull/399) Exception in sub-message call reverts the call if it's not propagated.
### API Breaking
* (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:
* (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:
* 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/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.
* (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.
### Improvements
* (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.
* (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.
### Bug Fixes
* (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.
* (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.
## [v0.4.1] - 2021-03-01
@ -659,11 +373,9 @@ 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
@ -702,7 +414,7 @@ the Tracer type used to collect execution traces from the EVM transaction execut
### Improvements
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.39.2)
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2)
* (deps) [tharsis#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+.
* (evm) [tharsis#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
* (deps) [tharsis#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9)

View File

@ -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/evmos/ethermint/issues/new/choose) or
[find](https://github.com/evmos/ethermint/issues) an issue you'd like to help with
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
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/evmos/ethermint/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
[good first issues](https://github.com/tharsis/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/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).
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).
## 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/evmos/ethermint`, and do all the work there.
`$GOPATH/src/github.com/tharsis/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/evmos/ethermint`)
- Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/tharsis/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/evmos/ethermint, or your fork (using `git remote add origin`)
- create a development branch either on github.com/tharsis/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/evmos/ethermint/blob/main/docs/architecture/PROCESS.md)
[ADR Creation Process](https://github.com/tharsis/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**

351
DXNS_MODULES_README.md Normal file
View File

@ -0,0 +1,351 @@
# Vulcanize chiba-clonk gql
> Browser : http://localhost:9473 for gql
## Start server
```shell
./build/chibaclonkd start --gql-playground --gql-server
```
Basic node status:
```graphql
{
getStatus {
version
node {
id
network
moniker
}
sync {
latest_block_height
catching_up
}
num_peers
peers {
is_outbound
remote_ip
}
disk_usage
}
}
```
Full node status:
```graphql
{
getStatus {
version
node {
id
network
moniker
}
sync {
latest_block_hash
latest_block_time
latest_block_height
catching_up
}
validator {
address
voting_power
proposer_priority
}
validators {
address
voting_power
proposer_priority
}
num_peers
peers {
node {
id
network
moniker
}
is_outbound
remote_ip
}
disk_usage
}
}
```
Get records by IDs.
```graphql
{
getRecordsByIds(ids: ["QmYDtNCKtTu6u6jaHaFAC5PWZXcj7fAmry6NoWwMaixFHz"]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
```
Query records.
```graphql
{
queryRecords(attributes: [{ key: "type", value: { string: "crn:bot" } }]) {
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
```
Get account details:
```graphql
{
getAccounts(addresses: ["cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094"]) {
address
pubKey
number
sequence
balance {
type
quantity
}
}
}
```
Query bonds:
```graphql
{
queryBonds(
attributes: [
{
key: "owner"
value: { string: "cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094" }
}
]
) {
id
owner
balance {
type
quantity
}
}
}
```
Get bonds by IDs.
```graphql
{
getBondsByIds(ids :
[
"1c2b677cb2a27c88cc6bf8acf675c94b69051125b40c4fd073153b10f046dd87",
"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440"
])
{
id
owner
balance{
type
quantity
}
}
}
```
Query Bonds by Owner
```graphql
{
queryBondsByOwner(ownerAddresses: ["ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"])
{
owner
bonds{
id
owner
balance
{
type
quantity
}
}
}
}
```
Query auctions by ids
```graphql
{
getAuctionsByIds(ids: ["be98f2073c246194276554eefdb4c95b682a35a0f06fbe619a6da57c10c93e90"]){
id
ownerAddress
createTime
minimumBid{
type
quantity
}
commitFee{
type
quantity
}
commitsEndTime
revealFee{
type
quantity
}
revealsEndTime
winnerBid{
type
quantity
}
winnerPrice{
type
quantity
}
winnerAddress
bids{
bidderAddress
commitHash
commitTime
commitFee{
type
quantity
}
revealFee{
type
quantity
}
revealTime
bidAmount{
type
quantity
}
status
}
}
}
```
LookUp Authorities
```graphql
{
lookupAuthorities(names: []){
ownerAddress
ownerAddress
height
bondId
status
expiryTime
auction {
id
ownerAddress
createTime
minimumBid{
type
quantity
}
commitFee{
type
quantity
}
commitsEndTime
revealFee{
type
quantity
}
revealsEndTime
winnerBid{
type
quantity
}
winnerPrice{
type
quantity
}
winnerAddress
bids{
bidderAddress
commitHash
commitTime
commitFee{
type
quantity
}
revealFee{
type
quantity
}
revealTime
bidAmount{
type
quantity
}
status
}
}
}
}
```
LookUp Names
```graphql
{
lookupNames(names: ["crn://hello/test"]){
latest{
id
height
}
history{
id
height
}
}
}
```
Resolve Names
```graphql
{
resolveNames(names: ["asd"]){
id
names
bondId
createTime
expiryTime
owners
attributes {
key
value {
string
}
}
}
}
```

View File

@ -1,14 +1,14 @@
FROM golang:alpine AS build-env
# Install dependencies
RUN apk add --update git build-base linux-headers
# Set up dependencies
ENV PACKAGES git build-base
# Set working directory for the build
WORKDIR /go/src/github.com/cerc-io/laconicd
WORKDIR /go/src/github.com/vulcanize/chiba-clonk
# Cache Go modules
COPY go.mod go.sum ./
RUN go mod download
# Install dependencies
RUN apk add --update $PACKAGES
RUN apk add linux-headers
# Add source files
COPY . .
@ -17,14 +17,14 @@ COPY . .
RUN make build
# Final image
FROM alpine:3.17.0
FROM alpine:3.15
# Install ca-certificates
RUN apk add --update ca-certificates jq curl
RUN apk add --update ca-certificates jq
WORKDIR /
# 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/vulcanize/chiba-clonk/build/chibaclonkd /usr/bin/chibaclonkd
WORKDIR /
# Run laconicd by default
CMD ["laconicd"]
# Run chibaclonkd by default
CMD ["chibaclonkd"]

281
Makefile Normal file → Executable file
View File

@ -7,16 +7,14 @@ TMVERSION := $(shell go list -m github.com/tendermint/tendermint | sed 's:.* ::'
COMMIT := $(shell git log -1 --format='%H')
LEDGER_ENABLED ?= true
BINDIR ?= $(GOPATH)/bin
LACONIC_BINARY = laconicd
LACONIC_DIR = laconic
CHIBACLONK_BINARY = chibaclonkd
CHIBACLONK_DIR = chibaclonk
BUILDDIR ?= $(CURDIR)/build
SIMAPP = ./app
HTTPS_GIT := https://github.com/cerc-io/laconicd.git
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
HTTPS_GIT := https://github.com/vulcanize/chiba-clonk.git
DOCKER := $(shell which docker)
# 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
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
export GO111MODULE = on
@ -51,6 +49,9 @@ 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))
@ -61,43 +62,34 @@ build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags))
# process linker flags
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=laconic \
-X github.com/cosmos/cosmos-sdk/version.AppName=$(LACONIC_BINARY) \
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=chibaclonk \
-X github.com/cosmos/cosmos-sdk/version.AppName=$(CHIBACLONK_BINARY) \
-X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \
-X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \
-X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \
-X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION)
ifeq ($(ENABLE_ROCKSDB),true)
BUILD_TAGS += rocksdb_build
test_tags += rocksdb_build
else
$(info 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
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=cleveldb
endif
ifeq (badgerdb,$(findstring badgerdb,$(COSMOS_BUILD_OPTIONS)))
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=badgerdb
BUILD_TAGS += badgerdb
endif
# handle rocksdb
ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS)))
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))
@ -105,17 +97,20 @@ 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
# check if no optimization option is passed
# used for remote debugging
ifneq (,$(findstring nooptimization,$(COSMOS_BUILD_OPTIONS)))
BUILD_FLAGS += -gcflags "all=-N -l"
endif
all: tools build lint test
# # The below include contains the tools and runsim targets.
# include contrib/devtools/Makefile
@ -127,15 +122,15 @@ BUILD_TARGETS := build install
build: BUILD_ARGS=-o $(BUILDDIR)/
build-linux:
GOOS=linux GOARCH=amd64 LEDGER_ENABLED=false $(MAKE) build
GOOS=linux GOARCH=$(if $(findstring aarch64,$(shell uname -m)) || $(findstring arm64,$(shell uname -m)),arm64,amd64) LEDGER_ENABLED=false $(MAKE) build
$(BUILD_TARGETS): go.sum $(BUILDDIR)/
go $@ $(BUILD_FLAGS) $(BUILD_ARGS) ./...
go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./...
$(BUILDDIR)/:
mkdir -p $(BUILDDIR)/
.PHONY: build build-linux
.PHONY: build build-linux cosmovisor
docker-build:
# TODO replace with kaniko
@ -143,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 laconicd || true
docker rm ethermint || true
# create a new container from the latest image
docker create --name laconic -t -i ${DOCKER_IMAGE}:${DOCKER_TAG} laconicd
docker create --name ethermint -t -i tharsis/ethermint:latest ethermint
# move the binaries to the ./build directory
mkdir -p ./build/
docker cp laconic:/usr/bin/laconicd ./build/
docker cp ethermint:/usr/bin/ethermintd ./build/
$(MOCKS_DIR):
mkdir -p $(MOCKS_DIR)
@ -163,7 +158,7 @@ clean:
all: build
build-all: tools build lint test vulncheck
build-all: tools build lint test
.PHONY: distclean clean build-all
@ -171,8 +166,8 @@ build-all: tools build lint test vulncheck
### Releasing ###
###############################################################################
PACKAGE_NAME:=github.com/cerc-io/laconicd
GOLANG_CROSS_VERSION = v1.19
PACKAGE_NAME:=github.com/tharsis/ethermint
GOLANG_CROSS_VERSION = v1.17.1
GOPATH ?= '$(HOME)/go'
release-dry-run:
docker run \
@ -183,8 +178,8 @@ release-dry-run:
-v `pwd`:/go/src/$(PACKAGE_NAME) \
-v ${GOPATH}/pkg:/go/pkg \
-w /go/src/$(PACKAGE_NAME) \
ghcr.io/goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
--rm-dist --skip-validate --skip-publish --snapshot
ghcr.io/troian/golang-cross:${GOLANG_CROSS_VERSION} \
--rm-dist --skip-validate --skip-publish
release:
@if [ ! -f ".release-env" ]; then \
@ -199,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/goreleaser/goreleaser-cross:${GOLANG_CROSS_VERSION} \
ghcr.io/troian/golang-cross:${GOLANG_CROSS_VERSION} \
release --rm-dist --skip-validate
.PHONY: release-dry-run release
@ -220,7 +215,7 @@ RUNSIM = $(TOOLS_DESTDIR)/runsim
runsim: $(RUNSIM)
$(RUNSIM):
@echo "Installing runsim..."
@(cd /tmp && ${GO_MOD} go install github.com/cosmos/tools/cmd/runsim@master)
@(cd /tmp && ${GO_MOD} go get github.com/cosmos/tools/cmd/runsim@master)
statik: $(STATIK)
$(STATIK):
@ -237,7 +232,7 @@ endif
ifeq (, $(shell which go-bindata))
@echo "Installing go-bindata..."
@go get github.com/kevinburke/go-bindata/go-bindata@v3
@go get github.com/kevinburke/go-bindata/go-bindata
else
@echo "go-bindata already installed; skipping..."
endif
@ -256,6 +251,14 @@ 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
@ -281,10 +284,6 @@ go.sum: go.mod
go mod verify
go mod tidy
vulncheck: $(BUILDDIR)/
GOBIN=$(BUILDDIR) go install golang.org/x/vuln/cmd/govulncheck@latest
$(BUILDDIR)/govulncheck ./...
###############################################################################
### Documentation ###
###############################################################################
@ -300,7 +299,7 @@ update-swagger-docs: statik
.PHONY: update-swagger-docs
godocs:
@echo "--> Wait a few seconds and visit http://localhost:6060/pkg/github.com/cerc-io/laconicd/types"
@echo "--> Wait a few seconds and visit http://localhost:6060/pkg/github.com/tharsis/ethermint/types"
godoc -http=:6060
###############################################################################
@ -316,7 +315,7 @@ TEST_TARGETS := test-unit test-unit-cover test-race
# Test runs-specific rules. To add a new test target, just add
# a new rule, customise ARGS or TEST_PACKAGES ad libitum, and
# append the new rule to the TEST_TARGETS list.
test-unit: ARGS=-timeout=10m -race -test.v -skip $(SKIP_UNIT_TESTS)
test-unit: ARGS=-timeout=10m -race
test-unit: TEST_PACKAGES=$(PACKAGES_UNIT)
test-race: ARGS=-race
@ -334,16 +333,13 @@ else
endif
test-import:
go test -run TestImporterTestSuite -timeout=20m -v --vet=off github.com/cerc-io/laconicd/tests/importer
go test -run TestImporterTestSuite -v --vet=off github.com/tharsis/ethermint/tests/importer
test-rpc:
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 10 -m "rpc" -r "true"
run-integration-tests:
@nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh
.PHONY: run-integration-tests
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
test-integration:
./scripts/integration-test-all.sh -t "integration" -q 1 -z 1 -s 2 -m "integration" -r "true"
test-rpc-pending:
./scripts/integration-test-all.sh -t "pending" -q 1 -z 1 -s 2 -m "pending" -r "true"
@ -355,6 +351,53 @@ test-solidity:
.PHONY: run-tests test test-all test-import test-rpc test-contract test-solidity $(TEST_TARGETS)
test-sim-nondeterminism:
@echo "Running non-determinism test..."
@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}/.$(CHIBACLONK_DIR)/config/genesis.json will be used."
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation -Genesis=${HOME}/.$(CHIBACLONK_DIR)/config/genesis.json \
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
test-sim-import-export: runsim
@echo "Running application import/export simulation. This may take several minutes..."
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport
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
@echo "Running multi-seed custom genesis simulation..."
@echo "By default, ${HOME}/.$(CHIBACLONK_DIR)/config/genesis.json will be used."
@$(BINDIR)/runsim -Genesis=${HOME}/.$(CHIBACLONK_DIR)/config/genesis.json -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
test-sim-multi-seed-long: runsim
@echo "Running long multi-seed application simulation. This may take awhile!"
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation
test-sim-multi-seed-short: runsim
@echo "Running short multi-seed application simulation. This may take awhile!"
@$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation
test-sim-benchmark-invariants:
@echo "Running simulation invariant benchmarks..."
@go test -mod=readonly $(SIMAPP) -benchmem -bench=BenchmarkInvariants -run=^$ \
-Enabled=true -NumBlocks=1000 -BlockSize=200 \
-Period=1 -Commit=true -Seed=57 -v -timeout 24h
.PHONY: \
test-sim-nondeterminism \
test-sim-custom-genesis-fast \
test-sim-import-export \
test-sim-after-import \
test-sim-custom-genesis-multi-seed \
test-sim-multi-seed-short \
test-sim-multi-seed-long \
test-sim-benchmark-invariants
benchmark:
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
@ -365,19 +408,14 @@ benchmark:
###############################################################################
lint:
@@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" \
golangci-lint run --out-format=tab
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 lint-py
.PHONY: lint lint-fix
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
@ -388,62 +426,73 @@ format-fix:
### Protobuf ###
###############################################################################
# ------
# NOTE: Link to the tendermintdev/sdk-proto-gen docker images:
# https://hub.docker.com/r/tendermintdev/sdk-proto-gen/tags
#
protoVer=v0.7
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
protoImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
# ------
# NOTE: cosmos/proto-builder image is needed because clang-format is not installed
# on the tendermintdev/sdk-proto-gen docker image.
# Link to the cosmos/proto-builder docker images:
# https://github.com/cosmos/cosmos-sdk/pkgs/container/proto-builder
#
protoCosmosVer=0.11.2
protoCosmosName=ghcr.io/cosmos/proto-builder:$(protoCosmosVer)
protoCosmosImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoCosmosName)
# ------
# NOTE: Link to the yoheimuta/protolint docker images:
# https://hub.docker.com/r/yoheimuta/protolint/tags
#
protolintVer=0.42.2
protolintName=yoheimuta/protolint:$(protolintVer)
protolintImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protolintName)
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)
# ------
# NOTE: If you are experiencing problems running these commands, try deleting
# the docker images and execute the desired command again.
#
proto-all: proto-format proto-lint proto-gen
proto-gen:
@echo "Generating Protobuf files"
$(protoImage) sh ./scripts/protocgen.sh
@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) \
sh ./scripts/protocgen.sh; fi
# TODO: Rethink API docs generation
# proto-swagger-gen:
# @echo "Generating Protobuf Swagger"
# $(protoImage) sh ./scripts/protoc-swagger-gen.sh
proto-swagger-gen:
@echo "Generating Protobuf Swagger"
@./scripts/proto-tools-installer.sh
@./scripts/protoc-swagger-gen.sh
proto-format:
@echo "Formatting Protobuf files"
$(protoCosmosImage) find ./ -name *.proto -exec clang-format -i {} \;
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoFmt}$$"; then docker start -a $(containerProtoFmt); else docker run --name $(containerProtoFmt) -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \
find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi
# NOTE: The linter configuration lives in .protolint.yaml
proto-lint:
@echo "Linting Protobuf files"
$(protolintImage) lint ./proto
@$(DOCKER_BUF) lint --error-format=json
proto-check-breaking:
@echo "Checking Protobuf files for breaking changes"
$(protoImage) buf breaking --against $(HTTPS_GIT)#branch=main
@$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main
.PHONY: proto-all proto-gen proto-gen-any proto-format proto-lint proto-check-breaking
TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.12/proto/tendermint
GOGO_PROTO_URL = https://raw.githubusercontent.com/regen-network/protobuf/cosmos
COSMOS_SDK_URL = https://raw.githubusercontent.com/cosmos/cosmos-sdk/v0.43.0
COSMOS_PROTO_URL = https://raw.githubusercontent.com/regen-network/cosmos-proto/master
TM_CRYPTO_TYPES = third_party/proto/tendermint/crypto
TM_ABCI_TYPES = third_party/proto/tendermint/abci
TM_TYPES = third_party/proto/tendermint/types
GOGO_PROTO_TYPES = third_party/proto/gogoproto
COSMOS_PROTO_TYPES = third_party/proto/cosmos_proto
proto-update-deps:
@mkdir -p $(GOGO_PROTO_TYPES)
@curl -sSL $(GOGO_PROTO_URL)/gogoproto/gogo.proto > $(GOGO_PROTO_TYPES)/gogo.proto
@mkdir -p $(COSMOS_PROTO_TYPES)
@curl -sSL $(COSMOS_PROTO_URL)/cosmos.proto > $(COSMOS_PROTO_TYPES)/cosmos.proto
## Importing of tendermint protobuf definitions currently requires the
## use of `sed` in order to build properly with cosmos-sdk's proto file layout
## (which is the standard Buf.build FILE_LAYOUT)
## Issue link: https://github.com/tendermint/tendermint/issues/5021
@mkdir -p $(TM_ABCI_TYPES)
@curl -sSL $(TM_URL)/abci/types.proto > $(TM_ABCI_TYPES)/types.proto
@mkdir -p $(TM_TYPES)
@curl -sSL $(TM_URL)/types/types.proto > $(TM_TYPES)/types.proto
@mkdir -p $(TM_CRYPTO_TYPES)
@curl -sSL $(TM_URL)/crypto/proof.proto > $(TM_CRYPTO_TYPES)/proof.proto
@curl -sSL $(TM_URL)/crypto/keys.proto > $(TM_CRYPTO_TYPES)/keys.proto
.PHONY: proto-all proto-gen proto-gen-any proto-swagger-gen proto-format proto-lint proto-check-breaking proto-update-deps
###############################################################################
### Localnet ###
@ -459,19 +508,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\laconicd\Z laconicd/node "./laconicd testnet --v 4 -o /laconicd --keyring-backend=test --ip-addresses laconicdnode0,laconicdnode1,laconicdnode2,laconicdnode3"
IF not exist "build/node0/$(CHIBACLONK_BINARY)/config/genesis.json" docker run --rm -v $(CURDIR)/build\ethermint\Z chibaclonkd/node sh -c "chibaclonkd testnet init-files --v 4 --keyring-backend=test"
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 "./laconicd testnet --v 4 -o /laconicd --keyring-backend=test --ip-addresses laconicdnode0,laconicdnode1,laconicdnode2,laconicdnode3"; fi
if ! [ -f localnet-setup/node0/$(CHIBACLONK_BINARY)/config/genesis.json ]; then docker run --rm -v $(CURDIR)/localnet-setup:/localnet-setup:Z chibaclonkd/node sh -c "chibaclonkd testnet init-files --v 4 --keyring-backend=test"; fi
docker-compose up -d
endif
# Stop testnet
localnet-stop:
docker-compose down
docker-compose down -v
# Clean testnet
localnet-clean:
@ -482,19 +531,19 @@ localnet-clean:
localnet-unsafe-reset:
docker-compose down
ifeq ($(OS),Windows_NT)
@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"
@docker run --rm -v $(CURDIR)\localnet-setup\node0\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node1\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node2\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)\localnet-setup\node3\chibaclonkd:chibaclonk\Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
else
@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/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"
@docker run --rm -v $(CURDIR)/localnet-setup/node0/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node1/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node2/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
@docker run --rm -v $(CURDIR)/localnet-setup/node3/chibaclonkd:/chibaclonk:Z chibaclonkd/node "chibaclonkd unsafe-reset-all --home=/chibaclonk"
endif
# Clean testnet
localnet-show-logstream:
docker-compose logs --tail=1000 -f
.PHONY: build-docker-local-laconic localnet-start localnet-stop
.PHONY: build-docker-local-ethermint localnet-start localnet-stop

View File

@ -1,38 +1,78 @@
<!--
parent:
order: false
-->
<div align="center">
<h1> Laconic Network </h1>
<h1> Ethermint </h1>
</div>
![banner](docs/laconic.jpeg)
![banner](docs/ethermint.jpg)
<div align="center">
<a href="https://github.com/tharsis/ethermint/releases/latest">
<img alt="Version" src="https://img.shields.io/github/tag/tharsis/ethermint.svg" />
</a>
<a href="https://github.com/tharsis/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/tharsis/ethermint">
<img alt="GoDoc" src="https://godoc.org/github.com/tharsis/ethermint?status.svg" />
</a>
<a href="https://goreportcard.com/report/github.com/tharsis/ethermint">
<img alt="Go report card" src="https://goreportcard.com/badge/github.com/tharsis/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/tharsis/ethermint/actions?query=branch%3Amain+workflow%3ALint">
<img alt="Lint Status" src="https://github.com/tharsis/ethermint/actions/workflows/lint.yml/badge.svg?branch=main" />
</a>
<a href="https://codecov.io/gh/tharsis/ethermint">
<img alt="Code Coverage" src="https://codecov.io/gh/tharsis/ethermint/branch/main/graph/badge.svg" />
</a>
</div>
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.
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.19+](https://golang.org/dl/)
**Note**: Requires [Go 1.17+](https://golang.org/dl/)
## Installation
For prerequisites and detailed build instructions please read the Evmos [Installation](https://evmos.dev/quickstart/installation.html) instructions. Once the dependencies are installed, run:
```bash
make install
```
## Usage
Or check out the latest [release](https://github.com/tharsis/ethermint/releases).
To quickly get started with a single node fixture, run:
## Quick Start
```bash
./init.sh
```
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/tharsis/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.

17
app/addr_prefixes.go Normal file
View File

@ -0,0 +1,17 @@
package app
import (
sdk "github.com/cosmos/cosmos-sdk/types"
cmdcfg "github.com/tharsis/ethermint/cmd/config"
)
// sdk config
func init() {
config := sdk.GetConfig()
cmdcfg.SetBech32Prefixes(config)
cmdcfg.SetBip44CoinType(config)
config.Seal()
cmdcfg.RegisterDenoms()
}

View File

@ -6,15 +6,13 @@ import (
tmlog "github.com/tendermint/tendermint/libs/log"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
)
const (
@ -25,11 +23,7 @@ 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, error) {
if err := options.validate(); err != nil {
return nil, err
}
func NewAnteHandler(options HandlerOptions) sdk.AnteHandler {
return func(
ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) {
@ -46,14 +40,11 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
// handle as *evmtypes.MsgEthereumTx
anteHandler = newEthAnteHandler(options)
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
// Deprecated: Handle as normal Cosmos SDK tx, except signature is checked for Legacy EIP712 representation
anteHandler = NewLegacyCosmosAnteHandlerEip712(options)
case "/ethermint.types.v1.ExtensionOptionDynamicFeeTx":
// cosmos-sdk tx with dynamic fee extension
anteHandler = newCosmosAnteHandler(options)
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
anteHandler = newCosmosAnteHandlerEip712(options)
default:
return ctx, errorsmod.Wrapf(
errortypes.ErrUnknownExtensionOptions,
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrUnknownExtensionOptions,
"rejecting tx with unsupported extension option: %s", typeURL,
)
}
@ -67,16 +58,16 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
case sdk.Tx:
anteHandler = newCosmosAnteHandler(options)
default:
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
}
return anteHandler(ctx, tx, sim)
}, nil
}
}
func Recover(logger tmlog.Logger, err *error) {
if r := recover(); r != nil {
*err = errorsmod.Wrapf(errortypes.ErrPanic, "%v", r)
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r)
if e, ok := r.(error); ok {
logger.Error(
@ -101,48 +92,12 @@ var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsu
func DefaultSigVerificationGasConsumer(
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
) error {
pubkey := sig.PubKey
switch pubkey := pubkey.(type) {
case *ethsecp256k1.PubKey:
// support for ethereum ECDSA secp256k1 keys
_, ok := sig.PubKey.(*ethsecp256k1.PubKey)
if ok {
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
return nil
case multisig.PubKey:
// Multisig keys
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
if !ok {
return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data)
}
return ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence)
default:
return authante.DefaultSigVerificationGasConsumer(meter, sig, params)
}
}
// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature
func ConsumeMultisignatureVerificationGas(
meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey,
params authtypes.Params, accSeq uint64,
) error {
size := sig.BitArray.Count()
sigIndex := 0
for i := 0; i < size; i++ {
if !sig.BitArray.GetIndex(i) {
continue
}
sigV2 := signing.SignatureV2{
PubKey: pubkey.GetPubKeys()[i],
Data: sig.Signatures[sigIndex],
Sequence: accSeq,
}
err := DefaultSigVerificationGasConsumer(meter, sigV2, params)
if err != nil {
return err
}
sigIndex++
}
return nil
return authante.DefaultSigVerificationGasConsumer(meter, sig, params)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
/*
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

View File

@ -3,25 +3,22 @@ package ante
import (
"fmt"
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
ibcante "github.com/cosmos/ibc-go/v5/modules/core/ante"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/ethereum/eip712"
ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/ethereum/eip712"
ethermint "github.com/tharsis/ethermint/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
var ethermintCodec codec.ProtoCodecMarshaler
@ -32,47 +29,19 @@ func init() {
ethermintCodec = codec.NewProtoCodec(registry)
}
// Deprecated: NewLegacyCosmosAnteHandlerEip712 creates an AnteHandler to process legacy EIP-712
// transactions, as defined by the presence of an ExtensionOptionsWeb3Tx extension.
func NewLegacyCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
RejectMessagesDecorator{}, // reject MsgEthereumTxs
authante.NewSetUpContextDecorator(),
authante.NewValidateBasicDecorator(),
authante.NewTxTimeoutHeightDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
authante.NewValidateMemoDecorator(options.AccountKeeper),
authante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
authante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
// SetPubKeyDecorator must be called before all signature verification decorators
authante.NewSetPubKeyDecorator(options.AccountKeeper),
authante.NewValidateSigCountDecorator(options.AccountKeeper),
authante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
// Note: signature verification uses EIP instead of the cosmos signature validator
NewLegacyEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
authante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
)
}
// Deprecated: LegacyEip712SigVerificationDecorator Verify all signatures for a tx and return an error if any are invalid. Note,
// the LegacyEip712SigVerificationDecorator decorator will not get executed on ReCheck.
// NOTE: As of v0.20.0, EIP-712 signature verification is handled by the ethsecp256k1 public key (see ethsecp256k1.go)
// Eip712SigVerificationDecorator Verify all signatures for a tx and return an error if any are invalid. Note,
// the Eip712SigVerificationDecorator decorator will not get executed on ReCheck.
//
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
// CONTRACT: Tx must implement SigVerifiableTx interface
type LegacyEip712SigVerificationDecorator struct {
type Eip712SigVerificationDecorator struct {
ak evmtypes.AccountKeeper
signModeHandler authsigning.SignModeHandler
}
// Deprecated: NewLegacyEip712SigVerificationDecorator creates a new LegacyEip712SigVerificationDecorator
func NewLegacyEip712SigVerificationDecorator(
ak evmtypes.AccountKeeper,
signModeHandler authsigning.SignModeHandler,
) LegacyEip712SigVerificationDecorator {
return LegacyEip712SigVerificationDecorator{
// NewEip712SigVerificationDecorator creates a new Eip712SigVerificationDecorator
func NewEip712SigVerificationDecorator(ak evmtypes.AccountKeeper, signModeHandler authsigning.SignModeHandler) Eip712SigVerificationDecorator {
return Eip712SigVerificationDecorator{
ak: ak,
signModeHandler: signModeHandler,
}
@ -80,11 +49,7 @@ func NewLegacyEip712SigVerificationDecorator(
// AnteHandle handles validation of EIP712 signed cosmos txs.
// it is not run on RecheckTx
func (svd LegacyEip712SigVerificationDecorator) 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)
@ -92,12 +57,12 @@ func (svd LegacyEip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
sigTx, ok := tx.(authsigning.SigVerifiableTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
}
authSignTx, ok := tx.(authsigning.Tx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
}
// stdSigs contains the sequence number, account number, and signatures.
@ -111,16 +76,12 @@ func (svd LegacyEip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
// EIP712 allows just one signature
if len(sigs) != 1 {
return ctx, errorsmod.Wrapf(
errortypes.ErrTooManySignatures,
"invalid number of signers (%d); EIP712 signatures allows just one signature",
len(sigs),
)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
}
// check that signer length and signature length are the same
if len(sigs) != len(signerAddrs) {
return ctx, errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "invalid number of signers; expected: %d, got %d", len(signerAddrs), len(sigs))
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
}
// EIP712 has just one signature, avoid looping here and only read index 0
@ -135,13 +96,13 @@ func (svd LegacyEip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
// retrieve pubkey
pubKey := acc.GetPubKey()
if !simulate && pubKey == nil {
return ctx, errorsmod.Wrap(errortypes.ErrInvalidPubKey, "pubkey on account is not set")
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
}
// Check account sequence number.
if sig.Sequence != acc.GetSequence() {
return ctx, errorsmod.Wrapf(
errortypes.ErrWrongSequence,
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrWrongSequence,
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
)
}
@ -167,7 +128,7 @@ func (svd LegacyEip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
if err := VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
return ctx, errorsmod.Wrap(errortypes.ErrUnauthorized, errMsg.Error())
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg.Error())
}
return next(ctx, tx, simulate)
@ -185,12 +146,12 @@ func VerifySignature(
switch data := sigData.(type) {
case *signing.SingleSignatureData:
if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
return errorsmod.Wrapf(errortypes.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
return sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
}
// Note: this prevents the user from sending trash data in the signature field
// Note: this prevents the user from sending thrash data in the signature field
if len(data.Signature) != 0 {
return errorsmod.Wrap(errortypes.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
return sdkerrors.Wrap(sdkerrors.ErrTooManySignatures, "invalid signature value; EIP712 must have the cosmos transaction signature empty")
}
// @contract: this code is reached only when Msg has Web3Tx extension (so this custom Ante handler flow),
@ -198,7 +159,7 @@ func VerifySignature(
msgs := tx.GetMsgs()
if len(msgs) == 0 {
return errorsmod.Wrap(errortypes.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
return sdkerrors.Wrap(sdkerrors.ErrNoSignatures, "tx doesn't contain any msgs to verify signature")
}
txBytes := legacytx.StdSignBytes(
@ -215,33 +176,39 @@ func VerifySignature(
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
if err != nil {
return errorsmod.Wrapf(err, "failed to parse chain-id: %s", signerData.ChainID)
return sdkerrors.Wrapf(err, "failed to parse chainID: %s", signerData.ChainID)
}
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
if !ok {
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
}
opts := txWithExtensions.GetExtensionOptions()
if len(opts) != 1 {
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain expected amount of extension options")
}
extOpt, ok := opts[0].GetCachedValue().(*ethermint.ExtensionOptionsWeb3Tx)
var optIface ethermint.ExtensionOptionsWeb3TxI
if err := ethermintCodec.UnpackAny(opts[0], &optIface); err != nil {
return sdkerrors.Wrap(err, "failed to proto-unpack ExtensionOptionsWeb3Tx")
}
extOpt, ok := optIface.(*ethermint.ExtensionOptionsWeb3Tx)
if !ok {
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "unknown extension option")
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "unknown extension option")
}
if extOpt.TypedDataChainID != signerChainID.Uint64() {
return errorsmod.Wrap(errortypes.ErrInvalidChainID, "invalid chain-id")
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "invalid chainID")
}
if len(extOpt.FeePayer) == 0 {
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
}
feePayer, err := sdk.AccAddressFromBech32(extOpt.FeePayer)
if err != nil {
return errorsmod.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
return sdkerrors.Wrap(err, "failed to parse feePayer from ExtensionOptionsWeb3Tx")
}
feeDelegation := &eip712.FeeDelegationOptions{
@ -250,17 +217,17 @@ func VerifySignature(
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
if err != nil {
return errorsmod.Wrap(err, "failed to create EIP-712 typed data from tx")
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
}
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
sigHash, err := eip712.ComputeTypedDataHash(typedData)
if err != nil {
return err
}
feePayerSig := extOpt.FeePayerSig
if len(feePayerSig) != ethcrypto.SignatureLength {
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
}
// Remove the recovery offset if needed (ie. Metamask eip712 signature)
@ -270,12 +237,12 @@ func VerifySignature(
feePayerPubkey, err := secp256k1.RecoverPubkey(sigHash, feePayerSig)
if err != nil {
return errorsmod.Wrap(err, "failed to recover delegated fee payer from sig")
return sdkerrors.Wrap(err, "failed to recover delegated fee payer from sig")
}
ecPubKey, err := ethcrypto.UnmarshalPubkey(feePayerPubkey)
if err != nil {
return errorsmod.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
return sdkerrors.Wrap(err, "failed to unmarshal recovered fee payer pubkey")
}
pk := &ethsecp256k1.PubKey{
@ -283,23 +250,23 @@ func VerifySignature(
}
if !pubKey.Equals(pk) {
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "feePayer pubkey %s is different from transaction pubkey %s", pubKey, pk)
}
recoveredFeePayerAcc := sdk.AccAddress(pk.Address().Bytes())
if !recoveredFeePayerAcc.Equals(feePayer) {
return errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
return sdkerrors.Wrapf(sdkerrors.ErrorInvalidSigner, "failed to verify delegated fee payer %s signature", recoveredFeePayerAcc)
}
// VerifySignature of ethsecp256k1 accepts 64 byte signature [R||S]
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
if !secp256k1.VerifySignature(pubKey.Bytes(), sigHash, feePayerSig[:len(feePayerSig)-1]) {
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
}
return nil
default:
return errorsmod.Wrapf(errortypes.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
return sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
}
}

View File

@ -1,65 +1,94 @@
// Copyright 2021 Evmos Foundation
// This file is part of Evmos' Ethermint library.
//
// The Ethermint library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Ethermint library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Ethermint library. If not, see https://github.com/evmos/ethermint/blob/main/LICENSE
package ante
import (
"math"
"errors"
"math/big"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/evm/keeper"
"github.com/cerc-io/laconicd/x/evm/statedb"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
ethermint "github.com/tharsis/ethermint/types"
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
// EthAccountVerificationDecorator validates an account balance checks
type EthAccountVerificationDecorator struct {
ak evmtypes.AccountKeeper
// EthSigVerificationDecorator validates an ethereum signatures
type EthSigVerificationDecorator struct {
evmKeeper EVMKeeper
}
// NewEthAccountVerificationDecorator creates a new EthAccountVerificationDecorator
func NewEthAccountVerificationDecorator(ak evmtypes.AccountKeeper, ek EVMKeeper) EthAccountVerificationDecorator {
return EthAccountVerificationDecorator{
ak: ak,
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
return EthSigVerificationDecorator{
evmKeeper: ek,
}
}
// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
// that the signer address matches the one defined on the message.
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
// won't see the error message.
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
chainID := esvd.evmKeeper.ChainID()
params := esvd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(chainID)
blockNum := big.NewInt(ctx.BlockHeight())
signer := ethtypes.MakeSigner(ethCfg, blockNum)
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
sender, err := signer.Sender(msgEthTx.AsTransaction())
if err != nil {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrorInvalidSigner,
"couldn't retrieve sender address ('%s') from the ethereum transaction: %s",
msgEthTx.From,
err.Error(),
)
}
// set up the sender to the transaction field if not already
msgEthTx.From = sender.Hex()
}
return next(ctx, tx, simulate)
}
// EthAccountVerificationDecorator validates an account balance checks
type EthAccountVerificationDecorator struct {
ak evmtypes.AccountKeeper
bankKeeper evmtypes.BankKeeper
evmKeeper EVMKeeper
}
// NewEthAccountVerificationDecorator creates a new EthAccountVerificationDecorator
func NewEthAccountVerificationDecorator(ak evmtypes.AccountKeeper, bankKeeper evmtypes.BankKeeper, ek EVMKeeper) EthAccountVerificationDecorator {
return EthAccountVerificationDecorator{
ak: ak,
bankKeeper: bankKeeper,
evmKeeper: ek,
}
}
// AnteHandle validates checks that the sender balance is greater than the total transaction cost.
// The account will be set to store if it doesn't exis, i.e cannot be found on store.
// This AnteHandler decorator will fail if:
// - 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)
}
@ -67,18 +96,18 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errorsmod.Wrapf(err, "failed to unpack tx data any for tx %d", i)
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
}
// sender address should be in the tx cache from the previous AnteHandle call
from := msgEthTx.GetFrom()
if from.Empty() {
return ctx, errorsmod.Wrap(errortypes.ErrInvalidAddress, "from address cannot be empty")
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty")
}
// check whether the sender address is EOA
@ -90,13 +119,14 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
avd.ak.SetAccount(ctx, acc)
acct = statedb.NewEmptyAccount()
} else if acct.IsContract() {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType,
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
}
if err := keeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
return ctx, errorsmod.Wrap(err, "failed to check sender balance")
if err := evmkeeper.CheckSenderBalance(sdk.NewIntFromBigInt(acct.Balance), txData); err != nil {
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
}
}
return next(ctx, tx, simulate)
}
@ -123,7 +153,7 @@ func NewEthGasConsumeDecorator(
// (during CheckTx only) and that the sender has enough balance to pay for the gas cost.
//
// Intrinsic gas for a transaction is the amount of gas that the transaction uses before the
// transaction is executed. The gas is a constant value plus any cost incurred by additional bytes
// transaction is executed. The gas is a constant value plus any cost inccured by additional bytes
// of data supplied with the transaction.
//
// This AnteHandler decorator will fail if:
@ -133,46 +163,31 @@ 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
// - gas limit is greater than the block gas meter limit
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
gasWanted := uint64(0)
// gas consumption limit already checked during CheckTx so there's no need to
// verify it again during ReCheckTx
if ctx.IsReCheckTx() {
// Use new context with gasWanted = 0
// Otherwise, there's an error on txmempool.postCheck (tendermint)
// that is not bubbled up. Thus, the Tx never runs on DeliverMode
// Error: "gas wanted -1 is negative"
// For more information, see issue #1554
// https://github.com/cerc-io/laconicd/issues/1554
newCtx := ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
return next(newCtx, tx, simulate)
}
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
params := egcd.evmKeeper.GetParams(ctx)
chainCfg := egcd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(egcd.evmKeeper.ChainID())
ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
blockHeight := big.NewInt(ctx.BlockHeight())
homestead := ethCfg.IsHomestead(blockHeight)
istanbul := ethCfg.IsIstanbul(blockHeight)
london := ethCfg.IsLondon(blockHeight)
evmDenom := params.EvmDenom
gasWanted := uint64(0)
var events sdk.Events
// Use the lowest priority of all the messages as the final one.
minPriority := int64(math.MaxInt64)
baseFee := egcd.evmKeeper.GetBaseFee(ctx, ethCfg)
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
}
if ctx.IsCheckTx() && egcd.maxGasWanted != 0 {
if ctx.IsCheckTx() {
// We can't trust the tx gas limit, because we'll refund the unused gas.
if txData.GetGas() > egcd.maxGasWanted {
gasWanted += egcd.maxGasWanted
@ -183,62 +198,43 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
gasWanted += txData.GetGas()
}
evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, homestead, istanbul, ctx.IsCheckTx())
if err != nil {
return ctx, errorsmod.Wrapf(err, "failed to verify the fees")
}
err = egcd.evmKeeper.DeductTxCostsFromUserBalance(ctx, fees, common.HexToAddress(msgEthTx.From))
if err != nil {
return ctx, errorsmod.Wrapf(err, "failed to deduct transaction costs from user balance")
}
events = append(events,
sdk.NewEvent(
sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyFee, fees.String()),
),
fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
ctx,
*msgEthTx,
txData,
evmDenom,
homestead,
istanbul,
london,
)
priority := evmtypes.GetTxPriority(txData, baseFee)
if priority < minPriority {
minPriority = priority
if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance")
}
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
}
// TODO: change to typed events
ctx.EventManager().EmitEvents(events)
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
blockGasLimit := ethermint.BlockGasLimit(ctx)
// return error if the tx gas is greater than the block limit (max gas)
// NOTE: it's important here to use the gas wanted instead of the gas consumed
// from the tx gas pool. The later only has the value so far since the
// EthSetupContextDecorator so it will never exceed the block gas limit.
if gasWanted > blockGasLimit {
return ctx, errorsmod.Wrapf(
errortypes.ErrOutOfGas,
"tx gas (%d) exceeds block gas limit (%d)",
gasWanted,
blockGasLimit,
)
// NOTE: safety check
if blockGasLimit > 0 {
// generate a copy of the gas pool (i.e block gas meter) to see if we've run out of gas for this block
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp
gasPool := sdk.NewGasMeter(blockGasLimit)
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
}
// Set tx GasMeter with a limit of GasWanted (i.e gas limit from the Ethereum tx).
// The gas consumed will be then reset to the gas used by the state transition
// in the EVM.
// FIXME: use a custom gas configuration that doesn't add any additional gas and only
// takes into account the gas consumed at the end of the EVM transaction.
newCtx := ctx.
WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted)).
WithPriority(minPriority)
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
gasConsumed := ctx.GasMeter().GasConsumed()
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
// we know that we have enough gas on the pool to cover the intrinsic gas
return next(newCtx, tx, simulate)
return next(ctx, tx, simulate)
}
// CanTransferDecorator checks if the sender is allowed to transfer funds according to the EVM block
@ -264,35 +260,19 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
baseFee := ctd.evmKeeper.BaseFee(ctx, ethCfg)
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
if err != nil {
return ctx, errorsmod.Wrapf(
return ctx, sdkerrors.Wrapf(
err,
"failed to create an ethereum core.Message from signer %T", signer,
)
}
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
if baseFee == nil {
return ctx, errorsmod.Wrap(
evmtypes.ErrInvalidBaseFee,
"base fee is supported but evm block context value is nil",
)
}
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
return ctx, errorsmod.Wrapf(
errortypes.ErrInsufficientFee,
"max fee per gas less than block base fee (%s < %s)",
coreMsg.GasFeeCap(), baseFee,
)
}
}
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
cfg := &evmtypes.EVMConfig{
ChainConfig: ethCfg,
@ -300,20 +280,35 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
CoinBase: common.Address{},
BaseFee: baseFee,
}
stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB)
// check that caller has enough balance to cover asset transfer for **topmost** call
// NOTE: here the gas consumed is from the context with the infinite gas meter
if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
return ctx, errorsmod.Wrapf(
errortypes.ErrInsufficientFunds,
if coreMsg.Value().Sign() > 0 && !evm.Context.CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"failed to transfer %s from address %s using the EVM block context transfer function",
coreMsg.Value(),
coreMsg.From(),
)
}
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
if baseFee == nil {
return ctx, sdkerrors.Wrap(
evmtypes.ErrInvalidBaseFee,
"base fee is supported but evm block context value is nil",
)
}
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee,
"max fee per gas less than block base fee (%s < %s)",
coreMsg.GasFeeCap(), baseFee,
)
}
}
}
return next(ctx, tx, simulate)
@ -338,19 +333,19 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
}
// increase sequence of sender
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
if acc == nil {
return ctx, errorsmod.Wrapf(
errortypes.ErrUnknownAddress,
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrUnknownAddress,
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
)
}
@ -359,14 +354,14 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
// we merged the nonce verification to nonce increment, so when tx includes multiple messages
// with same sender, they'll be accepted.
if txData.GetNonce() != nonce {
return ctx, errorsmod.Wrapf(
errortypes.ErrInvalidSequence,
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInvalidSequence,
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
)
}
if err := acc.SetSequence(nonce + 1); err != nil {
return ctx, errorsmod.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
return ctx, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
}
issd.ak.SetAccount(ctx, acc)
@ -374,3 +369,166 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
return next(ctx, tx, simulate)
}
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
type EthValidateBasicDecorator struct {
evmKeeper EVMKeeper
}
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
return EthValidateBasicDecorator{
evmKeeper: ek,
}
}
// AnteHandle handles basic validation of tx
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// no need to validate basic on recheck tx, call next antehandler
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
err := tx.ValidateBasic()
// ErrNoSignatures is fine with eth tx
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
return ctx, sdkerrors.Wrap(err, "tx basic validation failed")
}
// For eth type cosmos tx, some fields should be veified as zero values,
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
if wrapperTx, ok := tx.(protoTxProvider); ok {
protoTx := wrapperTx.GetProtoTx()
body := protoTx.Body
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
}
if len(body.ExtensionOptions) != 1 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
}
txFee := sdk.Coins{}
txGasLimit := uint64(0)
for _, msg := range protoTx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
txGasLimit += msgEthTx.GetGas()
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
}
params := vbd.evmKeeper.GetParams(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.BaseFee(ctx, ethCfg)
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}
txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee())))
}
authInfo := protoTx.AuthInfo
if len(authInfo.SignerInfos) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
}
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
}
if !authInfo.Fee.Amount.IsEqual(txFee) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
}
if authInfo.Fee.GasLimit != txGasLimit {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
}
sigs := protoTx.Signatures
if len(sigs) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty")
}
}
return next(ctx, tx, simulate)
}
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
// by setting the gas meter to infinite
type EthSetupContextDecorator struct {
evmKeeper EVMKeeper
}
func NewEthSetUpContextDecorator(evmKeeper EVMKeeper) EthSetupContextDecorator {
return EthSetupContextDecorator{
evmKeeper: evmKeeper,
}
}
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// all transactions must implement GasTx
_, ok := tx.(authante.GasTx)
if !ok {
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
}
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
// Reset transient gas used to prepare the execution of current cosmos tx.
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
esc.evmKeeper.ResetTransientGasUsed(ctx)
return next(newCtx, tx, simulate)
}
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
// as the local validator's minimum gasFee (defined in validator config).
// If fee is too low, decorator returns error and tx is rejected from mempool.
// Note this only applies when ctx.CheckTx = true
// If fee is high enough or not CheckTx, then call next AnteHandler
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
type EthMempoolFeeDecorator struct {
evmKeeper EVMKeeper
}
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
return EthMempoolFeeDecorator{
evmKeeper: ek,
}
}
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator,
// if this is a CheckTx. This is only for local mempool purposes, and thus
// is only ran on check tx.
// It only do the check if london hardfork not enabled or feemarket not enabled, because in that case feemarket will take over the task.
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if ctx.IsCheckTx() && !simulate {
params := mfd.evmKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(mfd.evmKeeper.ChainID())
baseFee := mfd.evmKeeper.BaseFee(ctx, ethCfg)
if baseFee == nil {
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
evmDenom := params.EvmDenom
feeAmt := ethMsg.GetFee()
glDec := sdk.NewDec(int64(ethMsg.GetGas()))
requiredFee := ctx.MinGasPrices().AmountOf(evmDenom).Mul(glDec)
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeAmt, requiredFee)
}
}
}
}
return next(ctx, tx, simulate)
}

View File

@ -1,24 +1,65 @@
package ante_test
import (
"math"
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cerc-io/laconicd/app/ante"
"github.com/cerc-io/laconicd/server/config"
"github.com/cerc-io/laconicd/tests"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/evm/statedb"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/tharsis/ethermint/app/ante"
"github.com/tharsis/ethermint/server/config"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
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)
signedTx.From = addr.Hex()
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
testCases := []struct {
name string
tx sdk.Tx
reCheckTx bool
expPass bool
}{
{"ReCheckTx", &invalidTx{}, true, false},
{"invalid transaction type", &invalidTx{}, false, false},
{
"invalid sender",
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
false,
false,
},
{"successful signature verification", signedTx, false, true},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
dec := ante.NewEthAccountVerificationDecorator(
suite.app.AccountKeeper, suite.app.EvmKeeper,
suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper,
)
addr := tests.GenerateAddress()
@ -93,7 +134,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)
@ -149,7 +190,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)
@ -169,72 +210,41 @@ 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, gasPrice, nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, big.NewInt(1), nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2.From = addr.Hex()
tx2Priority := int64(1)
tx3GasLimit := ethermint.BlockGasLimit(suite.ctx) + uint64(1)
tx3 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx3GasLimit, gasPrice, nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
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, &ethtypes.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
expPriority int64
name string
tx sdk.Tx
gasLimit uint64
malleate func()
expPass bool
expPanic bool
}{
{"invalid transaction type", &invalidTx{}, math.MaxUint64, func() {}, false, false, 0},
{"invalid transaction type", &invalidTx{}, 0, func() {}, false, false},
{
"sender not found",
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
math.MaxUint64,
0,
func() {},
false, false,
0,
},
{
"gas limit too low",
tx,
math.MaxUint64,
0,
func() {},
false, false,
0,
},
{
"gas limit above block gas limit",
tx3,
math.MaxUint64,
func() {},
false, false,
0,
},
{
"not enough balance for fees",
tx2,
math.MaxUint64,
0,
func() {},
false, false,
0,
},
{
"not enough tx gas",
@ -244,7 +254,6 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
vmdb.AddBalance(addr, big.NewInt(1000000))
},
false, true,
0,
},
{
"not enough block gas",
@ -252,43 +261,21 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
0,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1))
},
false, true,
0,
},
{
"success - legacy tx",
"success",
tx2,
tx2GasLimit, // it's capped
config.DefaultMaxTxGasWanted, // it's capped
func() {
vmdb.AddBalance(addr, big.NewInt(1001000000000000))
vmdb.AddBalance(addr, big.NewInt(1000000))
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,
},
{
"success - gas limit on gasMeter is set on ReCheckTx mode",
dynamicFeeTx,
0, // for reCheckTX mode, gas limit should be set to 0
func() {
vmdb.AddBalance(addr, big.NewInt(1001000000000000))
suite.ctx = suite.ctx.WithIsReCheckTx(true)
},
true, false,
0,
},
}
@ -300,19 +287,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
}
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, NextFn)
_, 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)
}
suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
// TODO: needs to check the gasmeter limit issue
// suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
})
}
}
@ -390,7 +377,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)
@ -469,12 +456,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)
@ -491,3 +478,33 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
})
}
}
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
dec := ante.NewEthSetUpContextDecorator(suite.app.EvmKeeper)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
testCases := []struct {
name string
tx sdk.Tx
expPass bool
}{
{"invalid transaction type - does not implement GasTx", &invalidTx{}, false},
{
"success - transaction implement GasTx",
tx,
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -1,144 +0,0 @@
package ante
import (
"fmt"
"math"
errorsmod "cosmossdk.io/errors"
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"
errortypes "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, errorsmod.Wrapf(errortypes.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, errorsmod.Wrapf(errortypes.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
}

View File

@ -1,219 +0,0 @@
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(&ethermint.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(&ethermint.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)
}
})
}
}

View File

@ -1,52 +0,0 @@
package ante
import (
"math/big"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// 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) {
chainCfg := gwd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.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()
isBaseFeeEnabled := gwd.feeMarketKeeper.GetBaseFeeEnabled(ctx)
// Add total gasWanted to cumulative in block transientStore in FeeMarket module
if isBaseFeeEnabled {
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
return ctx, errorsmod.Wrapf(err, "failed to add gas wanted to transient store")
}
}
return next(ctx, tx, simulate)
}

View File

@ -1,95 +0,0 @@
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)
})
}
}

View File

@ -1,211 +0,0 @@
package ante
import (
"math/big"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "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
}
// 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
}
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
// as the local validator's minimum gasFee (defined in validator config).
// If fee is too low, decorator returns error and tx is rejected from mempool.
// Note this only applies when ctx.CheckTx = true
// If fee is high enough or not CheckTx, then call next AnteHandler
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
type EthMempoolFeeDecorator struct {
evmKeeper EVMKeeper
}
// NewMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
// Cosmos transactions.
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
}
// NewEthMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
// Ethereum transactions.
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
}
// NewEthMempoolFeeDecorator creates a new NewEthMempoolFeeDecorator instance used only for
// Ethereum transactions.
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
return EthMempoolFeeDecorator{
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, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected sdk.FeeTx", tx)
}
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)
}
evmDenom := mpd.evmKeeper.GetEVMDenom(ctx)
minGasPrices := sdk.DecCoins{
{
Denom: 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, errorsmod.Wrapf(errortypes.ErrInsufficientFee,
"provided fee < minimum global fee (%s < %s). Please increase the gas price.",
feeCoins,
requiredFees)
}
return next(ctx, tx, simulate)
}
// AnteHandle ensures that the that the effective fee from the transaction is greater than the
// minimum global fee, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument).
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)
}
chainCfg := empd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(empd.evmKeeper.ChainID())
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(
errortypes.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, errorsmod.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, errorsmod.Wrapf(
errortypes.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)
}
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator.
// This check only for local mempool purposes, and thus it is only run on (Re)CheckTx.
// The logic is also skipped if the London hard fork and EIP-1559 are enabled.
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if !ctx.IsCheckTx() || simulate {
return next(ctx, tx, simulate)
}
chainCfg := mfd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(mfd.evmKeeper.ChainID())
baseFee := mfd.evmKeeper.GetBaseFee(ctx, ethCfg)
// skip check as the London hard fork and EIP-1559 are enabled
if baseFee != nil {
return next(ctx, tx, simulate)
}
evmDenom := mfd.evmKeeper.GetEVMDenom(ctx)
minGasPrice := ctx.MinGasPrices().AmountOf(evmDenom)
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
fee := sdk.NewDecFromBigInt(ethMsg.GetFee())
gasLimit := sdk.NewDecFromBigInt(new(big.Int).SetUint64(ethMsg.GetGas()))
requiredFee := minGasPrice.Mul(gasLimit)
if fee.LT(requiredFee) {
return ctx, errorsmod.Wrapf(
errortypes.ErrInsufficientFee,
"insufficient fee; got: %s required: %s",
fee, requiredFee,
)
}
}
return next(ctx, tx, simulate)
}

View File

@ -1,351 +0,0 @@
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,
"invalid transaction type",
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)
}
})
}
}
}
func (suite AnteTestSuite) TestEthMempoolFeeDecorator() {
// TODO: add test
}

View File

@ -1,68 +1,63 @@
package ante
import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
ibcante "github.com/cosmos/ibc-go/v5/modules/core/ante"
ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper"
ibcante "github.com/cosmos/ibc-go/v3/modules/core/ante"
ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
// channel keeper, EVM Keeper and Fee Market Keeper.
type HandlerOptions struct {
AccountKeeper evmtypes.AccountKeeper
BankKeeper evmtypes.BankKeeper
IBCKeeper *ibckeeper.Keeper
FeeMarketKeeper 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
AccountKeeper evmtypes.AccountKeeper
BankKeeper evmtypes.BankKeeper
IBCKeeper *ibckeeper.Keeper
FeeMarketKeeper evmtypes.FeeMarketKeeper
EvmKeeper EVMKeeper
FeegrantKeeper ante.FeegrantKeeper
SignModeHandler authsigning.SignModeHandler
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
MaxTxGasWanted uint64
TxFeeChecker ante.TxFeeChecker
}
func (options HandlerOptions) validate() error {
func (options HandlerOptions) Validate() error {
if options.AccountKeeper == nil {
return errorsmod.Wrap(errortypes.ErrLogic, "account keeper is required for AnteHandler")
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
}
if options.BankKeeper == nil {
return errorsmod.Wrap(errortypes.ErrLogic, "bank keeper is required for AnteHandler")
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
}
if options.SignModeHandler == nil {
return errorsmod.Wrap(errortypes.ErrLogic, "sign mode handler is required for ante builder")
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}
if options.FeeMarketKeeper == nil {
return errorsmod.Wrap(errortypes.ErrLogic, "fee market keeper is required for AnteHandler")
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
}
if options.EvmKeeper == nil {
return errorsmod.Wrap(errortypes.ErrLogic, "evm keeper is required for AnteHandler")
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
}
return nil
}
func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
NewEthMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper), // Check eth effective gas price against the global MinGasPrice
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
NewEthValidateBasicDecorator(options.EvmKeeper),
NewEthSigVerificationDecorator(options.EvmKeeper),
NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper),
NewCanTransferDecorator(options.EvmKeeper),
NewEthAccountVerificationDecorator(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted),
NewCanTransferDecorator(options.EvmKeeper),
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.
)
}
@ -70,10 +65,8 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(),
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
@ -83,7 +76,28 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
ibcante.NewAnteDecorator(options.IBCKeeper),
)
}
func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(),
// NOTE: extensions option decorator removed
// ante.NewRejectExtensionOptionsDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
// SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
// Note: signature verification uses EIP instead of the cosmos signature validator
NewEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewAnteDecorator(options.IBCKeeper),
)
}

View File

@ -3,49 +3,31 @@ package ante
import (
"math/big"
"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"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
// 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
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM
DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
ChainID() *big.Int
GetParams(ctx sdk.Context) evmtypes.Params
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) *vm.EVM
DeductTxCostsFromUserBalance(
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
) (sdk.Coins, error)
BaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
ResetTransientGasUsed(ctx sdk.Context)
GetTxIndexTransient(ctx sdk.Context) uint64
GetChainConfig(ctx sdk.Context) evmtypes.ChainConfig
GetEVMDenom(ctx sdk.Context) string
GetEnableCreate(ctx sdk.Context) bool
GetEnableCall(ctx sdk.Context) bool
GetAllowUnprotectedTxs(ctx sdk.Context) bool
}
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)
GetBaseFeeEnabled(ctx sdk.Context) bool
}

View File

@ -1,10 +1,9 @@
package ante
import (
errorsmod "cosmossdk.io/errors"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
// RejectMessagesDecorator prevents invalid msg types from being executed
@ -16,8 +15,8 @@ type RejectMessagesDecorator struct{}
func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
for _, msg := range tx.GetMsgs() {
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
return ctx, errorsmod.Wrapf(
errortypes.ErrInvalidType,
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInvalidType,
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
)
}

View File

@ -1,189 +0,0 @@
package ante
import (
"errors"
"strconv"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
// by setting the gas meter to infinite
type EthSetupContextDecorator struct {
evmKeeper EVMKeeper
}
func NewEthSetUpContextDecorator(evmKeeper EVMKeeper) EthSetupContextDecorator {
return EthSetupContextDecorator{
evmKeeper: evmKeeper,
}
}
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// all transactions must implement GasTx
_, ok := tx.(authante.GasTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected GasTx", tx)
}
// We need to setup an empty gas config so that the gas is consistent with Ethereum.
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()).
WithKVGasConfig(storetypes.GasConfig{}).
WithTransientKVGasConfig(storetypes.GasConfig{})
// Reset transient gas used to prepare the execution of current cosmos tx.
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
esc.evmKeeper.ResetTransientGasUsed(ctx)
return next(newCtx, tx, simulate)
}
// 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, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
// emit ethereum tx hash as an event so that it can be indexed by Tendermint for query purposes
// 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)
}
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
type EthValidateBasicDecorator struct {
evmKeeper EVMKeeper
}
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
return EthValidateBasicDecorator{
evmKeeper: ek,
}
}
// AnteHandle handles basic validation of tx
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// no need to validate basic on recheck tx, call next antehandler
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
err := tx.ValidateBasic()
// ErrNoSignatures is fine with eth tx
if err != nil && !errors.Is(err, errortypes.ErrNoSignatures) {
return ctx, errorsmod.Wrap(err, "tx basic validation failed")
}
// For eth type cosmos tx, some fields should be verified as zero values,
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
wrapperTx, ok := tx.(protoTxProvider)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.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, errorsmod.Wrap(errortypes.ErrInvalidRequest,
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
}
if len(body.ExtensionOptions) != 1 {
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
}
authInfo := protoTx.AuthInfo
if len(authInfo.SignerInfos) > 0 {
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
}
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
}
sigs := protoTx.Signatures
if len(sigs) > 0 {
return ctx, errorsmod.Wrap(errortypes.ErrInvalidRequest, "for eth tx Signatures should be empty")
}
txFee := sdk.Coins{}
txGasLimit := uint64(0)
chainCfg := vbd.evmKeeper.GetChainConfig(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := chainCfg.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)
enableCreate := vbd.evmKeeper.GetEnableCreate(ctx)
enableCall := vbd.evmKeeper.GetEnableCall(ctx)
evmDenom := vbd.evmKeeper.GetEVMDenom(ctx)
for _, msg := range protoTx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
// Validate `From` field
if msgEthTx.From != "" {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid From %s, expect empty string", msgEthTx.From)
}
txGasLimit += msgEthTx.GetGas()
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errorsmod.Wrap(err, "failed to unpack MsgEthereumTx Data")
}
// return error if contract creation or call are disabled through governance
if !enableCreate && txData.GetTo() == nil {
return ctx, errorsmod.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
} else if !enableCall && txData.GetTo() != nil {
return ctx, errorsmod.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
}
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, errorsmod.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}
txFee = txFee.Add(sdk.Coin{Denom: evmDenom, Amount: sdkmath.NewIntFromBigInt(txData.Fee())})
}
if !authInfo.Fee.Amount.IsEqual(txFee) {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
}
if authInfo.Fee.GasLimit != txGasLimit {
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
}
return next(ctx, tx, simulate)
}

View File

@ -1,42 +0,0 @@
package ante_test
import (
"math/big"
"github.com/cerc-io/laconicd/app/ante"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
dec := ante.NewEthSetUpContextDecorator(suite.app.EvmKeeper)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
testCases := []struct {
name string
tx sdk.Tx
expPass bool
}{
{"invalid transaction type - does not implement GasTx", &invalidTx{}, false},
{
"success - transaction implement GasTx",
tx,
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
ctx, err := dec.AnteHandle(suite.ctx, tc.tx, false, NextFn)
if tc.expPass {
suite.Require().NoError(err)
suite.Equal(storetypes.GasConfig{}, ctx.KVGasConfig())
suite.Equal(storetypes.GasConfig{}, ctx.TransientKVGasConfig())
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -1,64 +0,0 @@
package ante_test
import (
"math/big"
"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"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
addr, privKey := tests.NewAddrKey()
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
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
allowUnprotectedTxs bool
reCheckTx bool
expPass bool
}{
{"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, 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() {
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)
} else {
suite.Require().Error(err)
}
})
}
suite.evmParamsOption = nil
}

View File

@ -3,9 +3,9 @@ package ante_test
import (
"math/big"
"github.com/cerc-io/laconicd/tests"
"github.com/cerc-io/laconicd/x/evm/statedb"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
func (suite AnteTestSuite) TestSignatures() {

View File

@ -1,65 +0,0 @@
package ante
import (
"math/big"
errorsmod "cosmossdk.io/errors"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
// EthSigVerificationDecorator validates an ethereum signatures
type EthSigVerificationDecorator struct {
evmKeeper EVMKeeper
}
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
return EthSigVerificationDecorator{
evmKeeper: ek,
}
}
// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
// that the signer address matches the one defined on the message.
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
// won't see the error message.
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
chainID := esvd.evmKeeper.ChainID()
chainCfg := esvd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(chainID)
blockNum := big.NewInt(ctx.BlockHeight())
signer := ethtypes.MakeSigner(ethCfg, blockNum)
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
allowUnprotectedTxs := esvd.evmKeeper.GetAllowUnprotectedTxs(ctx)
ethTx := msgEthTx.AsTransaction()
if !allowUnprotectedTxs && !ethTx.Protected() {
return ctx, errorsmod.Wrapf(
errortypes.ErrNotSupported,
"rejected unprotected Ethereum transaction. Please EIP155 sign your transaction to protect it against replay-attacks")
}
sender, err := signer.Sender(ethTx)
if err != nil {
return ctx, errorsmod.Wrapf(
errortypes.ErrorInvalidSigner,
"couldn't retrieve sender address from the ethereum transaction: %s",
err.Error(),
)
}
// set up the sender to the transaction field if not already
msgEthTx.From = sender.Hex()
}
return next(ctx, tx, simulate)
}

View File

@ -1,59 +1,42 @@
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"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/tharsis/ethermint/ethereum/eip712"
"github.com/tharsis/ethermint/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"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"
sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authz "github.com/cosmos/cosmos-sdk/x/authz"
"github.com/cerc-io/laconicd/app"
ante "github.com/cerc-io/laconicd/app/ante"
"github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/tests"
"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"
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"github.com/tharsis/ethermint/app"
ante "github.com/tharsis/ethermint/app/ante"
"github.com/tharsis/ethermint/encoding"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
@ -68,11 +51,8 @@ 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())))
}
@ -80,7 +60,7 @@ func (suite *AnteTestSuite) StateDB() *statedb.StateDB {
func (suite *AnteTestSuite) SetupTest() {
checkTx := false
suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
suite.app = app.Setup(suite.T(), checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
if suite.enableFeemarket {
// setup feemarketGenesis params
feemarketGenesis := feemarkettypes.DefaultGenesisState()
@ -91,21 +71,14 @@ 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 {
maxInt := sdkmath.NewInt(math.MaxInt64)
evmGenesis := evmtypes.DefaultGenesisState()
maxInt := sdk.NewInt(math.MaxInt64)
evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
evmGenesis.Params.ChainConfig.ShanghaiBlock = &maxInt
evmGenesis.Params.ChainConfig.CancunBlock = &maxInt
evmGenesis.Params.ChainConfig.MergeForkBlock = &maxInt
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
}
if suite.evmParamsOption != nil {
suite.evmParamsOption(&evmGenesis.Params)
}
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
return genesis
})
@ -120,11 +93,10 @@ func (suite *AnteTestSuite) SetupTest() {
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
// We're using TestMsg amino encoding in some tests, so register it here.
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
eip712.SetEncodingConfig(encodingConfig)
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
options := ante.HandlerOptions{
AccountKeeper: suite.app.AccountKeeper,
BankKeeper: suite.app.BankKeeper,
EvmKeeper: suite.app.EvmKeeper,
@ -133,10 +105,11 @@ func (suite *AnteTestSuite) SetupTest() {
FeeMarketKeeper: suite.app.FeeMarketKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
})
suite.Require().NoError(err)
}
suite.anteHandler = anteHandler
suite.Require().NoError(options.Validate())
suite.anteHandler = ante.NewAnteHandler(options)
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
}
@ -146,38 +119,6 @@ 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,
@ -209,14 +150,13 @@ 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, sdkmath.NewIntFromBigInt(txData.Fee())))
fees := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(txData.Fee())))
builder.SetFeeAmount(fees)
builder.SetGasLimit(msg.GetGas())
@ -259,222 +199,23 @@ 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 := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(1))))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
}
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build MsgSend
valEthAddr := tests.GenerateAddress()
valAddr := sdk.ValAddress(valEthAddr.Bytes())
msgSend := stakingtypes.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
return suite.CreateTestEIP712SingleMessageTxBuilder(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 := stakingtypes.NewMsgCreateValidator(
valAddr,
privEd.PubKey(),
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
stakingtypes.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
)
suite.Require().NoError(err)
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate)
}
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator2(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 := stakingtypes.NewMsgCreateValidator(
valAddr,
privEd.PubKey(),
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
// Ensure optional fields can be left blank
stakingtypes.NewDescription("moniker", "indentity", "", "", ""),
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
)
suite.Require().NoError(err)
return suite.CreateTestEIP712SingleMessageTxBuilder(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 := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText)
suite.Require().True(ok)
msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from)
suite.Require().NoError(err)
return suite.CreateTestEIP712SingleMessageTxBuilder(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.CreateTestEIP712SingleMessageTxBuilder(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 := stakingtypes.NewMsgEditValidator(
valAddr,
stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"),
nil,
nil,
)
return suite.CreateTestEIP712SingleMessageTxBuilder(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.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
}
func (suite *AnteTestSuite) CreateTestEIP712MsgVoteV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
msgVote := govtypesv1.NewMsgVote(from, 1, govtypesv1.VoteOption_VOTE_OPTION_YES, "")
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgVote)
}
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposalV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build V1 proposal messages. Must all be same-type, since EIP-712
// does not support arrays of variable type.
authAcc := suite.app.GovKeeper.GetGovernanceAccount(suite.ctx)
proposal1, ok := govtypes.ContentFromProposalType("My proposal 1", "My description 1", govtypes.ProposalTypeText)
suite.Require().True(ok)
content1, err := govtypesv1.NewLegacyContent(
proposal1,
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
)
suite.Require().NoError(err)
proposal2, ok := govtypes.ContentFromProposalType("My proposal 2", "My description 2", govtypes.ProposalTypeText)
suite.Require().True(ok)
content2, err := govtypesv1.NewLegacyContent(
proposal2,
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
)
suite.Require().NoError(err)
proposalMsgs := []sdk.Msg{
content1,
content2,
}
// Build V1 proposal
msgProposal, err := govtypesv1.NewMsgSubmitProposal(
proposalMsgs,
sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100))),
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), from.Bytes()),
"Metadata",
)
suite.Require().NoError(err)
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgProposal)
}
func (suite *AnteTestSuite) CreateTestEIP712MsgExec(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
recipient := sdk.AccAddress(common.Address{}.Bytes())
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
msgExec := authz.NewMsgExec(from, []sdk.Msg{msgSend})
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, &msgExec)
}
func (suite *AnteTestSuite) CreateTestEIP712MultipleMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
recipient := sdk.AccAddress(common.Address{}.Bytes())
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msgSend, msgSend, msgSend})
}
// Fails
func (suite *AnteTestSuite) CreateTestEIP712MultipleSignerMsgs(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
recipient := sdk.AccAddress(common.Address{}.Bytes())
msgSend1 := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
msgSend2 := banktypes.NewMsgSend(recipient, from, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msgSend1, msgSend2})
}
// 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) CreateTestEIP712SingleMessageTxBuilder(
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
) client.TxBuilder {
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, []sdk.Msg{msg})
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
}
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg,
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
) client.TxBuilder {
var err error
@ -487,21 +228,16 @@ 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()
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, msgs, "", nil)
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msgs[0], data, &eip712.FeeDelegationOptions{
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil)
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
FeePayer: from,
})
suite.Require().NoError(err)
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
sigHash, err := eip712.ComputeTypedDataHash(typedData)
suite.Require().NoError(err)
// Sign typedData
@ -539,193 +275,12 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
err = builder.SetSignatures(sigsV2)
suite.Require().NoError(err)
err = builder.SetMsgs(msgs...)
err = builder.SetMsgs(msg)
suite.Require().NoError(err)
return builder
}
// Generate a set of pub/priv keys to be used in creating multi-keys
func (suite *AnteTestSuite) GenerateMultipleKeys(n int) ([]cryptotypes.PrivKey, []cryptotypes.PubKey) {
privKeys := make([]cryptotypes.PrivKey, n)
pubKeys := make([]cryptotypes.PubKey, n)
for i := 0; i < n; i++ {
privKey, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
privKeys[i] = privKey
pubKeys[i] = privKey.PubKey()
}
return privKeys, pubKeys
}
// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard)
func (suite *AnteTestSuite) generateSingleSignature(signMode signing.SignMode, privKey cryptotypes.PrivKey, signDocBytes []byte, signType string) (signature signing.SignatureV2) {
var (
msg []byte
err error
)
msg = signDocBytes
if signType == "EIP-712" {
msg, err = eip712.GetEIP712BytesForMsg(signDocBytes)
suite.Require().NoError(err)
}
sigBytes, _ := privKey.Sign(msg)
sigData := &signing.SingleSignatureData{
SignMode: signMode,
Signature: sigBytes,
}
return signing.SignatureV2{
PubKey: privKey.PubKey(),
Data: sigData,
}
}
// generateMultikeySignatures signs a set of messages using each private key within a given multi-key
func (suite *AnteTestSuite) generateMultikeySignatures(signMode signing.SignMode, privKeys []cryptotypes.PrivKey, signDocBytes []byte, signType string) (signatures []signing.SignatureV2) {
n := len(privKeys)
signatures = make([]signing.SignatureV2, n)
for i := 0; i < n; i++ {
privKey := privKeys[i]
currentType := signType
// If mixed type, alternate signing type on each iteration
if signType == "mixed" {
if i%2 == 0 {
currentType = "EIP-712"
} else {
currentType = "Standard"
}
}
signatures[i] = suite.generateSingleSignature(
signMode,
privKey,
signDocBytes,
currentType,
)
}
return signatures
}
// RegisterAccount creates an account with the keeper and populates the initial balance
func (suite *AnteTestSuite) RegisterAccount(pubKey cryptotypes.PubKey, balance *big.Int) {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, sdk.AccAddress(pubKey.Address()))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.app.EvmKeeper.SetBalance(suite.ctx, common.BytesToAddress(pubKey.Address()), balance)
}
// createSignerBytes generates sign doc bytes using the given parameters
func (suite *AnteTestSuite) createSignerBytes(chainId string, signMode signing.SignMode, pubKey cryptotypes.PubKey, txBuilder client.TxBuilder) []byte {
acc, err := sdkante.GetSignerAcc(suite.ctx, suite.app.AccountKeeper, sdk.AccAddress(pubKey.Address()))
suite.Require().NoError(err)
signerInfo := authsigning.SignerData{
Address: sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), acc.GetAddress().Bytes()),
ChainID: chainId,
AccountNumber: acc.GetAccountNumber(),
Sequence: acc.GetSequence(),
PubKey: pubKey,
}
signerBytes, err := suite.clientCtx.TxConfig.SignModeHandler().GetSignBytes(
signMode,
signerInfo,
txBuilder.GetTx(),
)
suite.Require().NoError(err)
return signerBytes
}
// createBaseTxBuilder creates a TxBuilder to be used for Single- or Multi-signing
func (suite *AnteTestSuite) createBaseTxBuilder(msg sdk.Msg, gas uint64) client.TxBuilder {
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
txBuilder.SetGasLimit(gas)
txBuilder.SetFeeAmount(sdk.NewCoins(
sdk.NewCoin("aphoton", sdk.NewInt(10000)),
))
err := txBuilder.SetMsgs(msg)
suite.Require().NoError(err)
txBuilder.SetMemo("")
return txBuilder
}
// CreateTestSignedMultisigTx creates and sign a multi-signed tx for the given message. `signType` indicates whether to use standard signing ("Standard"),
// EIP-712 signing ("EIP-712"), or a mix of the two ("mixed").
func (suite *AnteTestSuite) CreateTestSignedMultisigTx(privKeys []cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainId string, gas uint64, signType string) client.TxBuilder {
pubKeys := make([]cryptotypes.PubKey, len(privKeys))
for i, privKey := range privKeys {
pubKeys[i] = privKey.PubKey()
}
// Re-derive multikey
numKeys := len(privKeys)
multiKey := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
suite.RegisterAccount(multiKey, big.NewInt(10000000000))
txBuilder := suite.createBaseTxBuilder(msg, gas)
// Prepare signature field
sig := multisig.NewMultisig(len(pubKeys))
txBuilder.SetSignatures(signing.SignatureV2{
PubKey: multiKey,
Data: sig,
})
signerBytes := suite.createSignerBytes(chainId, signMode, multiKey, txBuilder)
// Sign for each key and update signature field
sigs := suite.generateMultikeySignatures(signMode, privKeys, signerBytes, signType)
for _, pkSig := range sigs {
err := multisig.AddSignatureV2(sig, pkSig, pubKeys)
suite.Require().NoError(err)
}
txBuilder.SetSignatures(signing.SignatureV2{
PubKey: multiKey,
Data: sig,
})
return txBuilder
}
func (suite *AnteTestSuite) CreateTestSingleSignedTx(privKey cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainId string, gas uint64, signType string) client.TxBuilder {
pubKey := privKey.PubKey()
suite.RegisterAccount(pubKey, big.NewInt(10000000000))
txBuilder := suite.createBaseTxBuilder(msg, gas)
// Prepare signature field
sig := signing.SingleSignatureData{}
txBuilder.SetSignatures(signing.SignatureV2{
PubKey: pubKey,
Data: &sig,
})
signerBytes := suite.createSignerBytes(chainId, signMode, pubKey, txBuilder)
sigData := suite.generateSingleSignature(signMode, privKey, signerBytes, signType)
txBuilder.SetSignatures(sigData)
return txBuilder
}
func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
return ctx, nil
}
var _ sdk.Tx = &invalidTx{}
type invalidTx struct{}

View File

@ -2,7 +2,6 @@ package app
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
@ -12,30 +11,29 @@ import (
"github.com/rakyll/statik/fs"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/node"
"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"
"github.com/tharsis/ethermint/app/ante"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
storetypes "github.com/cosmos/cosmos-sdk/store/v2alpha1"
"github.com/cosmos/cosmos-sdk/store/v2alpha1/multi"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
"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"
@ -69,7 +67,6 @@ 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"
@ -90,44 +87,46 @@ import (
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"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"
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"
// unnamed import of statik for swagger UI support
_ "github.com/cerc-io/laconicd/client/docs/statik"
_ "github.com/tharsis/ethermint/client/docs/statik"
"github.com/cerc-io/laconicd/app/ante"
"github.com/cerc-io/laconicd/ethereum/eip712"
srvflags "github.com/cerc-io/laconicd/server/flags"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/evm"
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"
srvflags "github.com/tharsis/ethermint/server/flags"
ethermint "github.com/tharsis/ethermint/types"
"github.com/tharsis/ethermint/x/evm"
// evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
"github.com/tharsis/ethermint/x/feemarket"
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
// Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
"github.com/cerc-io/laconicd/x/auction"
auctionkeeper "github.com/cerc-io/laconicd/x/auction/keeper"
auctiontypes "github.com/cerc-io/laconicd/x/auction/types"
"github.com/cerc-io/laconicd/x/bond"
bondkeeper "github.com/cerc-io/laconicd/x/bond/keeper"
bondtypes "github.com/cerc-io/laconicd/x/bond/types"
registry "github.com/cerc-io/laconicd/x/registry"
registrykeeper "github.com/cerc-io/laconicd/x/registry/keeper"
registrytypes "github.com/cerc-io/laconicd/x/registry/types"
"github.com/tharsis/ethermint/x/auction"
auctionkeeper "github.com/tharsis/ethermint/x/auction/keeper"
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
"github.com/tharsis/ethermint/x/bond"
bondkeeper "github.com/tharsis/ethermint/x/bond/keeper"
bondtypes "github.com/tharsis/ethermint/x/bond/types"
"github.com/tharsis/ethermint/x/nameservice"
nameservicekeeper "github.com/tharsis/ethermint/x/nameservice/keeper"
nameservicetypes "github.com/tharsis/ethermint/x/nameservice/types"
)
func init() {
@ -136,10 +135,10 @@ func init() {
panic(err)
}
DefaultNodeHome = filepath.Join(userHomeDir, ".laconicd")
DefaultNodeHome = filepath.Join(userHomeDir, ".chibaclonkd")
}
const appName = "laconicd"
const appName = "chibaclonkd"
var (
// DefaultNodeHome default home directories for the application daemon
@ -156,10 +155,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{},
@ -173,28 +172,28 @@ var (
// Ethermint modules
evm.AppModuleBasic{},
feemarket.AppModuleBasic{},
// Laconic modules
// Vulcanize chiba-clonk modules
auction.AppModuleBasic{},
bond.AppModuleBasic{},
registry.AppModuleBasic{},
nameservice.AppModuleBasic{},
)
// module account permissions
maccPerms = map[string][]string{
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, //nolint:lll // used for secure addition and subtraction of balance using module account
auctiontypes.ModuleName: nil,
auctiontypes.AuctionBurnModuleAccountName: nil,
registrytypes.ModuleName: nil,
registrytypes.RecordRentModuleAccountName: nil,
registrytypes.AuthorityRentModuleAccountName: nil,
bondtypes.ModuleName: nil,
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
auctiontypes.ModuleName: nil,
auctiontypes.AuctionBurnModuleAccountName: nil,
nameservicetypes.ModuleName: nil,
nameservicetypes.RecordRentModuleAccountName: nil,
nameservicetypes.AuthorityRentModuleAccountName: nil,
bondtypes.ModuleName: nil,
}
// module accounts that are allowed to receive tokens
@ -203,6 +202,8 @@ var (
}
)
var _ simapp.App = (*EthermintApp)(nil)
// var _ server.Application (*EthermintApp)(nil)
// EthermintApp implements an extended ABCI application. It is an application
@ -215,8 +216,7 @@ 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
@ -249,15 +249,18 @@ type EthermintApp struct {
EvmKeeper *evmkeeper.Keeper
FeeMarketKeeper feemarketkeeper.Keeper
// laconic keepers
AuctionKeeper auctionkeeper.Keeper
BondKeeper bondkeeper.Keeper
RegistryKeeper registrykeeper.Keeper
RegistryRecordKeeper registrykeeper.RecordKeeper
// chiba-clonk keepers
AuctionKeeper auctionkeeper.Keeper
BondKeeper bondkeeper.Keeper
NameServiceKeeper nameservicekeeper.Keeper
NameServiceRecordKeeper nameservicekeeper.RecordKeeper
// the module manager
mm *module.Manager
// simulation manager
sm *module.SimulationManager
// the configurator
configurator module.Configurator
}
@ -265,7 +268,7 @@ type EthermintApp struct {
// NewEthermintApp returns a reference to a new initialized Ethermint application.
func NewEthermintApp(
logger log.Logger,
db dbm.DB,
db db.DBConnection,
traceStore io.Writer,
loadLatest bool,
skipUpgradeHeights map[int64]bool,
@ -273,13 +276,66 @@ func NewEthermintApp(
invCheckPeriod uint,
encodingConfig simappparams.EncodingConfig,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
baseAppOptions ...baseapp.AppOption,
) *EthermintApp {
appCodec := encodingConfig.Codec
cdc := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
eip712.SetEncodingConfig(encodingConfig)
keys := sdk.NewKVStoreKeys(
// SDK keys
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey,
evidencetypes.StoreKey, capabilitytypes.StoreKey,
authzkeeper.StoreKey,
// ibc keys
ibchost.StoreKey, ibctransfertypes.StoreKey,
// ethermint keys
evmtypes.StoreKey, feemarkettypes.StoreKey,
// chiba-clonk keys
auctiontypes.StoreKey,
bondtypes.StoreKey,
nameservicetypes.StoreKey,
)
// Add the EVM transient store key
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
// initialize stores
setNamespaces := func(config *multi.StoreParams, ver uint64) error {
for _, key := range keys {
typ, err := storetypes.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
for _, key := range memKeys {
typ, err := storetypes.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
for _, key := range tkeys {
typ, err := storetypes.StoreKeyToType(key)
if err != nil {
return err
}
if err = config.RegisterSubstore(key, typ); err != nil {
return err
}
}
return nil
}
baseAppOptions = append(baseAppOptions, baseapp.StoreOption(setNamespaces))
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
bApp := baseapp.NewBaseApp(
@ -291,33 +347,14 @@ func NewEthermintApp(
)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
evmtypes.RegisterInterfaces(interfaceRegistry)
bApp.SetInterfaceRegistry(interfaceRegistry)
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,
registrytypes.StoreKey,
)
// Add the EVM transient store key
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
// load state streaming if enabled
// 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 {
fmt.Printf("failed to load state streaming: %s", err)
os.Exit(1)
tmos.Exit(err.Error())
}
app := &EthermintApp{
@ -348,114 +385,71 @@ func NewEthermintApp(
// use custom Ethermint account for contracts
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey],
app.GetSubspace(authtypes.ModuleName),
ethermint.ProtoAccount,
maccPerms,
sdk.GetConfig().GetBech32AccountAddrPrefix(),
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms, sdk.Bech32MainPrefix,
)
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)
// 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())
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())
// 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, app.GetSubspace(feemarkettypes.ModuleName), keys[feemarkettypes.StoreKey], tkeys[feemarkettypes.TransientKey],
appCodec, keys[feemarkettypes.StoreKey], app.GetSubspace(feemarkettypes.ModuleName),
)
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
// Create Vulcanize chiba-clonk keepers
app.AuctionKeeper = auctionkeeper.NewKeeper(
app.AccountKeeper, app.BankKeeper, keys[auctiontypes.StoreKey],
appCodec, app.GetSubspace(auctiontypes.ModuleName),
)
app.RegistryRecordKeeper = registrykeeper.NewRecordKeeper(app.AuctionKeeper, keys[registrytypes.StoreKey], appCodec)
app.NameServiceRecordKeeper = nameservicekeeper.NewRecordKeeper(app.AuctionKeeper, keys[nameservicetypes.StoreKey], appCodec)
app.AuctionKeeper.SetUsageKeepers([]auctiontypes.AuctionUsageKeeper{app.RegistryRecordKeeper})
app.AuctionKeeper.SetUsageKeepers([]auctiontypes.AuctionUsageKeeper{app.NameServiceRecordKeeper})
app.BondKeeper = bondkeeper.NewKeeper(
appCodec, app.AccountKeeper, app.BankKeeper,
[]bondtypes.BondUsageKeeper{app.RegistryRecordKeeper}, keys[bondtypes.StoreKey], app.GetSubspace(bondtypes.ModuleName),
[]bondtypes.BondUsageKeeper{app.NameServiceRecordKeeper}, keys[bondtypes.StoreKey], app.GetSubspace(bondtypes.ModuleName),
)
app.RegistryKeeper = registrykeeper.NewKeeper(
app.NameServiceKeeper = nameservicekeeper.NewKeeper(
appCodec, app.AccountKeeper, app.BankKeeper,
app.RegistryRecordKeeper, app.BondKeeper, app.AuctionKeeper,
keys[registrytypes.StoreKey], app.GetSubspace(registrytypes.ModuleName),
app.NameServiceRecordKeeper, app.BondKeeper, app.AuctionKeeper,
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
@ -470,11 +464,13 @@ 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,
@ -495,7 +491,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)
@ -526,7 +522,6 @@ 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),
@ -535,25 +530,25 @@ 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,
// Ethermint app modules
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper),
feemarket.NewAppModule(app.FeeMarketKeeper),
// laconic modules
// chiba-clonk modules
auction.NewAppModule(appCodec, app.AuctionKeeper),
bond.NewAppModule(appCodec, app.BondKeeper),
registry.NewAppModule(app.RegistryKeeper),
nameservice.NewAppModule(app.NameServiceKeeper),
)
// During begin block slashing happens after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant.
// NOTE: upgrade module must go first to handle software upgrades.
// NOTE: staking module is required if HistoricalEntries param > 0
// 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,
@ -577,10 +572,10 @@ func NewEthermintApp(
feegrant.ModuleName,
paramstypes.ModuleName,
vestingtypes.ModuleName,
// laconic modules
// chiba-clonk modules
auctiontypes.ModuleName,
bondtypes.ModuleName,
registrytypes.ModuleName,
nameservicetypes.ModuleName,
)
// NOTE: fee market module must go last in order to retrieve the block gas used.
@ -606,15 +601,14 @@ func NewEthermintApp(
paramstypes.ModuleName,
upgradetypes.ModuleName,
vestingtypes.ModuleName,
// laconic modules
// chiba-clonk modules
auctiontypes.ModuleName,
bondtypes.ModuleName,
registrytypes.ModuleName,
nameservicetypes.ModuleName,
)
// 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.
@ -629,11 +623,6 @@ 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,
@ -642,99 +631,83 @@ func NewEthermintApp(
paramstypes.ModuleName,
upgradetypes.ModuleName,
vestingtypes.ModuleName,
// laconic modules
// Ethermint modules
evmtypes.ModuleName,
feemarkettypes.ModuleName,
// chiba-clonk modules
auctiontypes.ModuleName,
bondtypes.ModuleName,
registrytypes.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{})
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)
// 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),
)
app.sm.RegisterStoreDecoders()
// initialize BaseApp
app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker)
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())
}
// 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.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
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,
ExtensionOptionChecker: ethermint.HasDynamicFeeExtensionOption,
// TxFeeChecker: ante.NewDynamicFeeChecker(app.EvmKeeper),
})
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() }
@ -760,13 +733,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 app.LoadVersion(height)
return nil
}
// 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
}
@ -778,7 +751,6 @@ 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]
}
@ -836,18 +808,25 @@ func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
return subspace
}
// SimulationManager implements the SimulationApp interface
func (app *EthermintApp) SimulationManager() *module.SimulationManager {
return app.sm
}
// RegisterAPIRoutes registers all application module routes with the provided
// API server.
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *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 node gRPC service for grpc-gateway.
node.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
@ -856,12 +835,10 @@ 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,
@ -871,12 +848,6 @@ func (app *EthermintApp) RegisterTendermintService(clientCtx client.Context) {
)
}
// RegisterNodeService registers the node gRPC service on the provided
// application gRPC query router.
func (app *EthermintApp) RegisterNodeService(clientCtx client.Context) {
node.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
}
// RegisterSwaggerAPI registers swagger route with API Server
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
statikFS, err := fs.New()
@ -894,11 +865,14 @@ 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
@ -915,9 +889,9 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
// ethermint subspaces
paramsKeeper.Subspace(evmtypes.ModuleName)
paramsKeeper.Subspace(feemarkettypes.ModuleName)
// laconic subspaces
// chiba-clonk subspaces
paramsKeeper.Subspace(auctiontypes.ModuleName)
paramsKeeper.Subspace(bondtypes.ModuleName)
paramsKeeper.Subspace(registrytypes.ModuleName)
paramsKeeper.Subspace(nameservicetypes.ModuleName)
return paramsKeeper
}

View File

@ -1,26 +1,45 @@
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"
"github.com/tharsis/ethermint/encoding"
)
func TestEthermintAppExport(t *testing.T) {
db := dbm.NewMemDB()
app := SetupWithDB(false, nil, db)
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",
)
}
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(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
app2 := NewEthermintApp(logger2, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
require.NoError(t, app2.Init())
_, err := app2.ExportAppStateAndValidators(false, []string{})
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
}

View File

@ -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"
"github.com/tharsis/ethermint/encoding"
)
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
db := dbm.NewMemDB()
app := NewEthermintApp(log.NewTMLogger(io.Discard), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
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{})
genesisState := NewTestGenesisState(app.AppCodec())
genesisState := NewDefaultGenesisState(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(log.NewTMLogger(log.NewSyncWriter(io.Discard)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
app2 := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
b.Fatal(err)
}

View File

@ -6,20 +6,18 @@ 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() simapp.GenesisState {
encCfg := encoding.MakeConfig(ModuleBasics)
return ModuleBasics.DefaultGenesis(encCfg.Codec)
func NewDefaultGenesisState(cdc codec.JSONCodec) simapp.GenesisState {
return ModuleBasics.DefaultGenesis(cdc)
}
// ExportAppStateAndValidators exports the state of the application for a genesis
@ -62,7 +60,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
@ -125,9 +123,7 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAd
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
app.DistrKeeper.SetFeePool(ctx, feePool)
if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()); err != nil {
return true
}
app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator())
return false
})
@ -141,12 +137,8 @@ func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAd
if err != nil {
return err
}
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
}
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr)
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr)
}
// reset context height

351
app/simulation_test.go Normal file
View File

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

283
app/test_helpers.go Normal file
View File

@ -0,0 +1,283 @@
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/cosmos/cosmos-sdk/simapp/params"
"github.com/stretchr/testify/require"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/encoding"
ethermint "github.com/tharsis/ethermint/types"
"github.com/cosmos/cosmos-sdk/db/memdb"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
)
// 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 := &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
}
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}
app := NewEthermintApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts)
genesisState := NewDefaultGenesisState(app.appCodec)
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
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 := &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
}
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}
app := SetupWithGenesisValSet(t, valSet, patchGenesis, []authtypes.GenesisAccount{acc}, balance)
return app
}
func setup(withGenesis bool, invCheckPeriod uint, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) (*EthermintApp, simapp.GenesisState) {
encCdc := encoding.MakeConfig(ModuleBasics)
app := NewEthermintApp(log.NewNopLogger(), memdb.NewDB(), nil, true, map[int64]bool{}, DefaultNodeHome, invCheckPeriod, encCdc, EmptyAppOptions{})
if withGenesis {
genesisState := NewDefaultGenesisState(encCdc.Codec)
if patchGenesis != nil {
genesisState = patchGenesis(app, genesisState)
}
return app, genesisState
}
return app, simapp.GenesisState{}
}
// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts
// that also act as delegators. For simplicity, each validator is bonded with a delegation
// of one consensus engine unit in the default token of the simapp from first genesis
// account. A Nop logger is set in SimApp.
func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *EthermintApp {
t.Helper()
app, genesisState := setup(true, 5, patchGenesis)
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, genAccs, balances...)
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)
// init chain will set the validator set and initialize the genesis accounts
app.InitChain(
abci.RequestInitChain{
ChainId: "ethermint_9000-1",
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)
// commit genesis changes
// app.Commit()
// app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
// ChainID: "ethermint_9000-1",
// Height: app.LastBlockHeight() + 1,
// AppHash: app.LastCommitID().Hash,
// ValidatorsHash: valSet.Hash(),
// NextValidatorsHash: valSet.Hash(),
// }})
return app
}
func genesisStateWithValSet(t *testing.T, app *EthermintApp, genesisState simapp.GenesisState,
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) simapp.GenesisState {
// set genesis accounts
authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
bondAmt := sdk.DefaultPowerReduction
for _, val := range valSet.Validators {
pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
require.NoError(t, err)
pkAny, err := codectypes.NewAnyWithValue(pk)
require.NoError(t, err)
validator := stakingtypes.Validator{
OperatorAddress: sdk.ValAddress(val.Address).String(),
ConsensusPubkey: pkAny,
Jailed: false,
Status: stakingtypes.Bonded,
Tokens: bondAmt,
DelegatorShares: sdk.OneDec(),
Description: stakingtypes.Description{},
UnbondingHeight: int64(0),
UnbondingTime: time.Unix(0, 0).UTC(),
Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
MinSelfDelegation: sdk.ZeroInt(),
}
validators = append(validators, validator)
delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec()))
}
// set validators and delegations
stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations)
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
totalSupply := sdk.NewCoins()
for _, b := range balances {
// add genesis acc tokens to total supply
totalSupply = totalSupply.Add(b.Coins...)
}
for range delegations {
// add delegated tokens to total supply
totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))
}
// add bonded amount to bonded pool module account
balances = append(balances, banktypes.Balance{
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)},
})
// update total supply
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{})
genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
return genesisState
}
// CreateRandomAccounts will generate random accounts
func CreateRandomAccounts(accNum int) []sdk.AccAddress {
// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
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
}

View File

@ -1,14 +0,0 @@
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)
})
}

View File

@ -1,201 +0,0 @@
package app
import (
"encoding/json"
"math/rand" // #nosec G702
"time"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"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/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/mock"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cerc-io/laconicd/encoding"
sdk "github.com/cosmos/cosmos-sdk/types"
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: "laconic_9000-1",
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
AppStateBytes: stateBytes,
},
)
}
return app
}
// 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)
}
// 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 := &ethsecp256k1.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
}
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
}

View File

@ -1,3 +1,4 @@
version: v1
directories:
- proto
- third_party/proto

View File

@ -12,7 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
ethermint "github.com/cerc-io/laconicd/types"
ethermint "github.com/tharsis/ethermint/types"
)
// InitConfig adds the chain-id, encoding and output flags to the persistent flag set.
@ -26,7 +26,7 @@ func InitConfig(cmd *cobra.Command) error {
_, err = os.Stat(configFile)
if err != nil && !os.IsNotExist(err) {
// Immediately return if the error isn't related to the file not existing.
// See issue https://github.com/cerc-io/laconicd/issues/539
// See issue https://github.com/tharsis/ethermint/issues/539
return err
}
if err == nil {

View File

@ -13,6 +13,57 @@
"Params": "EvmParams"
}
}
},
{
"url": "./tmp-swagger-gen/cosmos/auth/v1beta1/query.swagger.json",
"operationIds": {
"rename": {
"Account": "AuthAccount",
"Params": "AuthParams"
}
}
},
{
"url": "./tmp-swagger-gen/cosmos/bank/v1beta1/query.swagger.json",
"operationIds": {
"rename": {
"Balance": "BankBalance",
"Params": "BankParams"
}
}
},
{
"url": "./tmp-swagger-gen/cosmos/distribution/v1beta1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "DistributionParams",
"DelegatorValidators": "DistDelegatorValidators"
}
}
},
{
"url": "./tmp-swagger-gen/cosmos/mint/v1beta1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "MintParams"
}
}
},
{
"url": "./tmp-swagger-gen/cosmos/gov/v1beta1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "GovParams"
}
}
},
{
"url": "./tmp-swagger-gen/cosmos/staking/v1beta1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "StakingParams"
}
}
}
]
}

View File

@ -1,3 +1,3 @@
package statik
// This just for fixing the error in importing empty github.com/cerc-io/laconicd/client/docs/statik
// This just for fixing the error in importing empty github.com/tharsis/ethermint/client/docs/statik

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -6,15 +6,17 @@ 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"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/crypto/hd"
)
// UnsafeExportEthKeyCommand exports a key with the given name as a private key in hex format.
@ -25,8 +27,19 @@ 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 {
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
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(),
)
if err != nil {
return err
}
@ -34,8 +47,7 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
decryptPassword := ""
conf := true
inBuf := bufio.NewReader(cmd.InOrStdin())
switch clientCtx.Keyring.Backend() {
switch keyringBackend {
case keyring.BackendFile:
decryptPassword, err = input.GetPassword(
"**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:",
@ -50,7 +62,7 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
}
// Exports private key from keybase using password
armor, err := clientCtx.Keyring.ExportPrivKeyArmor(args[0], decryptPassword)
armor, err := kr.ExportPrivKeyArmor(args[0], decryptPassword)
if err != nil {
return err
}

View File

@ -5,13 +5,16 @@ import (
"github.com/spf13/cobra"
"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/tharsis/ethermint/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/crypto/hd"
"github.com/tharsis/ethermint/crypto/hd"
)
// UnsafeImportKeyCommand imports private keys from a keyfile.
@ -26,13 +29,23 @@ func UnsafeImportKeyCommand() *cobra.Command {
}
func runImportCmd(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
inBuf := bufio.NewReader(cmd.InOrStdin())
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
clientCtx := client.GetClientContextFromCmd(cmd)
kb, err := keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
rootDir,
inBuf,
clientCtx.Codec,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
inBuf := bufio.NewReader(cmd.InOrStdin())
passphrase, err := input.GetPassword("Enter passphrase to encrypt your key:", inBuf)
if err != nil {
return err
@ -44,5 +57,5 @@ func runImportCmd(cmd *cobra.Command, args []string) error {
armor := crypto.EncryptArmorPrivKey(privKey, passphrase, "eth_secp256k1")
return clientCtx.Keyring.ImportPrivKey(args[0], armor, passphrase)
return kb.ImportPrivKey(args[0], armor, passphrase)
}

View File

@ -6,12 +6,13 @@ 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"
clientkeys "github.com/cerc-io/laconicd/client/keys"
"github.com/cerc-io/laconicd/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
clientkeys "github.com/tharsis/ethermint/client/keys"
"github.com/tharsis/ethermint/crypto/hd"
)
// KeyCommands registers a sub-tree of commands to interact with
@ -48,7 +49,7 @@ The pass backend requires GnuPG: https://gnupg.org/
addCmd := keys.AddKeyCommand()
// update the default signing algorithm value to "eth_secp256k1"
algoFlag := addCmd.Flag(flags.FlagKeyAlgorithm)
algoFlag := addCmd.Flag("algo")
algoFlag.DefValue = string(hd.EthSecp256k1Type)
err := algoFlag.Value.Set(string(hd.EthSecp256k1Type))
if err != nil {
@ -64,8 +65,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,
@ -81,11 +82,23 @@ The pass backend requires GnuPG: https://gnupg.org/
}
func runAddCmd(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option())
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
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)
}
if err != nil {
return err
}
buf := bufio.NewReader(clientCtx.Input)
return clientkeys.RunAddCmd(clientCtx, cmd, args, buf)
}

View File

@ -7,7 +7,7 @@ import (
"fmt"
"sort"
etherminthd "github.com/cerc-io/laconicd/crypto/hd"
etherminthd "github.com/tharsis/ethermint/crypto/hd"
bip39 "github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
@ -38,44 +38,84 @@ const (
mnemonicEntropySize = 256
)
/*
RunAddCmd
input
- bip39 mnemonic
- bip39 passphrase
- bip44 path
- local encryption password
// 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)
}
/*
input
- 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 (
algo keyring.SignatureAlgo
err error
)
var err error
name := args[0]
interactive, _ := cmd.Flags().GetBool(flagInteractive)
noBackup, _ := cmd.Flags().GetBool(flagNoBackup)
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
showMnemonic := !noBackup
kb := ctx.Keyring
outputFormat := ctx.OutputFormat
keyringAlgos, ledgerAlgos := kb.SupportedAlgorithms()
// check if the provided signing algorithm is supported by the keyring or
// ledger
if useLedger {
algo, err = keyring.NewSigningAlgoFromString(algoStr, ledgerAlgos)
} else {
algo, err = keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
}
keyringAlgos, _ := kb.SupportedAlgorithms()
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
if err != nil {
return err
}
@ -116,11 +156,9 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}
key, err := k.GetPubKey()
if err != nil {
if pks[i], err = k.GetPubKey(); err != nil {
return err
}
pks[i] = key
}
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
@ -130,34 +168,36 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
}
pk := multisig.NewLegacyAminoPubKey(multisigThreshold, pks)
k, err := kb.SaveMultisig(name, pk)
info, err := kb.SaveMultisig(name, pk)
if err != nil {
return err
}
return printCreate(cmd, k, false, "", outputFormat)
return printCreate(cmd, info, false, "", outputFormat)
}
}
pubKey, _ := cmd.Flags().GetString(keys.FlagPublicKey)
if pubKey != "" {
var pk cryptotypes.PubKey
if err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk); err != nil {
return err
}
k, err := kb.SaveOfflineKey(name, pk)
err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk)
if err != nil {
return err
}
return printCreate(cmd, k, false, "", outputFormat)
info, err := kb.SaveOfflineKey(name, pk)
if err != nil {
return err
}
return printCreate(cmd, info, false, "", outputFormat)
}
coinType, _ := cmd.Flags().GetUint32(flagCoinType)
account, _ := cmd.Flags().GetUint32(flagAccount)
index, _ := cmd.Flags().GetUint32(flagIndex)
hdPath, _ := cmd.Flags().GetString(flagHDPath)
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
if len(hdPath) == 0 {
hdPath = hd.CreateHDPath(coinType, account, index).String()
@ -169,13 +209,12 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
if useLedger {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
// use the provided algo to save the ledger key
k, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index)
info, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index)
if err != nil {
return err
}
return printCreate(cmd, k, false, "", outputFormat)
return printCreate(cmd, info, false, "", outputFormat)
}
// Get bip39 mnemonic
@ -237,7 +276,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
}
}
k, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
info, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
if err != nil {
return err
}
@ -249,27 +288,24 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
mnemonic = ""
}
return printCreate(cmd, k, showMnemonic, mnemonic, outputFormat)
return printCreate(cmd, info, showMnemonic, mnemonic, outputFormat)
}
func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
func printCreate(cmd *cobra.Command, info *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
switch outputFormat {
case OutputFormatText:
cmd.PrintErrln()
if err := printKeyringRecord(cmd.OutOrStdout(), k, keyring.MkAccKeyOutput, outputFormat); err != nil {
return err
}
printKeyInfo(cmd.OutOrStdout(), info, keyring.MkAccKeyOutput, outputFormat)
// print mnemonic unless requested not to.
if showMnemonic {
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)
}
fmt.Fprintln(cmd.ErrOrStderr(), "\n**Important** write this mnemonic phrase in a safe place.")
fmt.Fprintln(cmd.ErrOrStderr(), "It is the only way to recover your account if you ever forget your password.")
fmt.Fprintln(cmd.ErrOrStderr(), "")
fmt.Fprintln(cmd.ErrOrStderr(), mnemonic)
}
case OutputFormatJSON:
out, err := keyring.MkAccKeyOutput(k)
out, err := keyring.MkAccKeyOutput(info)
if err != nil {
return err
}
@ -291,14 +327,3 @@ func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemo
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
}

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

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

View File

@ -4,7 +4,7 @@ import (
"fmt"
"io"
"sigs.k8s.io/yaml"
yaml "gopkg.in/yaml.v2"
"github.com/cosmos/cosmos-sdk/client/keys"
cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
@ -14,45 +14,48 @@ import (
const (
OutputFormatText = "text"
OutputFormatJSON = "json"
// defaultKeyDBName is the client's subdirectory where keys are stored.
defaultKeyDBName = "keys"
)
type bechKeyOutFn func(k *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
type bechKeyOutFn func(keyInfo *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) error {
ko, err := bechKeyOut(k)
func printKeyInfo(w io.Writer, keyInfo *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) {
ko, err := bechKeyOut(keyInfo)
if err != nil {
return err
panic(err)
}
switch output {
case OutputFormatText:
if err := printTextRecords(w, []cryptokeyring.KeyOutput{ko}); err != nil {
return err
}
printTextInfos(w, []cryptokeyring.KeyOutput{ko})
case OutputFormatJSON:
out, err := keys.KeysCdc.MarshalJSON(ko)
if err != nil {
return err
panic(err)
}
if _, err := fmt.Fprintln(w, string(out)); err != nil {
return err
}
fmt.Fprintln(w, string(out))
}
return nil
}
func printTextRecords(w io.Writer, kos []cryptokeyring.KeyOutput) error {
func printTextInfos(w io.Writer, kos []cryptokeyring.KeyOutput) {
out, err := yaml.Marshal(&kos)
if err != nil {
return err
panic(err)
}
fmt.Fprintln(w, string(out))
}
if _, err := fmt.Fprintln(w, string(out)); err != nil {
return err
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
}

View File

@ -6,17 +6,18 @@ 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"
@ -34,17 +35,18 @@ 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"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cerc-io/laconicd/crypto/hd"
"github.com/cerc-io/laconicd/server/config"
srvflags "github.com/cerc-io/laconicd/server/flags"
ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/tharsis/ethermint/crypto/hd"
"github.com/tharsis/ethermint/server/config"
srvflags "github.com/tharsis/ethermint/server/flags"
ethermint "github.com/tharsis/ethermint/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
"github.com/cerc-io/laconicd/testutil/network"
"github.com/tharsis/ethermint/testutil/network"
)
var (
@ -87,12 +89,9 @@ 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", "./.testnets", "Directory to store initialization data for the testnet")
cmd.Flags().StringP(flagOutputDir, "o", "./localnet-setup", "Directory to store initialization data for the testnet")
cmd.Flags().String(flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
cmd.Flags().String(sdkserver.FlagMinGasPrices,
fmt.Sprintf("0.000006%s",
ethermint.AttoPhoton),
"Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)")
cmd.Flags().String(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")
}
@ -117,7 +116,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)", //nolint:lll
Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)",
Long: `init-files will setup "v" number of directories and populate each with
necessary files (private validator, genesis, config, etc.) for running "v" validator nodes.
@ -127,7 +126,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:
evmosd testnet init-files --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
chibaclonkd testnet init-files --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2
`,
RunE: func(cmd *cobra.Command, _ []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
@ -154,10 +153,8 @@ 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, "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(flagNodeDaemonHome, "chibaclonkd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagStartingIPAddress, "192.168.10.1", "Starting IP address (192.168.10.1 results in persistent peers list ID0@192.168.10.1:46656, ID1@192.168.10.2:46656, ...)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
return cmd
@ -173,7 +170,7 @@ and generate "v" directories, populated with necessary validator configuration f
(private validator, genesis, config, etc.).
Example:
evmosd testnet --v 4 --output-dir ./.testnets
chibaclonkd testnet --v 4 --output-dir ./.testnets
`,
RunE: func(cmd *cobra.Command, _ []string) error {
args := startArgs{}
@ -215,7 +212,7 @@ func initTestnetFiles(
args initArgs,
) error {
if args.chainID == "" {
args.chainID = fmt.Sprintf("ethermint_%d-1", tmrand.Int63n(9999999999999)+1)
args.chainID = fmt.Sprintf("ethermint_%d-1", rand.Int63n(9999999999999)+1)
}
nodeIDs := make([]string, args.numValidators)
@ -349,7 +346,8 @@ func initTestnetFiles(
customAppTemplate, customAppConfig := config.AppConfig(ethermint.AttoPhoton)
srvconfig.SetConfigTemplate(customAppTemplate)
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, tmconfig.DefaultConfig()); err != nil {
customTmConfig := tmcfg.DefaultConfig()
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTmConfig); err != nil {
return err
}
@ -408,7 +406,7 @@ func initGenFiles(
stakingGenState.Params.BondDenom = coinDenom
appGenState[stakingtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&stakingGenState)
var govGenState govv1.GenesisState
var govGenState v1.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
@ -458,7 +456,7 @@ func collectGenFiles(
outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator,
) error {
var appState json.RawMessage
genTime := tmtime.Now()
genTime := time.Now()
for i := 0; i < numValidators; i++ {
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)

View File

@ -10,12 +10,12 @@ import (
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"github.com/cerc-io/laconicd/app"
laconicd "github.com/cerc-io/laconicd/cmd/laconicd"
"github.com/tharsis/ethermint/app"
chibaclonkd "github.com/tharsis/ethermint/cmd/chibaclonkd"
)
func TestInitCmd(t *testing.T) {
rootCmd, _ := laconicd.NewRootCmd()
rootCmd, _ := chibaclonkd.NewRootCmd()
rootCmd.SetArgs([]string{
"init", // Test the init cmd
"etherminttest", // Moniker
@ -23,6 +23,6 @@ func TestInitCmd(t *testing.T) {
fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint_9000-1"),
})
err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome)
err := svrcmd.Execute(rootCmd, chibaclonkd.EnvPrefix, app.DefaultNodeHome)
require.NoError(t, err)
}

View File

@ -5,10 +5,12 @@ import (
"github.com/spf13/cobra"
"github.com/cerc-io/laconicd/version"
"github.com/tharsis/ethermint/version"
)
const flagLong = "long"
const (
flagLong = "long"
)
func init() {
infoCmd.Flags().Bool(flagLong, false, "Print full information")

View File

@ -1,6 +1,7 @@
package main
import (
"bufio"
"encoding/json"
"errors"
"fmt"
@ -10,6 +11,7 @@ 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"
@ -18,9 +20,9 @@ import (
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cerc-io/laconicd/crypto/hd"
ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/tharsis/ethermint/crypto/hd"
ethermint "github.com/tharsis/ethermint/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
const (
@ -32,7 +34,7 @@ const (
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "add-genesis-account ADDRESS_OR_KEY_NAME COIN...",
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
Short: "Add a genesis account to genesis.json",
Long: `Add a genesis account to genesis.json. The provided account must specify
the account address or key name and a list of initial coins. If a key name is given,
@ -41,20 +43,36 @@ 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).WithKeyringOptions(hd.EthSecp256k1Option())
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
clientCtx := client.GetClientContextFromCmd(cmd)
serverCtx := server.GetServerContextFromCmd(cmd)
config := serverCtx.Config
config.SetRoot(clientCtx.HomeDir)
kr := clientCtx.Keyring
var kr keyring.Keyring
addr, err := sdk.AccAddressFromBech32(args[0])
if err != nil {
inBuf := bufio.NewReader(cmd.InOrStdin())
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
if keyringBackend != "" && clientCtx.Keyring == nil {
var err error
kr, err = keyring.New(
sdk.KeyringServiceName(),
keyringBackend,
clientCtx.HomeDir,
inBuf,
clientCtx.Codec,
hd.EthSecp256k1Option(),
)
if err != nil {
return err
}
} else {
kr = clientCtx.Keyring
}
info, err := kr.Key(args[0])
if err != nil {
return fmt.Errorf("failed to get address from Keyring: %w", err)
@ -62,7 +80,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
addr, err = info.GetAddress()
if err != nil {
return err
return fmt.Errorf("failed to get address from Keyring: %w", err)
}
}

24
cmd/chibaclonkd/main.go Normal file
View File

@ -0,0 +1,24 @@
package main
import (
"os"
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/tharsis/ethermint/app"
)
func main() {
rootCmd, _ := NewRootCmd()
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
switch e := err.(type) {
case server.ErrorCode:
os.Exit(e.Code)
default:
os.Exit(1)
}
}
}

View File

@ -6,19 +6,13 @@ 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"
@ -31,20 +25,24 @@ 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"
"github.com/cerc-io/laconicd/client/debug"
"github.com/cerc-io/laconicd/crypto/hd"
"github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/ethereum/eip712"
"github.com/cerc-io/laconicd/server"
servercfg "github.com/cerc-io/laconicd/server/config"
srvflags "github.com/cerc-io/laconicd/server/flags"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/tharsis/ethermint/app"
ethermintclient "github.com/tharsis/ethermint/client"
"github.com/tharsis/ethermint/client/debug"
"github.com/tharsis/ethermint/crypto/hd"
"github.com/tharsis/ethermint/encoding"
"github.com/tharsis/ethermint/server"
servercfg "github.com/tharsis/ethermint/server/config"
srvflags "github.com/tharsis/ethermint/server/flags"
ethermint "github.com/tharsis/ethermint/types"
)
const EnvPrefix = "LACONIC"
const EnvPrefix = "CHIBACLONK"
// NewRootCmd creates a new root command for simd. It is called once in the
// main function.
@ -62,11 +60,9 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
WithKeyringOptions(hd.EthSecp256k1Option()).
WithViper(EnvPrefix)
eip712.SetEncodingConfig(encodingConfig)
rootCmd := &cobra.Command{
Use: "laconicd",
Short: "Laconic Daemon",
Use: "chibaclonkd",
Short: "Chiba-Clonk Daemon",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// set the default command outputs
cmd.SetOut(cmd.OutOrStdout())
@ -88,13 +84,14 @@ 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, tmcfg.DefaultConfig())
return sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTMConfig)
},
}
// TODO: double-check
// authclient.Codec = encodingConfig.Codec
// authclient.Codec = encodingConfig.Marshaler
cfg := sdk.GetConfig()
cfg.Seal()
@ -143,6 +140,18 @@ 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",
@ -185,7 +194,6 @@ func txCommand() *cobra.Command {
authcmd.GetBroadcastCommand(),
authcmd.GetEncodeCommand(),
authcmd.GetDecodeCommand(),
authcmd.GetAuxToFeeCommand(),
)
app.ModuleBasics.AddTxCommands(cmd)
@ -199,7 +207,7 @@ type appCreator struct {
}
// newApp is an appCreator
func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
var cache sdk.MultiStorePersistentCache
if cast.ToBool(appOpts.Get(sdkserver.FlagInterBlockCache)) {
@ -217,11 +225,7 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
}
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")
if err = os.MkdirAll(snapshotDir, os.ModePerm); err != nil {
panic(err)
}
snapshotDB, err := dbm.NewDB("metadata", sdkserver.GetAppDBBackend(appOpts), snapshotDir)
snapshotDB, err := badgerdb.NewDB(filepath.Join(snapshotDir, "metadata"))
if err != nil {
panic(err)
}
@ -229,7 +233,6 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
if err != nil {
panic(err)
}
snapshotOptions := snapshottypes.NewSnapshotOptions(
cast.ToUint64(appOpts.Get(sdkserver.FlagStateSyncSnapshotInterval)),
cast.ToUint32(appOpts.Get(sdkserver.FlagStateSyncSnapshotKeepRecent)),
@ -250,8 +253,6 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
baseapp.SetTrace(cast.ToBool(appOpts.Get(sdkserver.FlagTrace))),
baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))),
baseapp.SetSnapshot(snapshotStore, snapshotOptions),
baseapp.SetIAVLCacheSize(cast.ToInt(appOpts.Get(sdkserver.FlagIAVLCacheSize))),
baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(sdkserver.FlagDisableIAVLFastNode))),
)
return ethermintApp
@ -260,7 +261,7 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
// appExport creates a new simapp (optionally at a given height)
// and exports state.
func (a appCreator) appExport(
logger tmlog.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
logger tmlog.Logger, db dbm.DBConnection, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
appOpts servertypes.AppOptions,
) (servertypes.ExportedApp, error) {
var ethermintApp *app.EthermintApp

View File

@ -3,12 +3,12 @@ package config
import (
sdk "github.com/cosmos/cosmos-sdk/types"
ethermint "github.com/cerc-io/laconicd/types"
ethermint "github.com/tharsis/ethermint/types"
)
const (
// Bech32Prefix defines the Bech32 prefix used for EthAccounts
Bech32Prefix = "ethm"
Bech32Prefix = ethermint.Bech32MainPrefix
// 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.

View File

@ -3,8 +3,8 @@ package config
import (
"testing"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/stretchr/testify/require"
ethermint "github.com/tharsis/ethermint/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
sdk "github.com/cosmos/cosmos-sdk/types"

View File

@ -1,37 +0,0 @@
package main
import (
"os"
"github.com/cosmos/cosmos-sdk/server"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cerc-io/laconicd/app"
cmdcfg "github.com/cerc-io/laconicd/cmd/config"
)
func main() {
setupConfig()
cmdcfg.RegisterDenoms()
rootCmd, _ := NewRootCmd()
if err := svrcmd.Execute(rootCmd, EnvPrefix, app.DefaultNodeHome); err != nil {
switch e := err.(type) {
case server.ErrorCode:
os.Exit(e.Code)
default:
os.Exit(1)
}
}
}
func setupConfig() {
// set the address prefixes
config := sdk.GetConfig()
cmdcfg.SetBech32Prefixes(config)
cmdcfg.SetBip44CoinType(config)
config.Seal()
}

View File

@ -30,7 +30,7 @@ if [ -z "$4" ]; then
exit 1
fi
docker_containers=($(docker ps -q -f name=laconicd --format='{{.Names}}'))
docker_containers=($(docker ps -q -f name=ethermintd --format='{{.Names}}'))
while [ ${CNT} -lt $ITER ]; do
curr_block=$(curl -s $NODEADDR:26657/status | jq -r '.result.sync_info.latest_block_height')

View File

@ -7,7 +7,7 @@ import (
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
)
// RegisterCrypto registers all crypto dependency types with the provided Amino

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