Sync from fork #74

Merged
0xmuralik merged 232 commits from murali/update-fork into main 2023-01-10 04:50:57 +00:00
354 changed files with 44802 additions and 13430 deletions

View File

@ -1,115 +1,6 @@
--- ---
Language: Proto Language: Proto
# BasedOnStyle: LLVM BasedOnStyle: google
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 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 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
... ...

5
.flake8 Normal file
View File

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

5
.github/CODEOWNERS vendored
View File

@ -1,4 +1,5 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/ # CODEOWNERS: https://help.github.com/articles/about-codeowners/
# Primary repo maintainers # Primary (global) repo maintainers
* @fedekunze @khoslaventures @jolube
* @evmos/core-engineering

View File

@ -17,16 +17,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v2 - uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
- uses: technote-space/get-diff-action@v6.0.1 check-latest: true
- uses: technote-space/get-diff-action@v6.1.2
id: git_diff id: git_diff
with: with:
SUFFIX_FILTER: | PATTERNS: |
.go **/**.go
.mod go.mod
.sum go.sum
- run: | - run: |
make build make build
if: env.GIT_DIFF if: env.GIT_DIFF

View File

@ -32,7 +32,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: [ 'go', 'javascript' ] language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more: # 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 # 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
@ -40,21 +40,33 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.2
with:
PATTERNS: |
**/**.sol
**/**.go
**/**.ts
**/**.js
go.mod
go.sum
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # 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. # 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. # 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 # queries: ./path/to/local/query, your-org/your-repo/queries@main
queries: crypto-com/cosmos-sdk-codeql@main,security-and-quality
if: env.GIT_DIFF
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # 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) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@v2
if: env.GIT_DIFF
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@ -68,4 +80,5 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@v2
if: env.GIT_DIFF

28
.github/workflows/dependencies.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: "Dependency Review"
on: pull_request
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.19
check-latest: true
- name: "Checkout Repository"
uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.2
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: "Dependency Review"
uses: actions/dependency-review-action@v3
if: env.GIT_DIFF
- name: "Go vulnerability check"
run: make vulncheck
if: env.GIT_DIFF

View File

@ -23,14 +23,14 @@ jobs:
node-version: '12.x' node-version: '12.x'
- name: Install dependencies - name: Install dependencies
run: npm install run: npm install
- uses: technote-space/get-diff-action@v6.0.1 - uses: technote-space/get-diff-action@v6.1.2
id: git_diff id: git_diff
with: with:
SUFFIX_FILTER: | PATTERNS: |
.go **/**.sol
.mod **/**.go
.sum go.mod
.sol go.sum
- name: Test contract - name: Test contract
run: | run: |
sudo make contract-tools sudo make contract-tools

View File

@ -13,9 +13,10 @@ jobs:
with: with:
submodules: true submodules: true
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v2 uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
check-latest: true
- name: release dry run - name: release dry run
run: make release-dry-run run: make release-dry-run
- name: setup release environment - name: setup release environment

View File

@ -1,12 +0,0 @@
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,20 +13,40 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
# Required: setup-go, for all versions v3.0.0+ of golangci-lint
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
check-latest: true
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.0 - uses: technote-space/get-diff-action@v6.1.2
with: with:
PATTERNS: | PATTERNS: |
**/**.go **/**.go
go.mod go.mod
go.sum go.sum
- uses: golangci/golangci-lint-action@v3 - uses: golangci/golangci-lint-action@v3.3.1
with: with:
version: v1.48.0 # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: latest
args: --timeout 10m args: --timeout 10m
github-token: ${{ secrets.github_token }} github-token: ${{ secrets.github_token }}
# Check only if there are differences in the source code # Check only if there are differences in the source code
if: "env.GIT_DIFF" if: env.GIT_DIFF
python-lint:
name: Run flake8 on python integration tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v18
- uses: cachix/cachix-action@v12
with:
name: ethermint
- uses: technote-space/get-diff-action@v6.1.2
with:
PATTERNS: |
**/**.py
- run: |
nix-shell -I nixpkgs=./nix -p test-env --run "make lint-py"
if: env.GIT_DIFF

View File

@ -3,6 +3,8 @@ name: Protobuf
# This workflow is only run when a .proto file has been changed # This workflow is only run when a .proto file has been changed
on: on:
pull_request: pull_request:
paths:
- "proto/**"
jobs: jobs:
lint: lint:
@ -10,21 +12,17 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1 - uses: bufbuild/buf-setup-action@v1.9.0
- uses: bufbuild/buf-lint-action@v1
with: with:
PATTERNS: | input: "proto"
**/**.proto
- name: lint break-check:
run: make proto-lint
if: env.GIT_DIFF
breakage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.0.1 - uses: bufbuild/buf-setup-action@v1.9.0
- uses: bufbuild/buf-breaking-action@v1
with: with:
PATTERNS: | input: "proto"
**/**.proto against: "https://github.com/${{ github.repository }}.git#branch=${{ github.event.pull_request.base.ref }},ref=HEAD~1,subdir=proto"
- name: check-breakage
run: make proto-check-breaking
if: env.GIT_DIFF

View File

@ -7,6 +7,9 @@ on:
jobs: jobs:
Gosec: Gosec:
permissions:
security-events: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
GO111MODULE: on GO111MODULE: on
@ -14,7 +17,7 @@ jobs:
- name: Checkout Source - name: Checkout Source
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Get Diff - name: Get Diff
uses: technote-space/get-diff-action@v6.0.1 uses: technote-space/get-diff-action@v6.1.2
with: with:
PATTERNS: | PATTERNS: |
**/*.go **/*.go
@ -27,7 +30,7 @@ jobs:
args: '-no-fail -fmt sarif -out results.sarif -exclude=G701,G703 ./...' args: '-no-fail -fmt sarif -out results.sarif -exclude=G701,G703 ./...'
if: "env.GIT_DIFF_FILTERED != ''" if: "env.GIT_DIFF_FILTERED != ''"
- name: Upload SARIF file - name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1 uses: github/codeql-action/upload-sarif@v2
with: with:
# Path to SARIF file relative to the root of the repository # Path to SARIF file relative to the root of the repository
sarif_file: results.sarif sarif_file: results.sarif

View File

@ -10,14 +10,19 @@ on:
schedule: schedule:
- cron: '0 0 * * 0' - cron: '0 0 * * 0'
jobs: jobs:
# Update from: https://semgrep.dev/docs/semgrep-ci/sample-ci-configs/#github-actions
semgrep: semgrep:
name: Scan name: Scan
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
if: (github.actor != 'dependabot[bot]') if: (github.actor != 'dependabot[bot]')
steps: steps:
- name: Permission issue fix
run: git config --global --add safe.directory /__w/laconicd/laconicd
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Get Diff - name: Get Diff
uses: technote-space/get-diff-action@v6.0.1 uses: technote-space/get-diff-action@v6.1.2
with: with:
PATTERNS: | PATTERNS: |
**/*.go **/*.go
@ -26,16 +31,15 @@ jobs:
**/*.sol **/*.sol
go.mod go.mod
go.sum go.sum
- uses: returntocorp/semgrep-action@v1 - uses: actions/checkout@v3
with: - run: semgrep scan --sarif --output=semgrep.sarif --config auto
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }} env:
# Upload findings to GitHub Advanced Security Dashboard [step 1/2] # Upload findings to GitHub Advanced Security Dashboard [step 1/2]
# See also the next step. SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
generateSarif: "1"
if: "env.GIT_DIFF_FILTERED != ''" if: "env.GIT_DIFF_FILTERED != ''"
# Upload findings to GitHub Advanced Security Dashboard [step 2/2] # Upload findings to GitHub Advanced Security Dashboard [step 2/2]
- name: Upload SARIF file for GitHub Advanced Security Dashboard - name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1 uses: github/codeql-action/upload-sarif@v2
with: with:
sarif_file: semgrep.sarif sarif_file: semgrep.sarif
if: "env.GIT_DIFF_FILTERED != ''" if: "env.GIT_DIFF_FILTERED != ''"

21
.github/workflows/stale.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: "Close stale issues & pull requests"
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v6
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: "This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed in 7 days-before-close if no further activity occurs."
stale-issue-message: "This issue is stale because it has been open 45 days with no activity. Remove `Status: Stale` label or comment or this will be closed in 7 days."
days-before-stale: 45
days-before-close: 7
exempt-issue-labels: "Status: Blocked, Type: Bug, pinned, automerge"
exempt-pr-labels: "Status: Blocked, Type: Bug, pinned, automerge"
stale-pr-label: "Status: Stale"
stale-issue-label: "Status: Stale"

View File

@ -20,10 +20,10 @@ jobs:
steps: steps:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
check-latest: true check-latest: true
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1 - uses: technote-space/get-diff-action@v6.1.2
with: with:
PATTERNS: | PATTERNS: |
**/**.go **/**.go
@ -45,10 +45,10 @@ jobs:
steps: steps:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
check-latest: true check-latest: true
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1 - uses: technote-space/get-diff-action@v6.1.2
id: git_diff id: git_diff
with: with:
PATTERNS: | PATTERNS: |
@ -66,10 +66,10 @@ jobs:
steps: steps:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.19
check-latest: true check-latest: true
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1 - uses: technote-space/get-diff-action@v6.1.2
with: with:
PATTERNS: | PATTERNS: |
**/**.sol **/**.sol
@ -81,37 +81,16 @@ jobs:
make test-rpc make test-rpc
if: env.GIT_DIFF if: env.GIT_DIFF
test-e2e:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1
with:
PATTERNS: |
**/**.sol
**/**.go
go.mod
go.sum
- name: Test e2e
run: |
make test-integration
if: env.GIT_DIFF
# integration_tests: # integration_tests:
# runs-on: ubuntu-latest # runs-on: ubuntu-latest
# steps: # steps:
# - uses: actions/checkout@v2 # - uses: actions/checkout@v2
# - uses: cachix/install-nix-action@v18 # - uses: cachix/install-nix-action@v18
# - uses: cachix/cachix-action@v11 # - uses: cachix/cachix-action@v12
# with: # with:
# name: ethermint # name: ethermint
# signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" # signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
# - uses: technote-space/get-diff-action@v6.1.1 # - uses: technote-space/get-diff-action@v6.1.2
# with: # with:
# PATTERNS: | # PATTERNS: |
# **/**.sol # **/**.sol
@ -142,89 +121,9 @@ jobs:
# steps: # steps:
# - uses: actions/checkout@v2 # - uses: actions/checkout@v2
# - uses: cachix/install-nix-action@v18 # - uses: cachix/install-nix-action@v18
# - uses: cachix/cachix-action@v11 # - uses: cachix/cachix-action@v12
# with: # with:
# name: ethermint # name: ethermint
# signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}" # signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
# - name: 'instantiate integration test env' # - name: 'instantiate integration test env'
# run: nix-store -r $(nix-instantiate tests/integration_tests/shell.nix) # run: nix-store -r "$(nix-instantiate tests/integration_tests/shell.nix)"
test-sim-nondeterminism:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test simulation nondeterminism
run: |
make test-sim-nondeterminism
if: env.GIT_DIFF
test-sim-random-genesis-fast:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test simulation with random genesis
run: |
make test-sim-random-genesis-fast
if: env.GIT_DIFF
test-sim-import-export:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Simulation of import and export genesis
run: |
make test-sim-import-export
if: env.GIT_DIFF
test-sim-after-import:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
check-latest: true
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6.1.1
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: Test simulation after import
run: |
make test-sim-after-import
if: env.GIT_DIFF

14
.gitignore vendored
View File

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

2766
.gitleaks.toml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,47 +6,35 @@ run:
linters: linters:
enable: enable:
- bodyclose - bodyclose
- deadcode
- depguard - depguard
- dogsled - dogsled
- dupl - dupl
- errcheck - errcheck
- goconst - goconst
- gocritic - gocritic
- gofmt - gofumpt
- goimports
- revive - revive
- gosec - gosec
- gosimple - gosimple
- govet - govet
- ineffassign - ineffassign
# - lll TODO: enable - lll
- misspell - misspell
- nakedret - nakedret
- prealloc - prealloc
- exportloopref - exportloopref
- staticcheck - staticcheck
- structcheck
- stylecheck - stylecheck
# - typecheck #TODO: enable - typecheck
- unconvert - unconvert
- unparam - unparam
- unused - unused
- varcheck
- nolintlint - nolintlint
- asciicheck - asciicheck
# - exhaustive
- exportloopref - exportloopref
- gofumpt - gofumpt
- gomodguard - gomodguard
# - nestif - whitespace
# - nlreturn
- noctx
- rowserrcheck
# - whitespace
# - wsl
disable:
- typecheck
issues: issues:
exclude-rules: exclude-rules:
@ -59,6 +47,8 @@ issues:
max-same-issues: 50 max-same-issues: 50
linters-settings: linters-settings:
lll:
line-length: 150
dogsled: dogsled:
max-blank-identifiers: 3 max-blank-identifiers: 3
golint: golint:
@ -73,7 +63,7 @@ linters-settings:
require-explanation: false require-explanation: false
require-specific: false require-specific: false
gofumpt: gofumpt:
lang-version: "1.17" lang-version: "1.19"
gomodguard: gomodguard:
blocked: blocked:
versions: # List of blocked module version constraints versions: # List of blocked module version constraints

21
.markdownlint.yml Normal file
View File

@ -0,0 +1,21 @@
"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

3
.markdownlintignore Normal file
View File

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

View File

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

174
.protolint.yml Normal file
View File

@ -0,0 +1,174 @@
---
# 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

3
.solhint.json Normal file
View File

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

31
.yamllint Normal file
View File

@ -0,0 +1,31 @@
---
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,7 +36,57 @@ Ref: https://keepachangelog.com/en/1.0.0/
# Changelog # Changelog
## Unreleased ## [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 ### State Machine Breaking
@ -63,11 +113,30 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Bug Fixes ### 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) [#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) [#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) [#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. * (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. * (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 ## [v0.19.2] - 2022-08-29
@ -197,7 +266,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (evm) [tharsis#1088](https://github.com/evmos/ethermint/pull/1088) Fix ability to append log in tx post processing. * (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. * (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 * (ante) [tharsis#1111](https://github.com/evmos/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
* (types) [tharsis#1112](https://github.com/cosmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account. * (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 ## [v0.15.0] - 2022-05-09
@ -633,7 +702,7 @@ the Tracer type used to collect execution traces from the EVM transaction execut
### Improvements ### Improvements
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2) * (deps) [tharsis#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#610](https://github.com/cosmos/ethermint/pull/610) Update Go dependency to 1.15+. * (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. * (evm) [tharsis#603](https://github.com/cosmos/ethermint/pull/603) Add state transition params that enable or disable the EVM `Call` and `Create` operations.
* (deps) [tharsis#602](https://github.com/cosmos/ethermint/pull/602) Bump tendermint version to [v0.33.9](https://github.com/tendermint/tendermint/releases/tag/v0.33.9) * (deps) [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

@ -17,7 +17,7 @@ COPY . .
RUN make build RUN make build
# Final image # Final image
FROM alpine:3.16.2 FROM alpine:3.17.0
# Install ca-certificates # Install ca-certificates
RUN apk add --update ca-certificates jq RUN apk add --update ca-certificates jq

155
Makefile Executable file → Normal file
View File

@ -14,7 +14,6 @@ SIMAPP = ./app
HTTPS_GIT := https://github.com/cerc-io/laconicd.git HTTPS_GIT := https://github.com/cerc-io/laconicd.git
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git) PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
DOCKER := $(shell which docker) DOCKER := $(shell which docker)
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8
# RocksDB is a native dependency, so we don't assume the library is installed. # 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. # Instead, it must be explicitly enabled and we warn when it is not.
ENABLE_ROCKSDB ?= false ENABLE_ROCKSDB ?= false
@ -111,6 +110,12 @@ ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
BUILD_FLAGS += -trimpath BUILD_FLAGS += -trimpath
endif 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
# # The below include contains the tools and runsim targets. # # The below include contains the tools and runsim targets.
# include contrib/devtools/Makefile # include contrib/devtools/Makefile
@ -158,7 +163,7 @@ clean:
all: build all: build
build-all: tools build lint test build-all: tools build lint test vulncheck
.PHONY: distclean clean build-all .PHONY: distclean clean build-all
@ -167,7 +172,7 @@ build-all: tools build lint test
############################################################################### ###############################################################################
PACKAGE_NAME:=github.com/cerc-io/laconicd PACKAGE_NAME:=github.com/cerc-io/laconicd
GOLANG_CROSS_VERSION = v1.18 GOLANG_CROSS_VERSION = v1.19
GOPATH ?= '$(HOME)/go' GOPATH ?= '$(HOME)/go'
release-dry-run: release-dry-run:
docker run \ docker run \
@ -276,6 +281,10 @@ go.sum: go.mod
go mod verify go mod verify
go mod tidy go mod tidy
vulncheck: $(BUILDDIR)/
GOBIN=$(BUILDDIR) go install golang.org/x/vuln/cmd/govulncheck@latest
$(BUILDDIR)/govulncheck ./...
############################################################################### ###############################################################################
### Documentation ### ### Documentation ###
############################################################################### ###############################################################################
@ -330,9 +339,6 @@ test-import:
test-rpc: test-rpc:
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true" ./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"
run-integration-tests: run-integration-tests:
@nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh @nix-shell ./tests/integration_tests/shell.nix --run ./scripts/run-integration-tests.sh
@ -349,51 +355,6 @@ test-solidity:
.PHONY: run-tests test test-all test-import test-rpc test-contract test-solidity $(TEST_TARGETS) .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-random-genesis-fast:
@echo "Running random genesis simulation..."
@go test -mod=readonly $(SIMAPP) -run TestFullAppSimulation \
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
test-sim-import-export: runsim
@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-random-genesis-multi-seed: runsim
@echo "Running multi-seed custom genesis simulation..."
@$(BINDIR)/runsim -SimAppPkg=$(SIMAPP) -ExitOnFail 400 5 TestFullAppSimulation
test-sim-multi-seed-long: runsim
@echo "Running long multi-seed application simulation. This may take awhile!"
@$(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: benchmark:
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) @go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
@ -427,74 +388,62 @@ format-fix:
### Protobuf ### ### Protobuf ###
############################################################################### ###############################################################################
protoVer=v0.2 # ------
# 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) protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(protoVer) protoImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
containerProtoGenAny=$(PROJECT_NAME)-proto-gen-any-$(protoVer) # ------
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(protoVer) # NOTE: cosmos/proto-builder image is needed because clang-format is not installed
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(protoVer) # 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)
# ------
# 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-all: proto-format proto-lint proto-gen
proto-gen: proto-gen:
@echo "Generating Protobuf files" @echo "Generating Protobuf files"
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \ $(protoImage) sh ./scripts/protocgen.sh
sh ./scripts/protocgen.sh; fi
proto-swagger-gen:
@echo "Generating Protobuf Swagger" # TODO: Rethink API docs generation
@./scripts/proto-tools-installer.sh # proto-swagger-gen:
@./scripts/protoc-swagger-gen.sh # @echo "Generating Protobuf Swagger"
# $(protoImage) sh ./scripts/protoc-swagger-gen.sh
proto-format: proto-format:
@echo "Formatting Protobuf files" @echo "Formatting Protobuf files"
@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 \ $(protoCosmosImage) find ./ -name *.proto -exec clang-format -i {} \;
find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi
# NOTE: The linter configuration lives in .protolint.yaml
proto-lint: proto-lint:
@$(DOCKER_BUF) lint --error-format=json @echo "Linting Protobuf files"
$(protolintImage) lint ./proto
proto-check-breaking: proto-check-breaking:
@$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main @echo "Checking Protobuf files for breaking changes"
$(protoImage) buf breaking --against $(HTTPS_GIT)#branch=main
TM_URL = https://raw.githubusercontent.com/tendermint/tendermint/v0.34.12/proto/tendermint .PHONY: proto-all proto-gen proto-gen-any proto-format proto-lint proto-check-breaking
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 ### ### Localnet ###

View File

@ -7,7 +7,7 @@
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. 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.
**Note**: Requires [Go 1.18+](https://golang.org/dl/) **Note**: Requires [Go 1.19+](https://golang.org/dl/)
## Installation ## Installation

62
SECURITY.md Normal file
View File

@ -0,0 +1,62 @@
# Security
As part of our vulnerability disclosure policy, we operate a security vulnerability program through [Immunefi](https://immunefi.com/). This document serves as a complementary guideline for reporting vulnerabilities and how the disclosure process is managed. Please refer to the official Evmos [bug bounty program](https://immunefi.com/bounty/evmos/) for up-to-date information.
## Guidelines
We require that all researchers:
- Use the Evmos [bug bounty program](https://immunefi.com/bounty/evmos/) on Immunefi to disclose all vulnerabilities, and avoid posting vulnerability information in public places, including GitHub, Discord, Telegram, Twitter or other non-private channels.
- Make every effort to avoid privacy violations, degradation of user experience, disruption to production systems, and destruction of data.
- Keep any information about vulnerabilities that youve discovered confidential between yourself and the engineering team until the issue has been resolved and disclosed
- Avoid posting personally identifiable information, privately or publicly
If you follow these guidelines when reporting an issue to us, we commit to:
- Not pursue or support any legal action related to your research on this vulnerability
- Work with you to understand, resolve and ultimately disclose the issue in a timely fashion
## Disclosure Process
Evmos uses the following disclosure process:
1. Once a security report is received via the Immunefi Bug Bounty program, the team works to verify the issue and confirm its severity level using [CVSS](https://nvd.nist.gov/vuln-metrics/cvss) or [Immunefis Vulnerability Severity Classification System v2.2](https://immunefi.com/immunefi-vulnerability-severity-classification-system-v2-2/).
1. Two people from the affected project will review, replicate and acknowledge the report within 48-96 hours of the alert according to the table below:
| Security Level | Hours to First Response (ACK) from Escalation |
| -------------------- | --------------------------------------------- |
| Critical | 48 |
| High | 96 |
| Medium | 96 |
| Low or Informational | 96 |
| None | 96 |
2. If the report is not applicable or reproducible, the Security Lead (or Security Secondary) will revert to the reporter to request more info or close the report.
3. The report is confirmed by the Security Lead to the reporter.
2. The team determines the vulnerabilitys potential impact on Evmos.
1. Vulnerabilities with `Informational` and `Low` categorization will result in creating a public issue.
2. Vulnerabilities with `Medium` categorization will result in the creation of an internal ticket and patch of the code.
3. Vulnerabilities with `High` or `Critical` will result in the [creation of a new Security Advisory](https://docs.github.com/en/code-security/repository-security-advisories/creating-a-repository-security-advisory)
Once the vulnerability severity is defined, the following steps apply:
- For `High` and `Critical`:
1. Patches are prepared for supported releases of Evmos in a [temporary private fork](https://docs.github.com/en/code-security/repository-security-advisories/collaborating-in-a-temporary-private-fork-to-resolve-a-repository-security-vulnerability) of the repository.
2. Only relevant parties will be notified about an upcoming upgrade. These being validators, the core developer team, and users directly affected by the vulnerability.
3. 24 hours following this notification, relevant releases with the patch will be made public.
4. The nodes and validators update their Evmos and Ethermint dependencies to use these releases.
5. A week (or less) after the security vulnerability has been patched on Evmos, we will disclose that the mentioned release contained a security fix.
6. After an additional 2 weeks, we will publish a public announcement of the vulnerability. We also publish a security Advisory on GitHub and publish a [CVE](https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures)
- For `Informational` , `Low` and `Medium` severities:
1. `Medium` and `Low` severity bug reports are included in a public issue and will be incorporated in the current sprint and patched in the next release. `Informational` reports are additionally categorized as with low or medium priority and might not be included in the next release.
2. One week after the releases go out, we will publish a post with further details on the vulnerability as well as our response to it.
This process can take some time. Every effort will be made to handle the bug in as timely a manner as possible, however, it's important that we follow the process described above to ensure that disclosures are handled consistently and to keep Ethermint and its downstream dependent projects, including but not limited to Evmos, as secure as possible.
### Payment Process
The payment process will be executed according to Evmoss Immunefi Bug Bounty program Rules.
### Contact
The Evmos Security Team is constantly being monitored. If you need to reach out to the team directly, please reach out via email: [security@evmos.org](mailto:security@evmos.org)

View File

@ -6,8 +6,10 @@ import (
tmlog "github.com/tendermint/tendermint/libs/log" 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" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/types/tx/signing"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -44,14 +46,14 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
// handle as *evmtypes.MsgEthereumTx // handle as *evmtypes.MsgEthereumTx
anteHandler = newEthAnteHandler(options) anteHandler = newEthAnteHandler(options)
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx": case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation // Deprecated: Handle as normal Cosmos SDK tx, except signature is checked for Legacy EIP712 representation
anteHandler = newCosmosAnteHandlerEip712(options) anteHandler = NewLegacyCosmosAnteHandlerEip712(options)
case "/ethermint.types.v1.ExtensionOptionDynamicFeeTx": case "/ethermint.types.v1.ExtensionOptionDynamicFeeTx":
// cosmos-sdk tx with dynamic fee extension // cosmos-sdk tx with dynamic fee extension
anteHandler = newCosmosAnteHandler(options) anteHandler = newCosmosAnteHandler(options)
default: default:
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
sdkerrors.ErrUnknownExtensionOptions, errortypes.ErrUnknownExtensionOptions,
"rejecting tx with unsupported extension option: %s", typeURL, "rejecting tx with unsupported extension option: %s", typeURL,
) )
} }
@ -65,7 +67,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
case sdk.Tx: case sdk.Tx:
anteHandler = newCosmosAnteHandler(options) anteHandler = newCosmosAnteHandler(options)
default: default:
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid transaction type: %T", tx)
} }
return anteHandler(ctx, tx, sim) return anteHandler(ctx, tx, sim)
@ -74,7 +76,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
func Recover(logger tmlog.Logger, err *error) { func Recover(logger tmlog.Logger, err *error) {
if r := recover(); r != nil { if r := recover(); r != nil {
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r) *err = errorsmod.Wrapf(errortypes.ErrPanic, "%v", r)
if e, ok := r.(error); ok { if e, ok := r.(error); ok {
logger.Error( logger.Error(
@ -99,12 +101,48 @@ var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsu
func DefaultSigVerificationGasConsumer( func DefaultSigVerificationGasConsumer(
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params, meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
) error { ) error {
// support for ethereum ECDSA secp256k1 keys pubkey := sig.PubKey
_, ok := sig.PubKey.(*ethsecp256k1.PubKey) switch pubkey := pubkey.(type) {
if ok { case *ethsecp256k1.PubKey:
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1") meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
return nil 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 authante.DefaultSigVerificationGasConsumer(meter, sig, params) return nil
} }

View File

@ -2,24 +2,36 @@ package ante_test
import ( import (
"errors" "errors"
"fmt"
"math/big" "math/big"
"strings" "strings"
"time" "time"
sdkmath "cosmossdk.io/math" sdkmath "cosmossdk.io/math"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
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/types/tx/signing" "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/authz" "github.com/cosmos/cosmos-sdk/x/authz"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cerc-io/laconicd/app/ante"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/tests" "github.com/cerc-io/laconicd/tests"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
ethparams "github.com/ethereum/go-ethereum/params" ethparams "github.com/ethereum/go-ethereum/params"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
) )
func (suite AnteTestSuite) TestAnteHandler() { func (suite AnteTestSuite) TestAnteHandler() {
@ -337,6 +349,17 @@ func (suite AnteTestSuite) TestAnteHandler() {
return txBuilder.GetTx() return txBuilder.GetTx()
}, false, false, true, }, false, false, true,
}, },
{
"success- DeliverTx EIP712 create validator (with blank fields)",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712MsgCreateValidator2(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{ {
"success- DeliverTx EIP712 MsgSubmitProposal", "success- DeliverTx EIP712 MsgSubmitProposal",
func() sdk.Tx { func() sdk.Tx {
@ -364,7 +387,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt, from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt,
) )
suite.Require().NoError(err) suite.Require().NoError(err)
return suite.CreateTestEIP712CosmosTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx() return suite.CreateTestEIP712SingleMessageTxBuilder(from, privKey, "ethermint_9000-1", gas, gasAmount, msg).GetTx()
}, false, false, true, }, false, false, true,
}, },
@ -397,10 +420,65 @@ func (suite AnteTestSuite) TestAnteHandler() {
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)) coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount) amount := sdk.NewCoins(coinAmount)
gas := uint64(200000) gas := uint64(200000)
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount) txBuilder := suite.CreateTestEIP712MsgSubmitEvidence(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx() return txBuilder.GetTx()
}, false, false, true, }, false, false, true,
}, },
{
"success- DeliverTx EIP712 submit proposal v1",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712SubmitProposalV1(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{
"success- DeliverTx EIP712 MsgExec",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712MsgExec(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{
"success- DeliverTx EIP712 MsgVoteV1",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712MsgVoteV1(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{
"success- DeliverTx EIP712 Multiple MsgSend",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712MultipleMsgSend(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, true,
},
{
"fails - DeliverTx EIP712 Multiple Signers",
func() sdk.Tx {
from := acc.GetAddress()
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
amount := sdk.NewCoins(coinAmount)
gas := uint64(200000)
txBuilder := suite.CreateTestEIP712MultipleSignerMsgs(from, privKey, "ethermint_9000-1", gas, amount)
return txBuilder.GetTx()
}, false, false, false,
},
{ {
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID", "fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
func() sdk.Tx { func() sdk.Tx {
@ -496,6 +574,301 @@ func (suite AnteTestSuite) TestAnteHandler() {
return tx return tx
}, true, false, false, }, true, false, false,
}, },
{
"passes - Single-signer EIP-712",
func() sdk.Tx {
msg := banktypes.NewMsgSend(
sdk.AccAddress(privKey.PubKey().Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSingleSignedTx(
privKey,
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
msg,
"ethermint_9000-1",
2000000,
"EIP-712",
)
return txBuilder.GetTx()
}, false, false, true,
},
{
"passes - EIP-712 multi-key",
func() sdk.Tx {
numKeys := 5
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
msg,
"ethermint_9000-1",
2000000,
"EIP-712",
)
return txBuilder.GetTx()
}, false, false, true,
},
{
"passes - Mixed multi-key",
func() sdk.Tx {
numKeys := 5
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
msg,
"ethermint_9000-1",
2000000,
"mixed", // Combine EIP-712 and standard signatures
)
return txBuilder.GetTx()
}, false, false, true,
},
{
"passes - Mixed multi-key with MsgVote",
func() sdk.Tx {
numKeys := 5
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := govtypes.NewMsgVote(
sdk.AccAddress(pk.Address()),
1,
govtypes.OptionYes,
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
msg,
"ethermint_9000-1",
2000000,
"mixed", // Combine EIP-712 and standard signatures
)
return txBuilder.GetTx()
}, false, false, true,
},
{
"Fails - Multi-Key with incorrect Chain ID",
func() sdk.Tx {
numKeys := 5
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
msg,
"ethermint_9005-1",
2000000,
"mixed",
)
return txBuilder.GetTx()
}, false, false, false,
},
{
"Fails - Multi-Key with incorrect sign mode",
func() sdk.Tx {
numKeys := 5
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_DIRECT,
msg,
"ethermint_9000-1",
2000000,
"mixed",
)
return txBuilder.GetTx()
}, false, false, false,
},
{
"Fails - Multi-Key with too little gas",
func() sdk.Tx {
numKeys := 5
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_DIRECT,
msg,
"ethermint_9000-1",
2000,
"mixed", // Combine EIP-712 and standard signatures
)
return txBuilder.GetTx()
}, false, false, false,
},
{
"Fails - Multi-Key with different payload than one signed",
func() sdk.Tx {
numKeys := 1
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_DIRECT,
msg,
"ethermint_9000-1",
2000,
"EIP-712",
)
msg.Amount[0].Amount = sdk.NewInt(5)
txBuilder.SetMsgs(msg)
return txBuilder.GetTx()
}, false, false, false,
},
{
"Fails - Multi-Key with messages added after signing",
func() sdk.Tx {
numKeys := 1
privKeys, pubKeys := suite.GenerateMultipleKeys(numKeys)
pk := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
msg := banktypes.NewMsgSend(
sdk.AccAddress(pk.Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSignedMultisigTx(
privKeys,
signing.SignMode_SIGN_MODE_DIRECT,
msg,
"ethermint_9000-1",
2000,
"EIP-712",
)
// Duplicate
txBuilder.SetMsgs(msg, msg)
return txBuilder.GetTx()
}, false, false, false,
},
{
"Fails - Single-Signer EIP-712 with messages added after signing",
func() sdk.Tx {
msg := banktypes.NewMsgSend(
sdk.AccAddress(privKey.PubKey().Address()),
addr[:],
sdk.NewCoins(
sdk.NewCoin(
"photon",
sdk.NewInt(1),
),
),
)
txBuilder := suite.CreateTestSingleSignedTx(
privKey,
signing.SignMode_SIGN_MODE_DIRECT,
msg,
"ethermint_9000-1",
2000,
"EIP-712",
)
txBuilder.SetMsgs(msg, msg)
return txBuilder.GetTx()
}, false, false, false,
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -914,3 +1287,93 @@ func (suite AnteTestSuite) TestAnteHandlerWithParams() {
} }
suite.evmParamsOption = nil suite.evmParamsOption = nil
} }
func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() {
params := authtypes.DefaultParams()
msg := []byte{1, 2, 3, 4}
cdc := simapp.MakeTestEncodingConfig().Amino
p := authtypes.DefaultParams()
skR1, _ := secp256r1.GenPrivKey()
pkSet1, sigSet1, err := generatePubKeysAndSignatures(5, msg, false)
suite.Require().NoError(err)
multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
multisignature1 := multisig.NewMultisig(len(pkSet1))
expectedCost1 := expectedGasCostByKeys(pkSet1)
for i := 0; i < len(pkSet1); i++ {
stdSig := legacytx.StdSignature{PubKey: pkSet1[i], Signature: sigSet1[i]}
sigV2, err := legacytx.StdSignatureToSignatureV2(cdc, stdSig)
suite.Require().NoError(err)
err = multisig.AddSignatureV2(multisignature1, sigV2, pkSet1)
suite.Require().NoError(err)
}
type args struct {
meter sdk.GasMeter
sig signing.SignatureData
pubkey cryptotypes.PubKey
params authtypes.Params
}
tests := []struct {
name string
args args
gasConsumed uint64
shouldErr bool
}{
{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true},
{"PubKeyEthSecp256k1", args{sdk.NewInfiniteGasMeter(), nil, pkSet1[0], params}, 21_000, false},
{"PubKeySecp256r1", args{sdk.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false},
{"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false},
{"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
}
for _, tt := range tests {
sigV2 := signing.SignatureV2{
PubKey: tt.args.pubkey,
Data: tt.args.sig,
Sequence: 0, // Arbitrary account sequence
}
err := ante.DefaultSigVerificationGasConsumer(tt.args.meter, sigV2, tt.args.params)
if tt.shouldErr {
suite.Require().NotNil(err)
} else {
suite.Require().Nil(err)
suite.Require().Equal(tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed()))
}
}
}
func generatePubKeysAndSignatures(n int, msg []byte, _ bool) (pubkeys []cryptotypes.PubKey, signatures [][]byte, err error) {
pubkeys = make([]cryptotypes.PubKey, n)
signatures = make([][]byte, n)
for i := 0; i < n; i++ {
privkey, err := ethsecp256k1.GenerateKey()
if err != nil {
return nil, nil, err
}
pubkeys[i] = privkey.PubKey()
signatures[i], _ = privkey.Sign(msg)
}
return
}
func expectedGasCostByKeys(pubkeys []cryptotypes.PubKey) uint64 {
cost := uint64(0)
for _, pubkey := range pubkeys {
pubkeyType := strings.ToLower(fmt.Sprintf("%T", pubkey))
switch {
case strings.Contains(pubkeyType, "ed25519"):
cost += authtypes.DefaultParams().SigVerifyCostED25519
case strings.Contains(pubkeyType, "ethsecp256k1"):
cost += 21_000
case strings.Contains(pubkeyType, "secp256k1"):
cost += authtypes.DefaultParams().SigVerifyCostSecp256k1
default:
panic("unexpected key type")
}
}
return cost
}

View File

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

View File

@ -1,19 +1,32 @@
// 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 package ante
import ( import (
"errors"
"math" "math"
"math/big" "math/big"
"strconv"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math" sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
evmkeeper "github.com/cerc-io/laconicd/x/evm/keeper" "github.com/cerc-io/laconicd/x/evm/keeper"
"github.com/cerc-io/laconicd/x/evm/statedb" "github.com/cerc-io/laconicd/x/evm/statedb"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
@ -21,61 +34,6 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types" 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()
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))
}
ethTx := msgEthTx.AsTransaction()
if !params.AllowUnprotectedTxs && !ethTx.Protected() {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrNotSupported,
"rejected unprotected Ethereum txs. Please EIP155 sign your transaction to protect it against replay-attacks")
}
sender, err := signer.Sender(ethTx)
if err != nil {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrorInvalidSigner,
"couldn't retrieve sender address 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)
}
// EthAccountVerificationDecorator validates an account balance checks // EthAccountVerificationDecorator validates an account balance checks
type EthAccountVerificationDecorator struct { type EthAccountVerificationDecorator struct {
ak evmtypes.AccountKeeper ak evmtypes.AccountKeeper
@ -109,35 +67,35 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
for i, msg := range tx.GetMsgs() { for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
} }
txData, err := evmtypes.UnpackTxData(msgEthTx.Data) txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i) return ctx, errorsmod.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 // sender address should be in the tx cache from the previous AnteHandle call
from := msgEthTx.GetFrom() from := msgEthTx.GetFrom()
if from.Empty() { if from.Empty() {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty") return ctx, errorsmod.Wrap(errortypes.ErrInvalidAddress, "from address cannot be empty")
} }
// check whether the sender address is EOA // check whether the sender address is EOA
fromAddr := common.BytesToAddress(from) fromAddr := common.BytesToAddress(from)
acct := avd.evmKeeper.GetAccount(ctx, fromAddr) //nolint: all acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
if acct == nil { if acct == nil {
acc := avd.ak.NewAccountWithAddress(ctx, from) acc := avd.ak.NewAccountWithAddress(ctx, from)
avd.ak.SetAccount(ctx, acc) avd.ak.SetAccount(ctx, acc)
acct = statedb.NewEmptyAccount() acct = statedb.NewEmptyAccount()
} else if acct.IsContract() { } else if acct.IsContract() {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType,
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash) "the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
} }
if err := evmkeeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil { if err := keeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
return ctx, sdkerrors.Wrap(err, "failed to check sender balance") return ctx, errorsmod.Wrap(err, "failed to check sender balance")
} }
} }
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
@ -165,7 +123,7 @@ func NewEthGasConsumeDecorator(
// (during CheckTx only) and that the sender has enough balance to pay for the gas cost. // (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 // 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 inccured by additional bytes // transaction is executed. The gas is a constant value plus any cost incurred by additional bytes
// of data supplied with the transaction. // of data supplied with the transaction.
// //
// This AnteHandler decorator will fail if: // This AnteHandler decorator will fail if:
@ -175,31 +133,43 @@ func NewEthGasConsumeDecorator(
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price) // - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
// - transaction or block gas meter runs out of gas // - transaction or block gas meter runs out of gas
// - sets the gas meter limit // - 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) { func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
params := egcd.evmKeeper.GetParams(ctx) 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)
}
ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID()) chainCfg := egcd.evmKeeper.GetChainConfig(ctx)
ethCfg := chainCfg.EthereumConfig(egcd.evmKeeper.ChainID())
blockHeight := big.NewInt(ctx.BlockHeight()) blockHeight := big.NewInt(ctx.BlockHeight())
homestead := ethCfg.IsHomestead(blockHeight) homestead := ethCfg.IsHomestead(blockHeight)
istanbul := ethCfg.IsIstanbul(blockHeight) istanbul := ethCfg.IsIstanbul(blockHeight)
london := ethCfg.IsLondon(blockHeight)
evmDenom := params.EvmDenom
gasWanted := uint64(0)
var events sdk.Events var events sdk.Events
// Use the lowest priority of all the messages as the final one. // Use the lowest priority of all the messages as the final one.
minPriority := int64(math.MaxInt64) minPriority := int64(math.MaxInt64)
baseFee := egcd.evmKeeper.GetBaseFee(ctx, ethCfg)
for _, msg := range tx.GetMsgs() { for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
} }
txData, err := evmtypes.UnpackTxData(msgEthTx.Data) txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data") return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
} }
if ctx.IsCheckTx() && egcd.maxGasWanted != 0 { if ctx.IsCheckTx() && egcd.maxGasWanted != 0 {
@ -213,45 +183,59 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
gasWanted += txData.GetGas() gasWanted += txData.GetGas()
} }
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance( evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
ctx,
*msgEthTx, fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, homestead, istanbul, ctx.IsCheckTx())
txData,
evmDenom,
homestead,
istanbul,
london,
)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance") return ctx, errorsmod.Wrapf(err, "failed to verify the fees")
} }
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String()))) 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()),
),
)
priority := evmtypes.GetTxPriority(txData, baseFee)
if priority < minPriority { if priority < minPriority {
minPriority = priority minPriority = priority
} }
} }
// TODO: change to typed events
ctx.EventManager().EmitEvents(events) ctx.EventManager().EmitEvents(events)
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
blockGasLimit := ethermint.BlockGasLimit(ctx) blockGasLimit := ethermint.BlockGasLimit(ctx)
// NOTE: safety check // return error if the tx gas is greater than the block limit (max gas)
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 // NOTE: it's important here to use the gas wanted instead of the gas consumed
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp // from the tx gas pool. The later only has the value so far since the
gasPool := sdk.NewGasMeter(blockGasLimit) // EthSetupContextDecorator so it will never exceed the block gas limit.
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check") if gasWanted > blockGasLimit {
return ctx, errorsmod.Wrapf(
errortypes.ErrOutOfGas,
"tx gas (%d) exceeds block gas limit (%d)",
gasWanted,
blockGasLimit,
)
} }
// Set ctx.GasMeter with a limit of GasWanted (gasLimit) // Set tx GasMeter with a limit of GasWanted (i.e gas limit from the Ethereum tx).
gasConsumed := ctx.GasMeter().GasConsumed() // The gas consumed will be then reset to the gas used by the state transition
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted)) // in the EVM.
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
newCtx := ctx.WithPriority(minPriority) // 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)
// we know that we have enough gas on the pool to cover the intrinsic gas // we know that we have enough gas on the pool to cover the intrinsic gas
return next(newCtx, tx, simulate) return next(newCtx, tx, simulate)
@ -280,19 +264,35 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
for _, msg := range tx.GetMsgs() { for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
} }
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg) baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
coreMsg, err := msgEthTx.AsMessage(signer, baseFee) coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
err, err,
"failed to create an ethereum core.Message from signer %T", signer, "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 // NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
cfg := &evmtypes.EVMConfig{ cfg := &evmtypes.EVMConfig{
ChainConfig: ethCfg, ChainConfig: ethCfg,
@ -300,35 +300,20 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
CoinBase: common.Address{}, CoinBase: common.Address{},
BaseFee: baseFee, BaseFee: baseFee,
} }
stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))) stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB) evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB)
// check that caller has enough balance to cover asset transfer for **topmost** call // 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 // NOTE: here the gas consumed is from the context with the infinite gas meter
if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) { if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
sdkerrors.ErrInsufficientFunds, errortypes.ErrInsufficientFunds,
"failed to transfer %s from address %s using the EVM block context transfer function", "failed to transfer %s from address %s using the EVM block context transfer function",
coreMsg.Value(), coreMsg.Value(),
coreMsg.From(), 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) return next(ctx, tx, simulate)
@ -353,19 +338,19 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
for _, msg := range tx.GetMsgs() { for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
} }
txData, err := evmtypes.UnpackTxData(msgEthTx.Data) txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data") return ctx, errorsmod.Wrap(err, "failed to unpack tx data")
} }
// increase sequence of sender // increase sequence of sender
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom()) acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
if acc == nil { if acc == nil {
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
sdkerrors.ErrUnknownAddress, errortypes.ErrUnknownAddress,
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()), "account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
) )
} }
@ -374,14 +359,14 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
// we merged the nonce verification to nonce increment, so when tx includes multiple messages // we merged the nonce verification to nonce increment, so when tx includes multiple messages
// with same sender, they'll be accepted. // with same sender, they'll be accepted.
if txData.GetNonce() != nonce { if txData.GetNonce() != nonce {
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
sdkerrors.ErrInvalidSequence, errortypes.ErrInvalidSequence,
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce, "invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
) )
} }
if err := acc.SetSequence(nonce + 1); err != nil { if err := acc.SetSequence(nonce + 1); err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1) return ctx, errorsmod.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
} }
issd.ak.SetAccount(ctx, acc) issd.ak.SetAccount(ctx, acc)
@ -389,216 +374,3 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
return next(ctx, tx, simulate) 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
wrapperTx, ok := tx.(protoTxProvider)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid tx type %T, didn't implement interface protoTxProvider", tx)
}
protoTx := wrapperTx.GetProtoTx()
body := protoTx.Body
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
}
if len(body.ExtensionOptions) != 1 {
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
}
txFee := sdk.Coins{}
txGasLimit := uint64(0)
params := vbd.evmKeeper.GetParams(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)
for _, msg := range protoTx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
// Validate `From` field
if msgEthTx.From != "" {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid From %s, expect empty string", msgEthTx.From)
}
txGasLimit += msgEthTx.GetGas()
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
}
// return error if contract creation or call are disabled through governance
if !params.EnableCreate && txData.GetTo() == nil {
return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
} else if !params.EnableCall && txData.GetTo() != nil {
return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
}
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}
txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdkmath.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.GetBaseFee(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)
}
// EthEmitEventDecorator emit events in ante handler in case of tx execution failed (out of block gas limit).
type EthEmitEventDecorator struct {
evmKeeper EVMKeeper
}
// NewEthEmitEventDecorator creates a new EthEmitEventDecorator
func NewEthEmitEventDecorator(evmKeeper EVMKeeper) EthEmitEventDecorator {
return EthEmitEventDecorator{evmKeeper}
}
// AnteHandle emits some basic events for the eth messages
func (eeed EthEmitEventDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
// After eth tx passed ante handler, the fee is deducted and nonce increased, it shouldn't be ignored by json-rpc,
// we need to emit some basic events at the very end of ante handler to be indexed by tendermint.
txIndex := eeed.evmKeeper.GetTxIndexTransient(ctx)
for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}
// emit ethereum tx hash as event, should be indexed by tm tx indexer for query purpose.
// it's emitted in ante handler so we can query failed transaction (out of block gas limit).
ctx.EventManager().EmitEvent(sdk.NewEvent(
evmtypes.EventTypeEthereumTx,
sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msgEthTx.Hash),
sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(txIndex+uint64(i), 10)),
))
}
return next(ctx, tx, simulate)
}

View File

@ -9,65 +9,13 @@ import (
"github.com/cerc-io/laconicd/app/ante" "github.com/cerc-io/laconicd/app/ante"
"github.com/cerc-io/laconicd/server/config" "github.com/cerc-io/laconicd/server/config"
"github.com/cerc-io/laconicd/tests" "github.com/cerc-io/laconicd/tests"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/evm/statedb" "github.com/cerc-io/laconicd/x/evm/statedb"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
ethtypes "github.com/ethereum/go-ethereum/core/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
}
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() { func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
dec := ante.NewEthAccountVerificationDecorator( dec := ante.NewEthAccountVerificationDecorator(
suite.app.AccountKeeper, suite.app.EvmKeeper, suite.app.AccountKeeper, suite.app.EvmKeeper,
@ -233,6 +181,9 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
tx2.From = addr.Hex() tx2.From = addr.Hex()
tx2Priority := int64(1) 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, dynamicFeeTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit,
nil, // gasPrice nil, // gasPrice
new(big.Int).Add(baseFee, big.NewInt(evmtypes.DefaultPriorityReduction.Int64()*2)), // gasFeeCap new(big.Int).Add(baseFee, big.NewInt(evmtypes.DefaultPriorityReduction.Int64()*2)), // gasFeeCap
@ -269,6 +220,14 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
false, false, false, false,
0, 0,
}, },
{
"gas limit above block gas limit",
tx3,
math.MaxUint64,
func() {},
false, false,
0,
},
{ {
"not enough balance for fees", "not enough balance for fees",
tx2, tx2,
@ -320,6 +279,17 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
true, false, true, false,
dynamicFeeTxPriority, 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,
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -521,33 +491,3 @@ 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

@ -4,12 +4,13 @@ import (
"fmt" "fmt"
"math" "math"
errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math" sdkmath "cosmossdk.io/math"
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/evm/types" "github.com/cerc-io/laconicd/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
) )
@ -64,7 +65,7 @@ func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker {
baseFeeInt := sdkmath.NewIntFromBigInt(baseFee) baseFeeInt := sdkmath.NewIntFromBigInt(baseFee)
if feeCap.LT(baseFeeInt) { if feeCap.LT(baseFeeInt) {
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient gas prices; got: %s required: %s", feeCap, 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. // calculate the effective gas price using the EIP-1559 logic.
@ -112,7 +113,7 @@ func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.FeeTx) (sdk.Coi
} }
if !feeCoins.IsAnyGTE(requiredFees) { if !feeCoins.IsAnyGTE(requiredFees) {
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees) return nil, 0, errorsmod.Wrapf(errortypes.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees)
} }
} }

View File

@ -3,8 +3,8 @@ package ante
import ( import (
"math/big" "math/big"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
) )
// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store // GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store
@ -27,8 +27,8 @@ func NewGasWantedDecorator(
} }
func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
params := gwd.evmKeeper.GetParams(ctx) chainCfg := gwd.evmKeeper.GetChainConfig(ctx)
ethCfg := params.ChainConfig.EthereumConfig(gwd.evmKeeper.ChainID()) ethCfg := chainCfg.EthereumConfig(gwd.evmKeeper.ChainID())
blockHeight := big.NewInt(ctx.BlockHeight()) blockHeight := big.NewInt(ctx.BlockHeight())
isLondon := ethCfg.IsLondon(blockHeight) isLondon := ethCfg.IsLondon(blockHeight)
@ -39,12 +39,12 @@ func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
} }
gasWanted := feeTx.GetGas() gasWanted := feeTx.GetGas()
feeMktParams := gwd.feeMarketKeeper.GetParams(ctx) isBaseFeeEnabled := gwd.feeMarketKeeper.GetBaseFeeEnabled(ctx)
// Add total gasWanted to cumulative in block transientStore in FeeMarket module // Add total gasWanted to cumulative in block transientStore in FeeMarket module
if feeMktParams.IsBaseFeeEnabled(ctx.BlockHeight()) { if isBaseFeeEnabled {
if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil { if _, err := gwd.feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to add gas wanted to transient store") return ctx, errorsmod.Wrapf(err, "failed to add gas wanted to transient store")
} }
} }

View File

@ -3,8 +3,9 @@ package ante
import ( import (
"math/big" "math/big"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -20,14 +21,50 @@ type MinGasPriceDecorator struct {
evmKeeper EVMKeeper 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 { func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek} 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) { 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) feeTx, ok := tx.(sdk.FeeTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected sdk.FeeTx", tx)
} }
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
@ -37,10 +74,10 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
evmParams := mpd.evmKeeper.GetParams(ctx) evmDenom := mpd.evmKeeper.GetEVMDenom(ctx)
minGasPrices := sdk.DecCoins{ minGasPrices := sdk.DecCoins{
{ {
Denom: evmParams.EvmDenom, Denom: evmDenom,
Amount: minGasPrice, Amount: minGasPrice,
}, },
} }
@ -62,7 +99,7 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
} }
if !feeCoins.IsAnyGTE(requiredFees) { if !feeCoins.IsAnyGTE(requiredFees) {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, return ctx, errorsmod.Wrapf(errortypes.ErrInsufficientFee,
"provided fee < minimum global fee (%s < %s). Please increase the gas price.", "provided fee < minimum global fee (%s < %s). Please increase the gas price.",
feeCoins, feeCoins,
requiredFees) requiredFees)
@ -71,20 +108,8 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large // AnteHandle ensures that the that the effective fee from the transaction is greater than the
// as the MinGasPrices param. If fee is too low, decorator returns error and tx // minimum global fee, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument).
// is rejected. This applies to both CheckTx and DeliverTx and regardless
// if London hard fork or fee market params (EIP-1559) are enabled.
// If fee is high enough, then call next AnteHandler
type EthMinGasPriceDecorator struct {
feesKeeper FeeMarketKeeper
evmKeeper EVMKeeper
}
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
}
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 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 minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
@ -93,15 +118,15 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
paramsEvm := empd.evmKeeper.GetParams(ctx) chainCfg := empd.evmKeeper.GetChainConfig(ctx)
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID()) ethCfg := chainCfg.EthereumConfig(empd.evmKeeper.ChainID())
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg) baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
for _, msg := range tx.GetMsgs() { for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok { if !ok {
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
sdkerrors.ErrUnknownRequest, errortypes.ErrUnknownRequest,
"invalid message type %T, expected %T", "invalid message type %T, expected %T",
msg, (*evmtypes.MsgEthereumTx)(nil), msg, (*evmtypes.MsgEthereumTx)(nil),
) )
@ -120,7 +145,7 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
txData, err := evmtypes.UnpackTxData(ethMsg.Data) txData, err := evmtypes.UnpackTxData(ethMsg.Data)
if err != nil { if err != nil {
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash) return ctx, errorsmod.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
} }
if txData.TxType() != ethtypes.LegacyTxType { if txData.TxType() != ethtypes.LegacyTxType {
@ -133,8 +158,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
fee := sdk.NewDecFromBigInt(feeAmt) fee := sdk.NewDecFromBigInt(feeAmt)
if fee.LT(requiredFee) { if fee.LT(requiredFee) {
return ctx, sdkerrors.Wrapf( return ctx, errorsmod.Wrapf(
sdkerrors.ErrInsufficientFee, 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 "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(), fee.TruncateInt().Int64(), requiredFee.TruncateInt().Int64(),
) )
@ -143,3 +168,44 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
return next(ctx, tx, simulate) 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

@ -42,7 +42,7 @@ func (s AnteTestSuite) TestMinGasPriceDecorator() {
return &invalidTx{} return &invalidTx{}
}, },
false, false,
"must be a FeeTx", "invalid transaction type",
false, false,
}, },
{ {
@ -345,3 +345,7 @@ func (s AnteTestSuite) TestEthMinGasPriceDecorator() {
} }
} }
} }
func (suite AnteTestSuite) TestEthMempoolFeeDecorator() {
// TODO: add test
}

View File

@ -1,8 +1,9 @@
package ante package ante
import ( import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/ante"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
@ -20,7 +21,7 @@ type HandlerOptions struct {
AccountKeeper evmtypes.AccountKeeper AccountKeeper evmtypes.AccountKeeper
BankKeeper evmtypes.BankKeeper BankKeeper evmtypes.BankKeeper
IBCKeeper *ibckeeper.Keeper IBCKeeper *ibckeeper.Keeper
FeeMarketKeeper evmtypes.FeeMarketKeeper FeeMarketKeeper FeeMarketKeeper
EvmKeeper EVMKeeper EvmKeeper EVMKeeper
FeegrantKeeper ante.FeegrantKeeper FeegrantKeeper ante.FeegrantKeeper
SignModeHandler authsigning.SignModeHandler SignModeHandler authsigning.SignModeHandler
@ -31,20 +32,20 @@ type HandlerOptions struct {
} }
func (options HandlerOptions) validate() error { func (options HandlerOptions) validate() error {
if options.AccountKeeper == evmtypes.AccountKeeper(nil) { if options.AccountKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler") return errorsmod.Wrap(errortypes.ErrLogic, "account keeper is required for AnteHandler")
} }
if options.BankKeeper == evmtypes.BankKeeper(nil) { if options.BankKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler") return errorsmod.Wrap(errortypes.ErrLogic, "bank keeper is required for AnteHandler")
} }
if options.SignModeHandler == authsigning.SignModeHandler(nil) { if options.SignModeHandler == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder") return errorsmod.Wrap(errortypes.ErrLogic, "sign mode handler is required for ante builder")
} }
if options.FeeMarketKeeper == evmtypes.FeeMarketKeeper(nil) { if options.FeeMarketKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler") return errorsmod.Wrap(errortypes.ErrLogic, "fee market keeper is required for AnteHandler")
} }
if options.EvmKeeper == EVMKeeper(nil) { if options.EvmKeeper == nil {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler") return errorsmod.Wrap(errortypes.ErrLogic, "evm keeper is required for AnteHandler")
} }
return nil return nil
} }
@ -70,9 +71,9 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
RejectMessagesDecorator{}, // reject MsgEthereumTxs RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(), ante.NewSetUpContextDecorator(),
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker), ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateBasicDecorator(), ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(), ante.NewTxTimeoutHeightDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
ante.NewValidateMemoDecorator(options.AccountKeeper), ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper), ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker), ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
@ -86,27 +87,3 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper), NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
) )
} }
func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
return sdk.ChainAnteDecorators(
RejectMessagesDecorator{}, // reject MsgEthereumTxs
ante.NewSetUpContextDecorator(),
// NOTE: extensions option decorator removed
// ante.NewRejectExtensionOptionsDecorator(),
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
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.NewRedundantRelayDecorator(options.IBCKeeper),
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
)
}

View File

@ -28,12 +28,15 @@ type EVMKeeper interface {
DynamicFeeEVMKeeper DynamicFeeEVMKeeper
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM
DeductTxCostsFromUserBalance( DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
) (fees sdk.Coins, priority int64, err error)
GetBalance(ctx sdk.Context, addr common.Address) *big.Int GetBalance(ctx sdk.Context, addr common.Address) *big.Int
ResetTransientGasUsed(ctx sdk.Context) ResetTransientGasUsed(ctx sdk.Context)
GetTxIndexTransient(ctx sdk.Context) uint64 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 { type protoTxProvider interface {
@ -44,4 +47,5 @@ type protoTxProvider interface {
type FeeMarketKeeper interface { type FeeMarketKeeper interface {
GetParams(ctx sdk.Context) (params feemarkettypes.Params) GetParams(ctx sdk.Context) (params feemarkettypes.Params)
AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error)
GetBaseFeeEnabled(ctx sdk.Context) bool
} }

View File

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

189
app/ante/setup.go Normal file
View File

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

42
app/ante/setup_test.go Normal file
View File

@ -0,0 +1,42 @@
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

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

65
app/ante/sigverify.go Normal file
View File

@ -0,0 +1,65 @@
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

@ -15,26 +15,32 @@ import (
"github.com/cerc-io/laconicd/types" "github.com/cerc-io/laconicd/types"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
types2 "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
types3 "github.com/cosmos/cosmos-sdk/x/staking/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
cryptocodec "github.com/cerc-io/laconicd/crypto/codec" cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" 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" 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/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx" txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing" "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" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authz "github.com/cosmos/cosmos-sdk/x/authz"
"github.com/cerc-io/laconicd/app" "github.com/cerc-io/laconicd/app"
ante "github.com/cerc-io/laconicd/app/ante" ante "github.com/cerc-io/laconicd/app/ante"
@ -46,7 +52,8 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types" evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
"github.com/cosmos/cosmos-sdk/x/feegrant" "github.com/cosmos/cosmos-sdk/x/feegrant"
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
) )
@ -92,6 +99,8 @@ func (suite *AnteTestSuite) SetupTest() {
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
evmGenesis.Params.ChainConfig.ShanghaiBlock = &maxInt
evmGenesis.Params.ChainConfig.CancunBlock = &maxInt
} }
if suite.evmParamsOption != nil { if suite.evmParamsOption != nil {
suite.evmParamsOption(&evmGenesis.Params) suite.evmParamsOption(&evmGenesis.Params)
@ -111,6 +120,7 @@ func (suite *AnteTestSuite) SetupTest() {
encodingConfig := encoding.MakeConfig(app.ModuleBasics) encodingConfig := encoding.MakeConfig(app.ModuleBasics)
// We're using TestMsg amino encoding in some tests, so register it here. // We're using TestMsg amino encoding in some tests, so register it here.
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil) encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
eip712.SetEncodingConfig(encodingConfig)
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig) suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
@ -263,41 +273,57 @@ func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdkmath.Int, deno
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder { func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build MsgSend // Build MsgSend
recipient := sdk.AccAddress(common.Address{}.Bytes()) recipient := sdk.AccAddress(common.Address{}.Bytes())
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1)))) msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend) return suite.CreateTestEIP712SingleMessageTxBuilder(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 { func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build MsgSend // Build MsgSend
valEthAddr := tests.GenerateAddress() valEthAddr := tests.GenerateAddress()
valAddr := sdk.ValAddress(valEthAddr.Bytes()) valAddr := sdk.ValAddress(valEthAddr.Bytes())
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20))) msgSend := stakingtypes.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend) 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 { func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
// Build MsgCreateValidator // Build MsgCreateValidator
valAddr := sdk.ValAddress(from.Bytes()) valAddr := sdk.ValAddress(from.Bytes())
privEd := ed25519.GenPrivKey() privEd := ed25519.GenPrivKey()
msgCreate, err := types3.NewMsgCreateValidator( msgCreate, err := stakingtypes.NewMsgCreateValidator(
valAddr, valAddr,
privEd.PubKey(), privEd.PubKey(),
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)), sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
// TODO: can this values be empty strings? stakingtypes.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
types3.NewDescription("moniker", "indentity", "website", "security_contract", "details"), stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
types3.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(), sdk.OneInt(),
) )
suite.Require().NoError(err) suite.Require().NoError(err)
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgCreate) 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 { func (suite *AnteTestSuite) CreateTestEIP712SubmitProposal(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, deposit sdk.Coins) client.TxBuilder {
proposal, ok := types5.ContentFromProposalType("My proposal", "My description", types5.ProposalTypeText) proposal, ok := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText)
suite.Require().True(ok) suite.Require().True(ok)
msgSubmit, err := types5.NewMsgSubmitProposal(proposal, deposit, from) msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from)
suite.Require().NoError(err) suite.Require().NoError(err)
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSubmit) 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 { func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
@ -311,18 +337,18 @@ func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress,
grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes()) grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes())
msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress()) msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress())
suite.Require().NoError(err) suite.Require().NoError(err)
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant) 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 { func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
valAddr := sdk.ValAddress(from.Bytes()) valAddr := sdk.ValAddress(from.Bytes())
msgEdit := types3.NewMsgEditValidator( msgEdit := stakingtypes.NewMsgEditValidator(
valAddr, valAddr,
types3.NewDescription("moniker", "identity", "website", "security_contract", "details"), stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"),
nil, nil,
nil, nil,
) )
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEdit) 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 { func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
@ -335,7 +361,72 @@ func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddres
}) })
suite.Require().NoError(err) suite.Require().NoError(err)
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence) 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. // StdSignBytes returns the bytes to sign for a transaction.
@ -376,8 +467,14 @@ func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequenc
return sdk.MustSortJSON(bz) return sdk.MustSortJSON(bz)
} }
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder( func (suite *AnteTestSuite) CreateTestEIP712SingleMessageTxBuilder(
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg, 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})
}
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg,
) client.TxBuilder { ) client.TxBuilder {
var err error var err error
@ -398,13 +495,13 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
fee := legacytx.NewStdFee(gas, gasAmount) fee := legacytx.NewStdFee(gas, gasAmount)
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber() accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil) data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, msgs, "", nil)
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{ typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msgs[0], data, &eip712.FeeDelegationOptions{
FeePayer: from, FeePayer: from,
}) })
suite.Require().NoError(err) suite.Require().NoError(err)
sigHash, err := eip712.ComputeTypedDataHash(typedData) sigHash, _, err := apitypes.TypedDataAndHash(typedData)
suite.Require().NoError(err) suite.Require().NoError(err)
// Sign typedData // Sign typedData
@ -442,12 +539,189 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
err = builder.SetSignatures(sigsV2) err = builder.SetSignatures(sigsV2)
suite.Require().NoError(err) suite.Require().NoError(err)
err = builder.SetMsgs(msg) err = builder.SetMsgs(msgs...)
suite.Require().NoError(err) suite.Require().NoError(err)
return builder 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) { func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
return ctx, nil return ctx, nil
} }

View File

@ -2,6 +2,7 @@ package app
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"net/http" "net/http"
"os" "os"
@ -18,6 +19,7 @@ import (
"github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client" "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/client/grpc/tmservice"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/codec/types"
@ -26,6 +28,7 @@ import (
servertypes "github.com/cosmos/cosmos-sdk/server/types" servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp"
simappparams "github.com/cosmos/cosmos-sdk/simapp/params" 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/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/module"
@ -101,6 +104,7 @@ import (
_ "github.com/cerc-io/laconicd/client/docs/statik" _ "github.com/cerc-io/laconicd/client/docs/statik"
"github.com/cerc-io/laconicd/app/ante" "github.com/cerc-io/laconicd/app/ante"
"github.com/cerc-io/laconicd/ethereum/eip712"
srvflags "github.com/cerc-io/laconicd/server/flags" srvflags "github.com/cerc-io/laconicd/server/flags"
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/evm" "github.com/cerc-io/laconicd/x/evm"
@ -184,7 +188,7 @@ var (
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner}, govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, 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 evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, //nolint:lll // used for secure addition and subtraction of balance using module account
auctiontypes.ModuleName: nil, auctiontypes.ModuleName: nil,
auctiontypes.AuctionBurnModuleAccountName: nil, auctiontypes.AuctionBurnModuleAccountName: nil,
registrytypes.ModuleName: nil, registrytypes.ModuleName: nil,
@ -199,8 +203,6 @@ var (
} }
) )
var _ simapp.App = (*EthermintApp)(nil)
// var _ server.Application (*EthermintApp)(nil) // var _ server.Application (*EthermintApp)(nil)
// EthermintApp implements an extended ABCI application. It is an application // EthermintApp implements an extended ABCI application. It is an application
@ -256,9 +258,6 @@ type EthermintApp struct {
// the module manager // the module manager
mm *module.Manager mm *module.Manager
// simulation manager
sm *module.SimulationManager
// the configurator // the configurator
configurator module.Configurator configurator module.Configurator
} }
@ -280,6 +279,8 @@ func NewEthermintApp(
cdc := encodingConfig.Amino cdc := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry interfaceRegistry := encodingConfig.InterfaceRegistry
eip712.SetEncodingConfig(encodingConfig)
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx // NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
bApp := baseapp.NewBaseApp( bApp := baseapp.NewBaseApp(
appName, appName,
@ -313,6 +314,12 @@ func NewEthermintApp(
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
// load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, keys); err != nil {
fmt.Printf("failed to load state streaming: %s", err)
os.Exit(1)
}
app := &EthermintApp{ app := &EthermintApp{
BaseApp: bApp, BaseApp: bApp,
cdc: cdc, cdc: cdc,
@ -658,17 +665,6 @@ func NewEthermintApp(
// add test gRPC service for testing gRPC queries in isolation // add test gRPC service for testing gRPC queries in isolation
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{}) // testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
// create the simulation manager and define the order of the modules for deterministic simulations
//
// NOTE: this is not required apps that don't use the simulator for fuzz testing
// transactions
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
}
app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules)
app.sm.RegisterStoreDecoders()
// initialize stores // initialize stores
app.MountKVStores(keys) app.MountKVStores(keys)
app.MountTransientStores(tkeys) app.MountTransientStores(tkeys)
@ -718,6 +714,8 @@ func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted u
EvmKeeper: app.EvmKeeper, EvmKeeper: app.EvmKeeper,
FeeMarketKeeper: app.FeeMarketKeeper, FeeMarketKeeper: app.FeeMarketKeeper,
MaxTxGasWanted: maxGasWanted, MaxTxGasWanted: maxGasWanted,
ExtensionOptionChecker: ethermint.HasDynamicFeeExtensionOption,
// TxFeeChecker: ante.NewDynamicFeeChecker(app.EvmKeeper),
}) })
if err != nil { if err != nil {
panic(err) panic(err)
@ -838,11 +836,6 @@ func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
return 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 // RegisterAPIRoutes registers all application module routes with the provided
// API server. // API server.
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
@ -851,6 +844,8 @@ func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// Register new tendermint queries routes from grpc-gateway. // Register new tendermint queries routes from grpc-gateway.
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) 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) ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
@ -876,6 +871,12 @@ 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 // RegisterSwaggerAPI registers swagger route with API Server
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) { func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
statikFS, err := fs.New() statikFS, err := fs.New()

View File

@ -1,414 +0,0 @@
package app
// TODO: COsmos SDK fix for the simulator issue for custom keys
import (
"encoding/json"
"fmt"
"math/rand"
"os"
"runtime/debug"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/cerc-io/laconicd/app/ante"
evmenc "github.com/cerc-io/laconicd/encoding"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
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"
ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
)
// MakeEncodingConfig creates the EncodingConfig
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.
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
bapp.SetFauxMerkleMode()
}
// NewSimApp disable feemarket on native tx, otherwise the cosmos-sdk simulation tests will fail.
func NewSimApp(logger log.Logger, db dbm.DB) (*EthermintApp, error) {
encodingConfig := MakeEncodingConfig()
app := NewEthermintApp(logger, db, nil, false, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, encodingConfig, simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
// disable feemarket on native tx
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
IBCKeeper: app.IBCKeeper,
EvmKeeper: app.EvmKeeper,
FeeMarketKeeper: app.FeeMarketKeeper,
MaxTxGasWanted: 0,
})
if err != nil {
return nil, err
}
app.SetAnteHandler(anteHandler)
if err := app.LoadLatestVersion(); err != nil {
return nil, err
}
return app, nil
}
// interBlockCacheOpt returns a BaseApp option function that sets the persistent
// inter-block write-through cache.
func interBlockCacheOpt() func(*baseapp.BaseApp) {
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
}
func TestFullAppSimulation(t *testing.T) {
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
if skip {
t.Skip("skipping application simulation")
}
require.NoError(t, err, "simulation setup failed")
config.ChainID = SimAppChainID
defer func() {
require.NoError(t, db.Close())
require.NoError(t, os.RemoveAll(dir))
}()
app, err := NewSimApp(logger, db)
require.Equal(t, appName, app.Name())
require.NoError(t, err)
// run randomized simulation
_, simParams, simErr := simulation.SimulateFromSeed(
t,
os.Stdout,
app.BaseApp,
StateFn(app.AppCodec(), app.SimulationManager()),
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simapp.SimulationOperations(app, app.AppCodec(), config),
app.ModuleAccountAddrs(),
config,
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")
config.ChainID = SimAppChainID
defer func() {
require.NoError(t, db.Close())
require.NoError(t, os.RemoveAll(dir))
}()
app, err := NewSimApp(logger, db)
require.NoError(t, err)
require.Equal(t, appName, app.Name())
// Run randomized simulation
_, simParams, simErr := simulation.SimulateFromSeed(
t,
os.Stdout,
app.BaseApp,
StateFn(app.AppCodec(), app.SimulationManager()),
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simapp.SimulationOperations(app, app.AppCodec(), config),
app.ModuleAccountAddrs(),
config,
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() {
require.NoError(t, newDB.Close())
require.NoError(t, os.RemoveAll(newDir))
}()
newApp, err := NewSimApp(log.NewNopLogger(), newDB)
require.Equal(t, appName, newApp.Name())
require.NoError(t, err)
var genesisState simapp.GenesisState
err = json.Unmarshal(exported.AppState, &genesisState)
require.NoError(t, err)
defer func() {
if r := recover(); r != nil {
err := fmt.Sprintf("%v", r)
if !strings.Contains(err, "validator set is empty after InitGenesis") {
panic(r)
}
logger.Info("Skipping simulation as all validators have been unbonded")
logger.Info("err", err, "stacktrace", string(debug.Stack()))
}
}()
ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID})
ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight(), ChainID: SimAppChainID})
newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState)
newApp.StoreConsensusParams(ctxB, exported.ConsensusParams)
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[authzkeeper.StoreKey], newApp.keys[authzkeeper.StoreKey], [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}},
{app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}},
{app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}},
}
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")
config.ChainID = SimAppChainID
defer func() {
require.NoError(t, db.Close())
require.NoError(t, os.RemoveAll(dir))
}()
app, err := NewSimApp(logger, db)
require.Equal(t, appName, app.Name())
require.NoError(t, err)
// Run randomized simulation
stopEarly, simParams, simErr := simulation.SimulateFromSeed(
t,
os.Stdout,
app.BaseApp,
StateFn(app.AppCodec(), app.SimulationManager()),
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simapp.SimulationOperations(app, app.AppCodec(), config),
app.ModuleAccountAddrs(),
config,
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)
defer func() {
if r := recover(); r != nil {
err := fmt.Sprintf("%v", r)
if !strings.Contains(err, "validator set is empty after InitGenesis") {
panic(r)
}
logger.Info("Skipping simulation as all validators have been unbonded")
logger.Info("err", err, "stacktrace", string(debug.Stack()))
}
}()
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() {
require.NoError(t, newDB.Close())
require.NoError(t, os.RemoveAll(newDir))
}()
newApp, err := NewSimApp(log.NewNopLogger(), newDB)
require.Equal(t, appName, newApp.Name())
require.NoError(t, err)
newApp.InitChain(abci.RequestInitChain{
ChainId: SimAppChainID,
AppStateBytes: exported.AppState,
})
_, _, err = simulation.SimulateFromSeed(
t,
os.Stdout,
newApp.BaseApp,
StateFn(app.AppCodec(), app.SimulationManager()),
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simapp.SimulationOperations(newApp, newApp.AppCodec(), config),
app.ModuleAccountAddrs(),
config,
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 := dbm.NewMemDB()
app, err := NewSimApp(logger, db)
require.NoError(t, err)
fmt.Printf(
"running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n",
config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
)
_, _, err = simulation.SimulateFromSeed(
t,
os.Stdout,
app.BaseApp,
StateFn(app.AppCodec(), app.SimulationManager()),
RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simapp.SimulationOperations(app, app.AppCodec(), config),
app.ModuleAccountAddrs(),
config,
app.AppCodec(),
)
require.NoError(t, err)
if config.Commit {
simapp.PrintStats(db)
}
appHash := app.LastCommitID().Hash
appHashList[j] = appHash
if j != 0 {
require.Equal(
t, string(appHashList[0]), string(appHashList[j]),
"non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed,
)
}
}
}
}

View File

@ -5,27 +5,21 @@ import (
"math/rand" // #nosec G702 "math/rand" // #nosec G702
"time" "time"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 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/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/mock" "github.com/cosmos/cosmos-sdk/testutil/mock"
"github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cerc-io/laconicd/encoding" "github.com/cerc-io/laconicd/encoding"
ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@ -94,22 +88,27 @@ func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.Genesis
return app return app
} }
// RandomGenesisAccounts is used by the auth module to create random genesis accounts in simulation when a genesis.json is not specified. // NewTestGenesisState generate genesis state with single validator
// In contrast, the default auth module's RandomGenesisAccounts implementation creates only base accounts and vestings accounts. func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts { privVal := mock.NewPV()
emptyCodeHash := crypto.Keccak256(nil) pubKey, err := privVal.GetPubKey()
genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts)) if err != nil {
for i, acc := range simState.Accounts { panic(err)
bacc := authtypes.NewBaseAccountWithAddress(acc.Address)
ethacc := &ethermint.EthAccount{
BaseAccount: bacc,
CodeHash: common.BytesToHash(emptyCodeHash).String(),
} }
genesisAccs[i] = ethacc // 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))),
} }
return genesisAccs genesisState := NewDefaultGenesisState()
return genesisStateWithValSet(codec, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
} }
// RandomAccounts creates random accounts with an ethsecp256k1 private key // RandomAccounts creates random accounts with an ethsecp256k1 private key
@ -135,78 +134,6 @@ func RandomAccounts(r *rand.Rand, n int) []simtypes.Account {
return accs return accs
} }
// StateFn returns the initial application state using a genesis or the simulation parameters.
// It is a wrapper of simapp.AppStateFn to replace evm param EvmDenom with staking param BondDenom.
func StateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
appStateFn := simapp.AppStateFn(cdc, simManager)
appState, simAccs, chainID, genesisTimestamp = appStateFn(r, accs, config)
rawState := make(map[string]json.RawMessage)
err := json.Unmarshal(appState, &rawState)
if err != nil {
panic(err)
}
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
if !ok {
panic("staking genesis state is missing")
}
stakingState := new(stakingtypes.GenesisState)
cdc.MustUnmarshalJSON(stakingStateBz, stakingState)
// we should get the BondDenom and make it the evmdenom.
// thus simulation accounts could have positive amount of gas token.
bondDenom := stakingState.Params.BondDenom
evmStateBz, ok := rawState[evmtypes.ModuleName]
if !ok {
panic("evm genesis state is missing")
}
evmState := new(evmtypes.GenesisState)
cdc.MustUnmarshalJSON(evmStateBz, evmState)
// we should replace the EvmDenom with BondDenom
evmState.Params.EvmDenom = bondDenom
// change appState back
rawState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmState)
// replace appstate
appState, err = json.Marshal(rawState)
if err != nil {
panic(err)
}
return appState, simAccs, chainID, genesisTimestamp
}
}
// NewTestGenesisState generate genesis state with single validator
func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
privVal := mock.NewPV()
pubKey, err := privVal.GetPubKey()
if err != nil {
panic(err)
}
// create validator set with single validator
validator := tmtypes.NewValidator(pubKey, 1)
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
// generate genesis account
senderPrivKey := secp256k1.GenPrivKey()
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}
genesisState := NewDefaultGenesisState()
return genesisStateWithValSet(codec, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
}
func genesisStateWithValSet(codec codec.Codec, genesisState simapp.GenesisState, func genesisStateWithValSet(codec codec.Codec, genesisState simapp.GenesisState,
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount,
balances ...banktypes.Balance, balances ...banktypes.Balance,

View File

@ -1,113 +0,0 @@
package app
import (
"encoding/json"
"math/rand"
"os"
"testing"
"github.com/stretchr/testify/require"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
)
var (
maxTestingAccounts = 100
seed = int64(233)
)
func TestRandomGenesisAccounts(t *testing.T) {
r := rand.New(rand.NewSource(seed))
accs := RandomAccounts(r, rand.Intn(maxTestingAccounts))
encodingConfig := MakeEncodingConfig()
appCodec := encodingConfig.Codec
cdc := encodingConfig.Amino
paramsKeeper := initParamsKeeper(appCodec, cdc, sdk.NewKVStoreKey(paramstypes.StoreKey), sdk.NewTransientStoreKey(paramstypes.StoreKey))
subSpace, find := paramsKeeper.GetSubspace(authtypes.ModuleName)
require.True(t, find)
accountKeeper := authkeeper.NewAccountKeeper(
appCodec, sdk.NewKVStoreKey(authtypes.StoreKey), subSpace, ethermint.ProtoAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(),
)
authModule := auth.NewAppModule(appCodec, accountKeeper, RandomGenesisAccounts)
genesisState := simapp.NewDefaultGenesisState(appCodec)
simState := &module.SimulationState{Accounts: accs, Cdc: appCodec, Rand: r, GenState: genesisState}
authModule.GenerateGenesisState(simState)
authStateBz, find := genesisState[authtypes.ModuleName]
require.True(t, find)
authState := new(authtypes.GenesisState)
appCodec.MustUnmarshalJSON(authStateBz, authState)
accounts, err := authtypes.UnpackAccounts(authState.Accounts)
require.NoError(t, err)
for _, acc := range accounts {
_, ok := acc.(ethermint.EthAccountI)
require.True(t, ok)
}
}
func TestStateFn(t *testing.T) {
config, db, dir, logger, skip, err := simapp.SetupSimulation("leveldb-app-sim", "Simulation")
if skip {
t.Skip("skipping AppStateFn testing")
}
require.NoError(t, err, "simulation setup failed")
config.ChainID = SimAppChainID
config.Commit = true
defer func() {
db.Close()
require.NoError(t, os.RemoveAll(dir))
}()
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, fauxMerkleModeOpt)
require.Equal(t, appName, app.Name())
appStateFn := StateFn(app.AppCodec(), app.SimulationManager())
r := rand.New(rand.NewSource(seed))
accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts))
appState, _, _, _ := appStateFn(r, accounts, config)
rawState := make(map[string]json.RawMessage)
err = json.Unmarshal(appState, &rawState)
require.NoError(t, err)
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
require.True(t, ok)
stakingState := new(stakingtypes.GenesisState)
app.AppCodec().MustUnmarshalJSON(stakingStateBz, stakingState)
bondDenom := stakingState.Params.BondDenom
evmStateBz, ok := rawState[evmtypes.ModuleName]
require.True(t, ok)
evmState := new(evmtypes.GenesisState)
app.AppCodec().MustUnmarshalJSON(evmStateBz, evmState)
require.Equal(t, bondDenom, evmState.Params.EvmDenom)
}
func TestRandomAccounts(t *testing.T) {
r := rand.New(rand.NewSource(seed))
accounts := RandomAccounts(r, rand.Intn(maxTestingAccounts))
for _, acc := range accounts {
_, ok := acc.PrivKey.(*ethsecp256k1.PrivKey)
require.True(t, ok)
}
}

View File

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

View File

@ -13,57 +13,6 @@
"Params": "EvmParams" "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"
}
}
} }
] ]
} }

File diff suppressed because one or more lines are too long

View File

@ -154,10 +154,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -369,10 +372,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -583,10 +589,20 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
<<<<<<< HEAD
any, err := ptypes.MarshalAny(foo) any, err := ptypes.MarshalAny(foo)
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := ptypes.UnmarshalAny(any, foo); err != nil {
=======
any, err := anypb.New(foo)
if err != nil {
...
}
...
foo := &pb.Foo{}
if err := any.UnmarshalTo(foo); err != nil {
>>>>>>> v0.20.0
... ...
} }
@ -791,10 +807,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -1014,10 +1033,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -1226,10 +1248,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -1301,6 +1326,18 @@ paths:
required: false required: false
type: string type: string
format: uint64 format: uint64
- name: proposer_address
description: the proposer of the requested block.
in: query
required: false
type: string
format: byte
- name: chain_id
description: the eip155 chain id parsed from the requested block header.
in: query
required: false
type: string
format: int64
tags: tags:
- Query - Query
/ethermint/evm/v1/eth_call: /ethermint/evm/v1/eth_call:
@ -1524,10 +1561,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -1599,6 +1639,18 @@ paths:
required: false required: false
type: string type: string
format: uint64 format: uint64
- name: proposer_address
description: the proposer of the requested block.
in: query
required: false
type: string
format: byte
- name: chain_id
description: the eip155 chain id parsed from the requested block header.
in: query
required: false
type: string
format: int64
tags: tags:
- Query - Query
/ethermint/evm/v1/params: /ethermint/evm/v1/params:
@ -1713,11 +1765,24 @@ paths:
title: >- title: >-
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = Eip-4345 (bomb delay) switch block (nil = no fork, 0 =
already activated) already activated)
<<<<<<< HEAD
merge_fork_block: merge_fork_block:
type: string type: string
title: >- title: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = EIP-3675 (TheMerge) switch block (nil = no fork, 0 =
already in merge proceedings) already in merge proceedings)
=======
gray_glacier_block:
type: string
title: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 =
already activated)
merge_netsplit_block:
type: string
title: >-
Virtual fork after The Merge to use as a network
splitter
>>>>>>> v0.20.0
description: >- description: >-
ChainConfig defines the Ethereum ChainConfig parameters ChainConfig defines the Ethereum ChainConfig parameters
using *sdk.Int values using *sdk.Int values
@ -1727,7 +1792,11 @@ paths:
type: boolean type: boolean
description: >- description: >-
Allow unprotected transactions defines if replay-protected Allow unprotected transactions defines if replay-protected
<<<<<<< HEAD
(i.e non EIP155 (i.e non EIP155
=======
(i.e non EIP155
>>>>>>> v0.20.0
signed) transactions can be executed on the state machine. signed) transactions can be executed on the state machine.
title: Params defines the EVM module parameters title: Params defines the EVM module parameters
@ -1861,10 +1930,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -2072,10 +2144,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -2292,10 +2367,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -2481,10 +2559,22 @@ paths:
in: query in: query
required: false required: false
type: string type: string
<<<<<<< HEAD
- name: trace_config.overrides.merge_fork_block - name: trace_config.overrides.merge_fork_block
description: >- description: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
merge proceedings). merge proceedings).
=======
- name: trace_config.overrides.gray_glacier_block
description: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already
activated).
in: query
required: false
type: string
- name: trace_config.overrides.merge_netsplit_block
description: Virtual fork after The Merge to use as a network splitter.
>>>>>>> v0.20.0
in: query in: query
required: false required: false
type: string type: string
@ -2498,6 +2588,11 @@ paths:
in: query in: query
required: false required: false
type: boolean type: boolean
- name: trace_config.tracer_json_config
description: tracer config.
in: query
required: false
type: string
- name: block_number - name: block_number
description: block number. description: block number.
in: query in: query
@ -2515,6 +2610,18 @@ paths:
required: false required: false
type: string type: string
format: date-time format: date-time
- name: proposer_address
description: the proposer of the requested block.
in: query
required: false
type: string
format: byte
- name: chain_id
description: the eip155 chain id parsed from the requested block header.
in: query
required: false
type: string
format: int64
tags: tags:
- Query - Query
/ethermint/evm/v1/trace_tx: /ethermint/evm/v1/trace_tx:
@ -2659,10 +2766,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -2783,7 +2893,7 @@ paths:
type: string type: string
format: byte format: byte
- name: msg.size - name: msg.size
description: encoded storage size of the transaction. description: 'DEPRECATED: encoded storage size of the transaction.'
in: query in: query
required: false required: false
type: number type: number
@ -2927,10 +3037,22 @@ paths:
in: query in: query
required: false required: false
type: string type: string
<<<<<<< HEAD
- name: trace_config.overrides.merge_fork_block - name: trace_config.overrides.merge_fork_block
description: >- description: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
merge proceedings). merge proceedings).
=======
- name: trace_config.overrides.gray_glacier_block
description: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already
activated).
in: query
required: false
type: string
- name: trace_config.overrides.merge_netsplit_block
description: Virtual fork after The Merge to use as a network splitter.
>>>>>>> v0.20.0
in: query in: query
required: false required: false
type: string type: string
@ -2944,6 +3066,11 @@ paths:
in: query in: query
required: false required: false
type: boolean type: boolean
- name: trace_config.tracer_json_config
description: tracer config.
in: query
required: false
type: string
- name: block_number - name: block_number
description: block number of requested transaction. description: block number of requested transaction.
in: query in: query
@ -2961,6 +3088,18 @@ paths:
required: false required: false
type: string type: string
format: date-time format: date-time
- name: proposer_address
description: the proposer of the requested block.
in: query
required: false
type: string
format: byte
- name: chain_id
description: the eip155 chain id parsed from the requested block header.
in: query
required: false
type: string
format: int64
tags: tags:
- Query - Query
/ethermint/evm/v1/validator_account/{cons_address}: /ethermint/evm/v1/validator_account/{cons_address}:
@ -3120,10 +3259,13 @@ paths:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -3190,6 +3332,7 @@ paths:
type: string type: string
tags: tags:
- Query - Query
<<<<<<< HEAD
/cosmos/auth/v1beta1/accounts: /cosmos/auth/v1beta1/accounts:
get: get:
summary: Accounts returns all the existing accounts summary: Accounts returns all the existing accounts
@ -14052,6 +14195,8 @@ paths:
type: boolean type: boolean
tags: tags:
- Query - Query
=======
>>>>>>> v0.20.0
definitions: definitions:
ethermint.evm.v1.ChainConfig: ethermint.evm.v1.ChainConfig:
type: object type: object
@ -14111,11 +14256,22 @@ definitions:
title: >- title: >-
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
activated) activated)
<<<<<<< HEAD
merge_fork_block: merge_fork_block:
type: string type: string
title: >- title: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in merge EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in merge
proceedings) proceedings)
=======
gray_glacier_block:
type: string
title: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already
activated)
merge_netsplit_block:
type: string
title: Virtual fork after The Merge to use as a network splitter
>>>>>>> v0.20.0
description: >- description: >-
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
values values
@ -14287,10 +14443,13 @@ definitions:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -14344,7 +14503,7 @@ definitions:
size: size:
type: number type: number
format: double format: double
title: encoded storage size of the transaction title: 'DEPRECATED: encoded storage size of the transaction'
hash: hash:
type: string type: string
title: transaction hash in hex format title: transaction hash in hex format
@ -14515,11 +14674,22 @@ definitions:
title: >- title: >-
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
activated) activated)
<<<<<<< HEAD
merge_fork_block: merge_fork_block:
type: string type: string
title: >- title: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
merge proceedings) merge proceedings)
=======
gray_glacier_block:
type: string
title: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already
activated)
merge_netsplit_block:
type: string
title: Virtual fork after The Merge to use as a network splitter
>>>>>>> v0.20.0
description: >- description: >-
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
values values
@ -14529,7 +14699,11 @@ definitions:
type: boolean type: boolean
description: >- description: >-
Allow unprotected transactions defines if replay-protected (i.e non Allow unprotected transactions defines if replay-protected (i.e non
<<<<<<< HEAD
EIP155 EIP155
=======
EIP155
>>>>>>> v0.20.0
signed) transactions can be executed on the state machine. signed) transactions can be executed on the state machine.
title: Params defines the EVM module parameters title: Params defines the EVM module parameters
@ -14684,11 +14858,22 @@ definitions:
title: >- title: >-
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
activated) activated)
<<<<<<< HEAD
merge_fork_block: merge_fork_block:
type: string type: string
title: >- title: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already
in merge proceedings) in merge proceedings)
=======
gray_glacier_block:
type: string
title: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already
activated)
merge_netsplit_block:
type: string
title: Virtual fork after The Merge to use as a network splitter
>>>>>>> v0.20.0
description: >- description: >-
ChainConfig defines the Ethereum ChainConfig parameters using ChainConfig defines the Ethereum ChainConfig parameters using
*sdk.Int values *sdk.Int values
@ -14698,7 +14883,11 @@ definitions:
type: boolean type: boolean
description: >- description: >-
Allow unprotected transactions defines if replay-protected (i.e Allow unprotected transactions defines if replay-protected (i.e
<<<<<<< HEAD
non EIP155 non EIP155
=======
non EIP155
>>>>>>> v0.20.0
signed) transactions can be executed on the state machine. signed) transactions can be executed on the state machine.
title: Params defines the EVM module parameters title: Params defines the EVM module parameters
@ -14839,11 +15028,22 @@ definitions:
title: >- title: >-
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
activated) activated)
<<<<<<< HEAD
merge_fork_block: merge_fork_block:
type: string type: string
title: >- title: >-
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
merge proceedings) merge proceedings)
=======
gray_glacier_block:
type: string
title: >-
EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already
activated)
merge_netsplit_block:
type: string
title: Virtual fork after The Merge to use as a network splitter
>>>>>>> v0.20.0
description: >- description: >-
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
values values
@ -14855,6 +15055,9 @@ definitions:
enable_return_data: enable_return_data:
type: boolean type: boolean
title: enable return data capture title: enable return data capture
tracer_json_config:
type: string
title: tracer config
description: TraceConfig holds extra parameters to trace functions. description: TraceConfig holds extra parameters to trace functions.
google.protobuf.Any: google.protobuf.Any:
type: object type: object
@ -14958,10 +15161,13 @@ definitions:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -15132,10 +15338,13 @@ definitions:
Example 4: Pack and unpack a message in Go Example 4: Pack and unpack a message in Go
foo := &pb.Foo{...} foo := &pb.Foo{...}
any, err := ptypes.MarshalAny(foo) any, err := anypb.New(foo)
if err != nil {
...
}
... ...
foo := &pb.Foo{} foo := &pb.Foo{}
if err := ptypes.UnmarshalAny(any, foo); err != nil { if err := any.UnmarshalTo(foo); err != nil {
... ...
} }
@ -15185,6 +15394,7 @@ definitions:
"@type": "type.googleapis.com/google.protobuf.Duration", "@type": "type.googleapis.com/google.protobuf.Duration",
"value": "1.212s" "value": "1.212s"
} }
<<<<<<< HEAD
cosmos.auth.v1beta1.Params: cosmos.auth.v1beta1.Params:
type: object type: object
properties: properties:
@ -21145,3 +21355,5 @@ definitions:
application's application's
state transition machine. state transition machine.
=======
>>>>>>> v0.20.0

View File

@ -50,18 +50,32 @@ 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 { func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *bufio.Reader) error {
var err error var (
algo keyring.SignatureAlgo
err error
)
name := args[0] name := args[0]
interactive, _ := cmd.Flags().GetBool(flagInteractive) interactive, _ := cmd.Flags().GetBool(flagInteractive)
noBackup, _ := cmd.Flags().GetBool(flagNoBackup) noBackup, _ := cmd.Flags().GetBool(flagNoBackup)
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
showMnemonic := !noBackup showMnemonic := !noBackup
kb := ctx.Keyring kb := ctx.Keyring
outputFormat := ctx.OutputFormat outputFormat := ctx.OutputFormat
keyringAlgos, _ := kb.SupportedAlgorithms() keyringAlgos, ledgerAlgos := kb.SupportedAlgorithms()
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos) // 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)
}
if err != nil { if err != nil {
return err return err
} }
@ -144,7 +158,6 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
account, _ := cmd.Flags().GetUint32(flagAccount) account, _ := cmd.Flags().GetUint32(flagAccount)
index, _ := cmd.Flags().GetUint32(flagIndex) index, _ := cmd.Flags().GetUint32(flagIndex)
hdPath, _ := cmd.Flags().GetString(flagHDPath) hdPath, _ := cmd.Flags().GetString(flagHDPath)
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
if len(hdPath) == 0 { if len(hdPath) == 0 {
hdPath = hd.CreateHDPath(coinType, account, index).String() hdPath = hd.CreateHDPath(coinType, account, index).String()
@ -155,7 +168,9 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
// If we're using ledger, only thing we need is the path and the bech32 prefix. // If we're using ledger, only thing we need is the path and the bech32 prefix.
if useLedger { if useLedger {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
k, err := kb.SaveLedgerKey(name, hd.Secp256k1, bech32PrefixAccAddr, coinType, account, index)
// use the provided algo to save the ledger key
k, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index)
if err != nil { if err != nil {
return err return err
} }

View File

@ -8,9 +8,7 @@ import (
"github.com/cerc-io/laconicd/version" "github.com/cerc-io/laconicd/version"
) )
const ( const flagLong = "long"
flagLong = "long"
)
func init() { func init() {
infoCmd.Flags().Bool(flagLong, false, "Print full information") infoCmd.Flags().Bool(flagLong, false, "Print full information")

View File

@ -32,7 +32,7 @@ const (
// AddGenesisAccountCmd returns add-genesis-account cobra Command. // AddGenesisAccountCmd returns add-genesis-account cobra Command.
func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command { func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", Use: "add-genesis-account ADDRESS_OR_KEY_NAME COIN...",
Short: "Add a genesis account to genesis.json", Short: "Add a genesis account to genesis.json",
Long: `Add a genesis account to genesis.json. The provided account must specify 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, the account address or key name and a list of initial coins. If a key name is given,

View File

@ -37,13 +37,14 @@ import (
"github.com/cerc-io/laconicd/client/debug" "github.com/cerc-io/laconicd/client/debug"
"github.com/cerc-io/laconicd/crypto/hd" "github.com/cerc-io/laconicd/crypto/hd"
"github.com/cerc-io/laconicd/encoding" "github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/ethereum/eip712"
"github.com/cerc-io/laconicd/server" "github.com/cerc-io/laconicd/server"
servercfg "github.com/cerc-io/laconicd/server/config" servercfg "github.com/cerc-io/laconicd/server/config"
srvflags "github.com/cerc-io/laconicd/server/flags" srvflags "github.com/cerc-io/laconicd/server/flags"
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
) )
const EnvPrefix = "ETHERMINT" const EnvPrefix = "LACONIC"
// NewRootCmd creates a new root command for simd. It is called once in the // NewRootCmd creates a new root command for simd. It is called once in the
// main function. // main function.
@ -61,9 +62,11 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
WithKeyringOptions(hd.EthSecp256k1Option()). WithKeyringOptions(hd.EthSecp256k1Option()).
WithViper(EnvPrefix) WithViper(EnvPrefix)
eip712.SetEncodingConfig(encodingConfig)
rootCmd := &cobra.Command{ rootCmd := &cobra.Command{
Use: "laconicd", Use: "laconicd",
Short: "Ethermint Daemon", Short: "Laconic Daemon",
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
// set the default command outputs // set the default command outputs
cmd.SetOut(cmd.OutOrStdout()) cmd.SetOut(cmd.OutOrStdout())
@ -182,6 +185,7 @@ func txCommand() *cobra.Command {
authcmd.GetBroadcastCommand(), authcmd.GetBroadcastCommand(),
authcmd.GetEncodeCommand(), authcmd.GetEncodeCommand(),
authcmd.GetDecodeCommand(), authcmd.GetDecodeCommand(),
authcmd.GetAuxToFeeCommand(),
) )
app.ModuleBasics.AddTxCommands(cmd) app.ModuleBasics.AddTxCommands(cmd)
@ -246,6 +250,8 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
baseapp.SetTrace(cast.ToBool(appOpts.Get(sdkserver.FlagTrace))), baseapp.SetTrace(cast.ToBool(appOpts.Get(sdkserver.FlagTrace))),
baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))), baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))),
baseapp.SetSnapshot(snapshotStore, snapshotOptions), baseapp.SetSnapshot(snapshotStore, snapshotOptions),
baseapp.SetIAVLCacheSize(cast.ToInt(appOpts.Get(sdkserver.FlagIAVLCacheSize))),
baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(sdkserver.FlagDisableIAVLFastNode))),
) )
return ethermintApp return ethermintApp

View File

@ -6,11 +6,12 @@ import (
"crypto/subtle" "crypto/subtle"
"fmt" "fmt"
errorsmod "cosmossdk.io/errors"
"github.com/cerc-io/laconicd/ethereum/eip712"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
tmcrypto "github.com/tendermint/tendermint/crypto" tmcrypto "github.com/tendermint/tendermint/crypto"
) )
@ -182,7 +183,7 @@ func (pubKey PubKey) MarshalAmino() ([]byte, error) {
// UnmarshalAmino overrides Amino binary marshaling. // UnmarshalAmino overrides Amino binary marshaling.
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error { func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
if len(bz) != PubKeySize { if len(bz) != PubKeySize {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz)) return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
} }
pubKey.Key = bz pubKey.Key = bz
@ -203,10 +204,28 @@ func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error {
// VerifySignature verifies that the ECDSA public key created a given signature over // VerifySignature verifies that the ECDSA public key created a given signature over
// the provided message. It will calculate the Keccak256 hash of the message // the provided message. It will calculate the Keccak256 hash of the message
// prior to verification. // prior to verification and approve verification if the signature can be verified
// from either the original message or its EIP-712 representation.
// //
// CONTRACT: The signature should be in [R || S] format. // CONTRACT: The signature should be in [R || S] format.
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool { func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
return pubKey.verifySignatureECDSA(msg, sig) || pubKey.verifySignatureAsEIP712(msg, sig)
}
// Verifies the signature as an EIP-712 signature by first converting the message payload
// to EIP-712 object bytes, then performing ECDSA verification on the hash. This is to support
// signing a Cosmos payload using EIP-712.
func (pubKey PubKey) verifySignatureAsEIP712(msg, sig []byte) bool {
eip712Bytes, err := eip712.GetEIP712BytesForMsg(msg)
if err != nil {
return false
}
return pubKey.verifySignatureECDSA(eip712Bytes, sig)
}
// Perform standard ECDSA signature verification for the given raw bytes and signature.
func (pubKey PubKey) verifySignatureECDSA(msg, sig []byte) bool {
if len(sig) == crypto.SignatureLength { if len(sig) == crypto.SignatureLength {
// remove recovery ID (V) if contained in the signature // remove recovery ID (V) if contained in the signature
sig = sig[:len(sig)-1] sig = sig[:len(sig)-1]

View File

@ -5,7 +5,7 @@ package ethsecp256k1
import ( import (
fmt "fmt" fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto" _ "github.com/cosmos/gogoproto/gogoproto"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
io "io" io "io"
math "math" math "math"
@ -27,6 +27,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// Tendermint's PubKey interface. It represents the 33-byte compressed public // Tendermint's PubKey interface. It represents the 33-byte compressed public
// key format. // key format.
type PubKey struct { type PubKey struct {
// key is the public key in byte form
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
} }
@ -72,6 +73,7 @@ func (m *PubKey) GetKey() []byte {
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements // PrivKey defines a type alias for an ecdsa.PrivateKey that implements
// Tendermint's PrivateKey interface. // Tendermint's PrivateKey interface.
type PrivKey struct { type PrivKey struct {
// key is the private key in byte form
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
} }

View File

@ -1,6 +1,7 @@
package hd package hd
import ( import (
"os"
"strings" "strings"
"testing" "testing"
@ -10,7 +11,6 @@ import (
hdwallet "github.com/miguelmota/go-ethereum-hdwallet" hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
"github.com/cosmos/cosmos-sdk/codec"
amino "github.com/cosmos/cosmos-sdk/codec" amino "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keyring"
@ -20,10 +20,10 @@ import (
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
) )
var TestCodec codec.Codec var TestCodec amino.Codec
func init() { func init() {
cdc := codec.NewLegacyAmino() cdc := amino.NewLegacyAmino()
cryptocodec.RegisterCrypto(cdc) cryptocodec.RegisterCrypto(cdc)
interfaceRegistry := types.NewInterfaceRegistry() interfaceRegistry := types.NewInterfaceRegistry()
@ -31,12 +31,18 @@ func init() {
enccodec.RegisterInterfaces(interfaceRegistry) enccodec.RegisterInterfaces(interfaceRegistry)
} }
const mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret" const (
mnemonic = "picnic rent average infant boat squirrel federal assault mercy purity very motor fossil wheel verify upset box fresh horse vivid copy predict square regret"
// hdWalletFixEnv defines whether the standard (correct) bip39
// derivation path was used, or if derivation was affected by
// https://github.com/btcsuite/btcutil/issues/172
hdWalletFixEnv = "GO_ETHEREUM_HDWALLET_FIX_ISSUE_179"
)
func TestKeyring(t *testing.T) { func TestKeyring(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
mockIn := strings.NewReader("") mockIn := strings.NewReader("")
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, TestCodec, EthSecp256k1Option()) kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, TestCodec, EthSecp256k1Option())
require.NoError(t, err) require.NoError(t, err)
@ -68,7 +74,9 @@ func TestKeyring(t *testing.T) {
privkey := EthSecp256k1.Generate()(bz) privkey := EthSecp256k1.Generate()(bz)
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes()) addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
os.Setenv(hdWalletFixEnv, "true")
wallet, err := hdwallet.NewFromMnemonic(mnemonic) wallet, err := hdwallet.NewFromMnemonic(mnemonic)
os.Setenv(hdWalletFixEnv, "")
require.NoError(t, err) require.NoError(t, err)
path := hdwallet.MustParseDerivationPath(hdPath) path := hdwallet.MustParseDerivationPath(hdPath)

View File

@ -423,6 +423,7 @@ TraceConfig holds extra parameters to trace functions.
| `overrides` | [ChainConfig](#ethermint.evm.v1.ChainConfig) | | Chain overrides, can be used to execute a trace using future fork rules | | `overrides` | [ChainConfig](#ethermint.evm.v1.ChainConfig) | | Chain overrides, can be used to execute a trace using future fork rules |
| `enable_memory` | [bool](#bool) | | enable memory capture | | `enable_memory` | [bool](#bool) | | enable memory capture |
| `enable_return_data` | [bool](#bool) | | enable return data capture | | `enable_return_data` | [bool](#bool) | | enable return data capture |
| `tracer_json_config` | [string](#string) | | tracer config |
@ -710,6 +711,8 @@ EthCallRequest defines EthCall request
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| `args` | [bytes](#bytes) | | same json format as the json rpc api. | | `args` | [bytes](#bytes) | | same json format as the json rpc api. |
| `gas_cap` | [uint64](#uint64) | | the default gas cap to be used | | `gas_cap` | [uint64](#uint64) | | the default gas cap to be used |
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
| `chain_id` | [int64](#int64) | | the eip155 chain id parsed from the requested block header |
@ -939,6 +942,8 @@ QueryTraceBlockRequest defines TraceTx request
| `block_number` | [int64](#int64) | | block number | | `block_number` | [int64](#int64) | | block number |
| `block_hash` | [string](#string) | | block hex hash | | `block_hash` | [string](#string) | | block hex hash |
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time | | `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time |
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
| `chain_id` | [int64](#int64) | | the eip155 chain id parsed from the requested block header |
@ -974,6 +979,8 @@ QueryTraceTxRequest defines TraceTx request
| `block_number` | [int64](#int64) | | block number of requested transaction | | `block_number` | [int64](#int64) | | block number of requested transaction |
| `block_hash` | [string](#string) | | block hex hash of requested transaction | | `block_hash` | [string](#string) | | block hex hash of requested transaction |
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time of requested transaction | | `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time of requested transaction |
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
| `chain_id` | [int64](#int64) | | the eip155 chain id parsed from the requested block header |

View File

@ -14,35 +14,17 @@ import (
"golang.org/x/text/cases" "golang.org/x/text/cases"
"golang.org/x/text/language" "golang.org/x/text/language"
errorsmod "cosmossdk.io/errors"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" errortypes "github.com/cosmos/cosmos-sdk/types/errors"
registry "github.com/cerc-io/laconicd/x/registry/types" registry "github.com/cerc-io/laconicd/x/registry/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/core/apitypes"
) )
// ComputeTypedDataHash computes keccak hash of typed data for signing.
func ComputeTypedDataHash(typedData apitypes.TypedData) ([]byte, error) {
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
if err != nil {
err = sdkerrors.Wrap(err, "failed to pack and hash typedData EIP712Domain")
return nil, err
}
typedDataHash, err := typedData.HashStruct(typedData.PrimaryType, typedData.Message)
if err != nil {
err = sdkerrors.Wrap(err, "failed to pack and hash typedData primary type")
return nil, err
}
rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash)))
return crypto.Keccak256(rawData), nil
}
// WrapTxToTypedData is an ultimate method that wraps Amino-encoded Cosmos Tx JSON data // WrapTxToTypedData is an ultimate method that wraps Amino-encoded Cosmos Tx JSON data
// into an EIP712-compatible TypedData request. // into an EIP712-compatible TypedData request.
func WrapTxToTypedData( func WrapTxToTypedData(
@ -55,7 +37,7 @@ func WrapTxToTypedData(
txData := make(map[string]interface{}) txData := make(map[string]interface{})
if err := json.Unmarshal(data, &txData); err != nil { if err := json.Unmarshal(data, &txData); err != nil {
return apitypes.TypedData{}, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, "failed to JSON unmarshal data") return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data")
} }
if txData["msgs"].([]interface{})[0].(map[string]interface{})["value"].(map[string]interface{})["payload"] != nil { if txData["msgs"].([]interface{})[0].(map[string]interface{})["value"].(map[string]interface{})["payload"] != nil {
@ -65,7 +47,7 @@ func WrapTxToTypedData(
attr = append(attr, fmt.Sprintf("%v", b)) attr = append(attr, fmt.Sprintf("%v", b))
} }
txData["msgs"].([]interface{})[0].(map[string]interface{})["value"].(map[string]interface{})["payload"].(map[string]interface{})["record"].(map[string]interface{})["attributes"] = map[string]interface{}{ txData["msgs"].([]interface{})[0].(map[string]interface{})["value"].(map[string]interface{})["payload"].(map[string]interface{})["record"].(map[string]interface{})["attributes"] = map[string]interface{}{ //nolint:lll
"type_url": setRecordMsg.Payload.Record.Attributes.TypeUrl, "type_url": setRecordMsg.Payload.Record.Attributes.TypeUrl,
"value": attr, "value": attr,
} }
@ -105,7 +87,7 @@ func WrapTxToTypedData(
if feeDelegation != nil { if feeDelegation != nil {
feeInfo, ok := txData["fee"].(map[string]interface{}) feeInfo, ok := txData["fee"].(map[string]interface{})
if !ok { if !ok {
return apitypes.TypedData{}, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "cannot parse fee from tx data") return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrInvalidType, "cannot parse fee from tx data")
} }
feeInfo["feePayer"] = feeDelegation.FeePayer.String() feeInfo["feePayer"] = feeDelegation.FeePayer.String()
@ -238,7 +220,11 @@ func traverseFields(
} }
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
var field reflect.Value var (
field reflect.Value
err error
)
if v.IsValid() { if v.IsValid() {
field = v.Field(i) field = v.Field(i)
} }
@ -247,23 +233,15 @@ func traverseFields(
fieldName := jsonNameFromTag(t.Field(i).Tag) fieldName := jsonNameFromTag(t.Field(i).Tag)
if fieldType == cosmosAnyType { if fieldType == cosmosAnyType {
any, ok := field.Interface().(*codectypes.Any) // Unpack field, value as Any
if !ok { if fieldType, field, err = unpackAny(cdc, field); err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "%T", field.Interface()) return err
}
} }
anyWrapper := &cosmosAnyWrapper{ // If field is an empty value, do not include in types, since it will not be present in the object
Type: any.TypeUrl, if field.IsZero() {
} continue
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
return sdkerrors.Wrap(err, "failed to unpack Any in msg struct")
}
fieldType = reflect.TypeOf(anyWrapper)
field = reflect.ValueOf(anyWrapper)
// then continue as normal
} }
// If its a nil pointer, do not include in types // If its a nil pointer, do not include in types
@ -305,6 +283,12 @@ func traverseFields(
fieldType = fieldType.Elem() fieldType = fieldType.Elem()
field = field.Index(0) field = field.Index(0)
isCollection = true isCollection = true
if fieldType == cosmosAnyType {
if fieldType, field, err = unpackAny(cdc, field); err != nil {
return err
}
}
} }
for { for {
@ -395,6 +379,27 @@ func jsonNameFromTag(tag reflect.StructTag) string {
return parts[0] return parts[0]
} }
// Unpack the given Any value with Type/Value deconstruction
func unpackAny(cdc codectypes.AnyUnpacker, field reflect.Value) (reflect.Type, reflect.Value, error) {
any, ok := field.Interface().(*codectypes.Any)
if !ok {
return nil, reflect.Value{}, errorsmod.Wrapf(errortypes.ErrPackAny, "%T", field.Interface())
}
anyWrapper := &cosmosAnyWrapper{
Type: any.TypeUrl,
}
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
return nil, reflect.Value{}, errorsmod.Wrap(err, "failed to unpack Any in msg struct")
}
fieldType := reflect.TypeOf(anyWrapper)
field = reflect.ValueOf(anyWrapper)
return fieldType, field, nil
}
// _.foo_bar.baz -> TypeFooBarBaz // _.foo_bar.baz -> TypeFooBarBaz
// //
// this is needed for Geth's own signing code which doesn't // this is needed for Geth's own signing code which doesn't
@ -497,7 +502,7 @@ func typToEth(typ reflect.Type) string {
func doRecover(err *error) { func doRecover(err *error) {
if r := recover(); r != nil { if r := recover(); r != nil {
if e, ok := r.(error); ok { if e, ok := r.(error); ok {
e = sdkerrors.Wrap(e, "panicked with error") e = errorsmod.Wrap(e, "panicked with error")
*err = e *err = e
return return
} }

View File

@ -0,0 +1,432 @@
package eip712_test
import (
"testing"
"cosmossdk.io/math"
"github.com/cerc-io/laconicd/ethereum/eip712"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/ethereum/go-ethereum/crypto"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cerc-io/laconicd/app"
"github.com/cerc-io/laconicd/encoding"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/suite"
)
// Unit tests for single-signer EIP-712 signature verification. Multi-signer verification tests are included
// in ante_test.go.
type EIP712TestSuite struct {
suite.Suite
config params.EncodingConfig
clientCtx client.Context
}
func TestEIP712TestSuite(t *testing.T) {
suite.Run(t, &EIP712TestSuite{})
}
// Set up test env to replicate prod. environment
func (suite *EIP712TestSuite) SetupTest() {
suite.config = encoding.MakeConfig(app.ModuleBasics)
suite.clientCtx = client.Context{}.WithTxConfig(suite.config.TxConfig)
sdk.GetConfig().SetBech32PrefixForAccount("ethm", "")
eip712.SetEncodingConfig(suite.config)
}
// Helper to create random test addresses for messages
func (suite *EIP712TestSuite) createTestAddress() sdk.AccAddress {
privkey, _ := ethsecp256k1.GenerateKey()
key, err := privkey.ToECDSA()
suite.Require().NoError(err)
addr := crypto.PubkeyToAddress(key.PublicKey)
return addr.Bytes()
}
// Helper to create random keypair for signing + verification
func (suite *EIP712TestSuite) createTestKeyPair() (*ethsecp256k1.PrivKey, *ethsecp256k1.PubKey) {
privKey, err := ethsecp256k1.GenerateKey()
suite.Require().NoError(err)
pubKey := &ethsecp256k1.PubKey{
Key: privKey.PubKey().Bytes(),
}
suite.Require().Implements((*cryptotypes.PubKey)(nil), pubKey)
return privKey, pubKey
}
// Helper to create instance of sdk.Coins[] with single coin
func (suite *EIP712TestSuite) makeCoins(denom string, amount math.Int) sdk.Coins {
return sdk.NewCoins(
sdk.NewCoin(
denom,
amount,
),
)
}
func (suite *EIP712TestSuite) TestEIP712SignatureVerification() {
suite.SetupTest()
signModes := []signing.SignMode{
signing.SignMode_SIGN_MODE_DIRECT,
signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
}
// Fixed test address
testAddress := suite.createTestAddress()
testCases := []struct {
title string
chainId string
fee txtypes.Fee
memo string
msgs []sdk.Msg
accountNumber uint64
sequence uint64
timeoutHeight uint64
expectSuccess bool
}{
{
title: "Succeeds - Standard MsgSend",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
banktypes.NewMsgSend(
suite.createTestAddress(),
suite.createTestAddress(),
suite.makeCoins("photon", math.NewInt(1)),
),
},
accountNumber: 8,
sequence: 5,
expectSuccess: true,
},
{
title: "Succeeds - Standard MsgVote",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
govtypes.NewMsgVote(
suite.createTestAddress(),
5,
govtypes.OptionNo,
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: true,
},
{
title: "Succeeds - Standard MsgDelegate",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
stakingtypes.NewMsgDelegate(
suite.createTestAddress(),
sdk.ValAddress(suite.createTestAddress()),
suite.makeCoins("photon", math.NewInt(1))[0],
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: true,
},
{
title: "Succeeds - Standard MsgWithdrawDelegationReward",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
distributiontypes.NewMsgWithdrawDelegatorReward(
suite.createTestAddress(),
sdk.ValAddress(suite.createTestAddress()),
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: true,
},
{
title: "Succeeds - Two Single-Signer MsgDelegate",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
stakingtypes.NewMsgDelegate(
testAddress,
sdk.ValAddress(suite.createTestAddress()),
suite.makeCoins("photon", math.NewInt(1))[0],
),
stakingtypes.NewMsgDelegate(
testAddress,
sdk.ValAddress(suite.createTestAddress()),
suite.makeCoins("photon", math.NewInt(5))[0],
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: true,
},
{
title: "Fails - Two MsgVotes with Different Signers",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
govtypes.NewMsgVote(
suite.createTestAddress(),
5,
govtypes.OptionNo,
),
govtypes.NewMsgVote(
suite.createTestAddress(),
25,
govtypes.OptionAbstain,
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: false,
},
{
title: "Fails - Empty transaction",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{},
accountNumber: 25,
sequence: 78,
expectSuccess: false,
},
{
title: "Fails - Single-Signer MsgSend + MsgVote",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
govtypes.NewMsgVote(
testAddress,
5,
govtypes.OptionNo,
),
banktypes.NewMsgSend(
testAddress,
suite.createTestAddress(),
suite.makeCoins("photon", math.NewInt(50)),
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: false,
},
{
title: "Fails - Invalid ChainID",
chainId: "invalidchainid",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
govtypes.NewMsgVote(
suite.createTestAddress(),
5,
govtypes.OptionNo,
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: false,
},
{
title: "Fails - Includes TimeoutHeight",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
govtypes.NewMsgVote(
suite.createTestAddress(),
5,
govtypes.OptionNo,
),
},
accountNumber: 25,
sequence: 78,
timeoutHeight: 1000,
expectSuccess: false,
},
{
title: "Fails - Single Message / Multi-Signer",
fee: txtypes.Fee{
Amount: suite.makeCoins("aphoton", math.NewInt(2000)),
GasLimit: 20000,
},
memo: "",
msgs: []sdk.Msg{
banktypes.NewMsgMultiSend(
[]banktypes.Input{
banktypes.NewInput(
suite.createTestAddress(),
suite.makeCoins("photon", math.NewInt(50)),
),
banktypes.NewInput(
suite.createTestAddress(),
suite.makeCoins("photon", math.NewInt(50)),
),
},
[]banktypes.Output{
banktypes.NewOutput(
suite.createTestAddress(),
suite.makeCoins("photon", math.NewInt(50)),
),
banktypes.NewOutput(
suite.createTestAddress(),
suite.makeCoins("photon", math.NewInt(50)),
),
},
),
},
accountNumber: 25,
sequence: 78,
expectSuccess: false,
},
}
for _, tc := range testCases {
for _, signMode := range signModes {
suite.Run(tc.title, func() {
privKey, pubKey := suite.createTestKeyPair()
// Init tx builder
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
// Set gas and fees
txBuilder.SetGasLimit(tc.fee.GasLimit)
txBuilder.SetFeeAmount(tc.fee.Amount)
// Set messages
err := txBuilder.SetMsgs(tc.msgs...)
suite.Require().NoError(err)
// Set memo
txBuilder.SetMemo(tc.memo)
// Prepare signature field
txSigData := signing.SingleSignatureData{
SignMode: signMode,
Signature: nil,
}
txSig := signing.SignatureV2{
PubKey: pubKey,
Data: &txSigData,
Sequence: tc.sequence,
}
err = txBuilder.SetSignatures([]signing.SignatureV2{txSig}...)
suite.Require().NoError(err)
chainId := "ethermint_9000-1"
if tc.chainId != "" {
chainId = tc.chainId
}
if tc.timeoutHeight != 0 {
txBuilder.SetTimeoutHeight(tc.timeoutHeight)
}
// Declare signerData
signerData := authsigning.SignerData{
ChainID: chainId,
AccountNumber: tc.accountNumber,
Sequence: tc.sequence,
PubKey: pubKey,
Address: sdk.MustBech32ifyAddressBytes("ethm", pubKey.Bytes()),
}
bz, err := suite.clientCtx.TxConfig.SignModeHandler().GetSignBytes(
signMode,
signerData,
txBuilder.GetTx(),
)
suite.Require().NoError(err)
suite.verifyEIP712SignatureVerification(tc.expectSuccess, *privKey, *pubKey, bz)
})
}
}
}
// Verify that the payload passes signature verification if signed as its EIP-712 representation.
func (suite *EIP712TestSuite) verifyEIP712SignatureVerification(expectedSuccess bool, privKey ethsecp256k1.PrivKey, pubKey ethsecp256k1.PubKey, signBytes []byte) {
// Convert to EIP712 bytes and sign
eip712Bytes, err := eip712.GetEIP712BytesForMsg(signBytes)
if !expectedSuccess {
// Expect failure generating EIP-712 bytes
suite.Require().Error(err)
return
}
suite.Require().NoError(err)
sig, err := privKey.Sign(eip712Bytes)
suite.Require().NoError(err)
// Verify against original payload bytes. This should pass, even though it is not
// the original message that was signed.
res := pubKey.VerifySignature(signBytes, sig)
suite.Require().True(res)
// Verify against the signed EIP-712 bytes. This should pass, since it is the message signed.
res = pubKey.VerifySignature(eip712Bytes, sig)
suite.Require().True(res)
// Verify against random bytes to ensure it does not pass unexpectedly (sanity check).
randBytes := make([]byte, len(signBytes))
copy(randBytes, signBytes)
// Change the first element of signBytes to a different value
randBytes[0] = (signBytes[0] + 10) % 128
res = pubKey.VerifySignature(randBytes, sig)
suite.Require().False(res)
}

299
ethereum/eip712/encoding.go Normal file
View File

@ -0,0 +1,299 @@
package eip712
import (
"encoding/json"
"errors"
"fmt"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
sdk "github.com/cosmos/cosmos-sdk/types"
txTypes "github.com/cosmos/cosmos-sdk/types/tx"
ethermint "github.com/cerc-io/laconicd/types"
apitypes "github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/cosmos/cosmos-sdk/codec"
)
type aminoMessage struct {
Type string `json:"type"`
Value interface{} `json:"value"`
}
var (
protoCodec codec.ProtoCodecMarshaler
aminoCodec *codec.LegacyAmino
)
// SetEncodingConfig set the encoding config to the singleton codecs (Amino and Protobuf).
// The process of unmarshaling SignDoc bytes into a SignDoc object requires having a codec
// populated with all relevant message types. As a result, we must call this method on app
// initialization with the app's encoding config.
func SetEncodingConfig(cfg params.EncodingConfig) {
aminoCodec = cfg.Amino
protoCodec = codec.NewProtoCodec(cfg.InterfaceRegistry)
}
// Get the EIP-712 object bytes for the given SignDoc bytes by first decoding the bytes into
// an EIP-712 object, then hashing the EIP-712 object to create the bytes to be signed.
// See https://eips.ethereum.org/EIPS/eip-712 for more.
func GetEIP712BytesForMsg(signDocBytes []byte) ([]byte, error) {
typedData, err := GetEIP712TypedDataForMsg(signDocBytes)
if err != nil {
return nil, err
}
_, rawData, err := apitypes.TypedDataAndHash(typedData)
if err != nil {
return nil, fmt.Errorf("could not get EIP-712 object bytes: %w", err)
}
return []byte(rawData), nil
}
// GetEIP712TypedDataForMsg returns the EIP-712 TypedData representation for either
// Amino or Protobuf encoded signature doc bytes.
func GetEIP712TypedDataForMsg(signDocBytes []byte) (apitypes.TypedData, error) {
// Attempt to decode as both Amino and Protobuf since the message format is unknown.
// If either decode works, we can move forward with the corresponding typed data.
typedDataAmino, errAmino := decodeAminoSignDoc(signDocBytes)
if errAmino == nil && isValidEIP712Payload(typedDataAmino) {
return typedDataAmino, nil
}
typedDataProtobuf, errProtobuf := decodeProtobufSignDoc(signDocBytes)
if errProtobuf == nil && isValidEIP712Payload(typedDataProtobuf) {
return typedDataProtobuf, nil
}
return apitypes.TypedData{}, fmt.Errorf("could not decode sign doc as either Amino or Protobuf.\n amino: %v\n protobuf: %v", errAmino, errProtobuf)
}
// isValidEIP712Payload ensures that the given TypedData does not contain empty fields from
// an improper initialization.
func isValidEIP712Payload(typedData apitypes.TypedData) bool {
return len(typedData.Message) != 0 && len(typedData.Types) != 0 && typedData.PrimaryType != "" && typedData.Domain != apitypes.TypedDataDomain{}
}
// decodeAminoSignDoc attempts to decode the provided sign doc (bytes) as an Amino payload
// and returns a signable EIP-712 TypedData object.
func decodeAminoSignDoc(signDocBytes []byte) (apitypes.TypedData, error) {
// Ensure codecs have been initialized
if err := validateCodecInit(); err != nil {
return apitypes.TypedData{}, err
}
var aminoDoc legacytx.StdSignDoc
if err := aminoCodec.UnmarshalJSON(signDocBytes, &aminoDoc); err != nil {
return apitypes.TypedData{}, err
}
var fees legacytx.StdFee
if err := aminoCodec.UnmarshalJSON(aminoDoc.Fee, &fees); err != nil {
return apitypes.TypedData{}, err
}
// Validate payload messages
msgs := make([]sdk.Msg, len(aminoDoc.Msgs))
for i, jsonMsg := range aminoDoc.Msgs {
var m sdk.Msg
if err := aminoCodec.UnmarshalJSON(jsonMsg, &m); err != nil {
return apitypes.TypedData{}, fmt.Errorf("failed to unmarshal sign doc message: %w", err)
}
msgs[i] = m
}
if err := validatePayloadMessages(msgs); err != nil {
return apitypes.TypedData{}, err
}
// Use first message for fee payer and type inference
msg := msgs[0]
// By convention, the fee payer is the first address in the list of signers.
feePayer := msg.GetSigners()[0]
feeDelegation := &FeeDelegationOptions{
FeePayer: feePayer,
}
chainID, err := ethermint.ParseChainID(aminoDoc.ChainID)
if err != nil {
return apitypes.TypedData{}, errors.New("invalid chain ID passed as argument")
}
typedData, err := WrapTxToTypedData(
protoCodec,
chainID.Uint64(),
msg,
signDocBytes,
feeDelegation,
)
if err != nil {
return apitypes.TypedData{}, fmt.Errorf("could not convert to EIP712 representation: %w", err)
}
return typedData, nil
}
// decodeProtobufSignDoc attempts to decode the provided sign doc (bytes) as a Protobuf payload
// and returns a signable EIP-712 TypedData object.
func decodeProtobufSignDoc(signDocBytes []byte) (apitypes.TypedData, error) {
// Ensure codecs have been initialized
if err := validateCodecInit(); err != nil {
return apitypes.TypedData{}, err
}
signDoc := &txTypes.SignDoc{}
if err := signDoc.Unmarshal(signDocBytes); err != nil {
return apitypes.TypedData{}, err
}
authInfo := &txTypes.AuthInfo{}
if err := authInfo.Unmarshal(signDoc.AuthInfoBytes); err != nil {
return apitypes.TypedData{}, err
}
body := &txTypes.TxBody{}
if err := body.Unmarshal(signDoc.BodyBytes); err != nil {
return apitypes.TypedData{}, err
}
// Until support for these fields is added, throw an error at their presence
if body.TimeoutHeight != 0 || len(body.ExtensionOptions) != 0 || len(body.NonCriticalExtensionOptions) != 0 {
return apitypes.TypedData{}, errors.New("body contains unsupported fields: TimeoutHeight, ExtensionOptions, or NonCriticalExtensionOptions")
}
if len(authInfo.SignerInfos) != 1 {
return apitypes.TypedData{}, fmt.Errorf("invalid number of signer infos provided, expected 1 got %v", len(authInfo.SignerInfos))
}
// Validate payload messages
msgs := make([]sdk.Msg, len(body.Messages))
for i, protoMsg := range body.Messages {
var m sdk.Msg
if err := protoCodec.UnpackAny(protoMsg, &m); err != nil {
return apitypes.TypedData{}, fmt.Errorf("could not unpack message object with error %w", err)
}
msgs[i] = m
}
if err := validatePayloadMessages(msgs); err != nil {
return apitypes.TypedData{}, err
}
// Use first message for fee payer and type inference
msg := msgs[0]
signerInfo := authInfo.SignerInfos[0]
chainID, err := ethermint.ParseChainID(signDoc.ChainId)
if err != nil {
return apitypes.TypedData{}, fmt.Errorf("invalid chain ID passed as argument: %w", err)
}
stdFee := &legacytx.StdFee{
Amount: authInfo.Fee.Amount,
Gas: authInfo.Fee.GasLimit,
}
feePayer := msg.GetSigners()[0]
feeDelegation := &FeeDelegationOptions{
FeePayer: feePayer,
}
tip := authInfo.Tip
// WrapTxToTypedData expects the payload as an Amino Sign Doc
signBytes := legacytx.StdSignBytes(
signDoc.ChainId,
signDoc.AccountNumber,
signerInfo.Sequence,
body.TimeoutHeight,
*stdFee,
msgs,
body.Memo,
tip,
)
typedData, err := WrapTxToTypedData(
protoCodec,
chainID.Uint64(),
msg,
signBytes,
feeDelegation,
)
if err != nil {
return apitypes.TypedData{}, err
}
return typedData, nil
}
// validateCodecInit ensures that both Amino and Protobuf encoding codecs have been set on app init,
// so the module does not panic if either codec is not found.
func validateCodecInit() error {
if aminoCodec == nil || protoCodec == nil {
return errors.New("missing codec: codecs have not been properly initialized using SetEncodingConfig")
}
return nil
}
// validatePayloadMessages ensures that the transaction messages can be represented in an EIP-712
// encoding by checking that messages exist, are of the same type, and share a single signer.
func validatePayloadMessages(msgs []sdk.Msg) error {
if len(msgs) == 0 {
return errors.New("unable to build EIP-712 payload: transaction does contain any messages")
}
var msgType string
var msgSigner sdk.AccAddress
for i, m := range msgs {
t, err := getMsgType(m)
if err != nil {
return err
}
if len(m.GetSigners()) != 1 {
return errors.New("unable to build EIP-712 payload: expect exactly 1 signer")
}
if i == 0 {
msgType = t
msgSigner = m.GetSigners()[0]
continue
}
if t != msgType {
return errors.New("unable to build EIP-712 payload: different types of messages detected")
}
if !msgSigner.Equals(m.GetSigners()[0]) {
return errors.New("unable to build EIP-712 payload: multiple signers detected")
}
}
return nil
}
// getMsgType returns the message type prefix for the given Cosmos SDK Msg
func getMsgType(msg sdk.Msg) (string, error) {
jsonBytes, err := aminoCodec.MarshalJSON(msg)
if err != nil {
return "", err
}
var jsonMsg aminoMessage
if err := json.Unmarshal(jsonBytes, &jsonMsg); err != nil {
return "", err
}
// Verify Type was successfully filled in
if jsonMsg.Type == "" {
return "", errors.New("could not decode message: type is missing")
}
return jsonMsg.Type, nil
}

63
go.mod
View File

@ -1,19 +1,22 @@
module github.com/cerc-io/laconicd module github.com/cerc-io/laconicd
go 1.18 go 1.19
require ( require (
cosmossdk.io/math v1.0.0-beta.3 cosmossdk.io/errors v1.0.0-beta.7
github.com/99designs/gqlgen v0.17.20 cosmossdk.io/math v1.0.0-beta.4
github.com/99designs/gqlgen v0.17.22
github.com/armon/go-metrics v0.4.1 github.com/armon/go-metrics v0.4.1
github.com/btcsuite/btcd v0.22.1 github.com/btcsuite/btcd v0.22.1
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/cosmos/cosmos-sdk v0.46.3 github.com/cosmos/cosmos-proto v1.0.0-beta.1
github.com/cosmos/cosmos-sdk v0.46.7
github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/ibc-go/v5 v5.0.1 github.com/cosmos/gogoproto v1.4.3
github.com/cosmos/ibc-go/v5 v5.2.0
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set v1.8.0 github.com/deckarep/golang-set v1.8.0
github.com/ethereum/go-ethereum v1.10.19 github.com/ethereum/go-ethereum v1.10.26
github.com/gibson042/canonicaljson-go v1.0.3 github.com/gibson042/canonicaljson-go v1.0.3
github.com/gogo/protobuf v1.3.3 github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
@ -26,27 +29,26 @@ require (
github.com/ipfs/go-ipld-cbor v0.0.6 github.com/ipfs/go-ipld-cbor v0.0.6
github.com/ipld/go-ipld-prime v0.18.0 github.com/ipld/go-ipld-prime v0.18.0
github.com/miguelmota/go-ethereum-hdwallet v0.1.1 github.com/miguelmota/go-ethereum-hdwallet v0.1.1
github.com/multiformats/go-multihash v0.2.1 github.com/multiformats/go-multihash v0.2.0
github.com/onsi/ginkgo/v2 v2.2.0 github.com/onsi/ginkgo/v2 v2.5.1
github.com/onsi/gomega v1.20.2 github.com/onsi/gomega v1.24.1
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/rakyll/statik v0.1.7 github.com/rakyll/statik v0.1.7
github.com/regen-network/cosmos-proto v0.3.1
github.com/rs/cors v1.8.2 github.com/rs/cors v1.8.2
github.com/spf13/cast v1.5.0 github.com/spf13/cast v1.5.0
github.com/spf13/cobra v1.5.0 github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.13.0 github.com/spf13/viper v1.14.0
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.1
github.com/tendermint/tendermint v0.34.22 github.com/tendermint/tendermint v0.34.24
github.com/tendermint/tm-db v0.6.7 github.com/tendermint/tm-db v0.6.7
github.com/tyler-smith/go-bip39 v1.1.0 github.com/tyler-smith/go-bip39 v1.1.0
github.com/vektah/gqlparser/v2 v2.5.1 github.com/vektah/gqlparser/v2 v2.5.1
golang.org/x/net v0.3.0 golang.org/x/net v0.4.0
golang.org/x/text v0.5.0 golang.org/x/text v0.5.0
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c
google.golang.org/grpc v1.51.0 google.golang.org/grpc v1.51.0
google.golang.org/protobuf v1.28.1 google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
sigs.k8s.io/yaml v1.3.0 sigs.k8s.io/yaml v1.3.0
) )
@ -57,7 +59,6 @@ require (
cloud.google.com/go/compute/metadata v0.2.1 // indirect cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go/iam v0.8.0 // indirect cloud.google.com/go/iam v0.8.0 // indirect
cloud.google.com/go/storage v1.27.0 // indirect cloud.google.com/go/storage v1.27.0 // indirect
cosmossdk.io/errors v1.0.0-beta.7 // indirect
filippo.io/edwards25519 v1.0.0-rc.1 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect
github.com/99designs/keyring v1.2.1 // indirect github.com/99designs/keyring v1.2.1 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
@ -69,7 +70,7 @@ require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect
@ -77,13 +78,11 @@ require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
github.com/confio/ics23/go v0.7.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect
github.com/cosmos/btcutil v1.0.4 // indirect github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/cosmos-proto v1.0.0-alpha7 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/cosmos/iavl v0.19.3 // indirect github.com/cosmos/iavl v0.19.4 // indirect
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
github.com/cosmos/ledger-go v0.9.2 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
@ -97,11 +96,12 @@ require (
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/go-stack/stack v1.8.0 // indirect github.com/go-stack/stack v1.8.0 // indirect
@ -139,7 +139,7 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
github.com/klauspost/compress v1.15.9 // indirect github.com/klauspost/compress v1.15.11 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/lib/pq v1.10.6 // indirect github.com/lib/pq v1.10.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect
@ -170,9 +170,10 @@ require (
github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.34.0 // indirect github.com/prometheus/common v0.34.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.8.0 // indirect
github.com/prometheus/tsdb v0.7.1 // indirect github.com/prometheus/tsdb v0.7.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/regen-network/cosmos-proto v0.3.1 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rs/zerolog v1.27.0 // indirect github.com/rs/zerolog v1.27.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect
@ -191,7 +192,8 @@ require (
github.com/tklauser/numcpus v0.4.0 // indirect github.com/tklauser/numcpus v0.4.0 // indirect
github.com/ulikunitz/xz v0.5.8 // indirect github.com/ulikunitz/xz v0.5.8 // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect github.com/zondax/hid v0.9.1 // indirect
github.com/zondax/ledger-go v0.14.0 // indirect
go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/bbolt v1.3.6 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.4.0 // indirect golang.org/x/crypto v0.4.0 // indirect
@ -211,10 +213,13 @@ require (
) )
replace ( replace (
// use cosmos keyring
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
// ics23 patch for dragonberry
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
// use cosmos flavored protobufs
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
) )

135
go.sum
View File

@ -52,15 +52,15 @@ cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w=
cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE=
cosmossdk.io/math v1.0.0-beta.3 h1:TbZxSopz2LqjJ7aXYfn7nJSb8vNaBklW6BLpcei1qwM= cosmossdk.io/math v1.0.0-beta.4 h1:JtKedVLGzA0vv84xjYmZ75RKG35Kf2WwcFu8IjRkIIw=
cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4= cosmossdk.io/math v1.0.0-beta.4/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw= git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw=
git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA=
github.com/99designs/gqlgen v0.17.20 h1:O7WzccIhKB1dm+7g6dhQcULINftfiLSBg2l/mwbpJMw= github.com/99designs/gqlgen v0.17.22 h1:TOcrF8t0T3I0za9JD3CB6ehq7dDEMjR9Onikf8Lc/04=
github.com/99designs/gqlgen v0.17.20/go.mod h1:Mja2HI23kWT1VRH09hvWshFgOzKswpO20o4ScpJIES4= github.com/99designs/gqlgen v0.17.22/go.mod h1:BMhYIhe4bp7OlCo5I2PnowSK/Wimpv/YlxfNkqZGwLo=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=
@ -87,7 +87,7 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
@ -157,7 +157,6 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94=
@ -165,13 +164,12 @@ github.com/btcsuite/btcd v0.21.0-beta.0.20201114000516-e9c7a5ac6401/go.mod h1:Sv
github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
@ -222,8 +220,6 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE
github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI=
github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA=
github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M= github.com/coinbase/rosetta-sdk-go v0.7.9/go.mod h1:0/knutI7XGVqXmmH4OQD8OckFrbQ8yMsUZTG7FXCR2M=
github.com/confio/ics23/go v0.7.0 h1:00d2kukk7sPoHWL4zZBZwzxnpA2pec1NPdwbSokJ5w8=
github.com/confio/ics23/go v0.7.0/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg=
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
github.com/consensys/bavard v0.1.8-0.20210915155054-088da2f7f54a/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/bavard v0.1.8-0.20210915155054-088da2f7f54a/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
@ -235,30 +231,34 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk=
github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis=
github.com/cosmos/cosmos-proto v1.0.0-alpha7 h1:yqYUOHF2jopwZh4dVQp3xgqwftE5/2hkrwIV6vkUbO0= github.com/cosmos/cosmos-proto v1.0.0-beta.1 h1:iDL5qh++NoXxG8hSy93FdYJut4XfgbShIocllGaXx/0=
github.com/cosmos/cosmos-proto v1.0.0-alpha7/go.mod h1:dosO4pSAbJF8zWCzCoTWP7nNsjcvSUBQmniFxDg5daw= github.com/cosmos/cosmos-proto v1.0.0-beta.1/go.mod h1:8k2GNZghi5sDRFw/scPL8gMSowT1vDA+5ouxL8GjaUE=
github.com/cosmos/cosmos-sdk v0.46.3 h1:2jdJYcSwh4AtFJKGoNGvmEy2mKDWtGaVZphGpvedljQ= github.com/cosmos/cosmos-sdk v0.46.7 h1:dkGy9y2ewgqvawrUOuWb2oz3MdotVduokyreXC4bS0s=
github.com/cosmos/cosmos-sdk v0.46.3/go.mod h1:AynIAjXwtS3T/ApdhNCz/7/KGMbZSUBbKRTcbukb2ic= github.com/cosmos/cosmos-sdk v0.46.7/go.mod h1:fqKqz39U5IlEFb4nbQ72951myztsDzFKKDtffYJ63nk=
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k=
github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
github.com/cosmos/gogoproto v1.4.3 h1:RP3yyVREh9snv/lsOvmsAPQt8f44LgL281X0IOIhhcI=
github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU=
github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y=
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
github.com/cosmos/iavl v0.19.3 h1:cESO0OwTTxQm5rmyESKW+zESheDUYI7CcZDWWDwnuxg= github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok=
github.com/cosmos/iavl v0.19.3/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw=
github.com/cosmos/ibc-go/v5 v5.0.1 h1:ZI5xCi6RDOL+hyu6Wx/w6JoAYFlOoK5hijsRTVWo+RA= github.com/cosmos/ibc-go/v5 v5.2.0 h1:LxwttRQqdUJpQ3/Gc3XPg5lkRo3pcbzx65dxFIY6ONE=
github.com/cosmos/ibc-go/v5 v5.0.1/go.mod h1:LX0DHLW3dfi/1e4BJzi8MGLWmQ4DSraPEgVjyo3VzAo= github.com/cosmos/ibc-go/v5 v5.2.0/go.mod h1:MhDUMDVSboK5JW2pEWHNcw0wJHaHqKV/vwwP7awGhzI=
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU=
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g=
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
@ -306,7 +306,7 @@ github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ=
@ -333,8 +333,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg=
github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0= github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0=
github.com/ethereum/go-ethereum v1.10.19 h1:EOR5JbL4MD5yeOqv8W2iC1s4NximrTjqFccUz8lyBRA= github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
github.com/ethereum/go-ethereum v1.10.19/go.mod h1:IJBNMtzKcNHPtllYihy6BL2IgK1u+32JriaTbdt4v+w= github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
@ -351,8 +351,8 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
@ -384,6 +384,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
@ -477,7 +479,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
@ -687,8 +688,8 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
@ -784,7 +785,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@ -816,8 +816,8 @@ github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPw
github.com/multiformats/go-multicodec v0.5.0 h1:EgU6cBe/D7WRwQb1KmnBvU7lrcFGMggZVTPtOW9dDHs= github.com/multiformats/go-multicodec v0.5.0 h1:EgU6cBe/D7WRwQb1KmnBvU7lrcFGMggZVTPtOW9dDHs=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= github.com/multiformats/go-multihash v0.2.0 h1:oytJb9ZA1OUW0r0f9ea18GiaPOo4SXyc7p2movyUuo4=
github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= github.com/multiformats/go-multihash v0.2.0/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@ -848,17 +848,17 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
@ -939,8 +939,9 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
@ -958,15 +959,17 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
@ -1005,8 +1008,8 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@ -1015,8 +1018,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E=
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
@ -1051,8 +1054,8 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RM
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/tendermint v0.34.22 h1:XMhtC8s8QqJO4l/dn+TkQvevTRSow3Vixjclr41o+2Q= github.com/tendermint/tendermint v0.34.24 h1:879MKKJWYYPJEMMKME+DWUTY4V9f/FBpnZDI82ky+4k=
github.com/tendermint/tendermint v0.34.22/go.mod h1:YpP5vBEAKUT4g6oyfjKgFeZmdB/GjkJAxfF+cgmJg6Y= github.com/tendermint/tendermint v0.34.24/go.mod h1:rXVrl4OYzmIa1I91av3iLv2HS0fGSiucyW9J4aMTpKI=
github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8=
github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@ -1083,9 +1086,11 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY=
github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
@ -1101,6 +1106,7 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -1110,9 +1116,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 h1:O9XLFXGkVswDFmH9LaYpqu+r/AAFWqr0DL6V00KEVFg= github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.0 h1:dlMC7aO8Wss1CxBq2I96kZ69Nh1ligzbs8UWOtq/AsA=
github.com/zondax/ledger-go v0.14.0/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
@ -1206,6 +1213,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1263,8 +1271,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1375,11 +1383,11 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@ -1396,6 +1404,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1404,7 +1413,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -1466,6 +1475,7 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1553,8 +1563,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg=
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@ -1593,10 +1603,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -1617,7 +1626,6 @@ gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJ
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@ -1648,8 +1656,7 @@ lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c=
lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= pgregory.net/rapid v0.5.3 h1:163N50IHFqr1phZens4FQOdPgfJscR7a562mjQqeo4M=
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

16
gometalinter.json Normal file
View File

@ -0,0 +1,16 @@
{
"Linters": {
"vet": "go tool vet -composites=false :PATH:LINE:MESSAGE"
},
"Enable": [
"golint",
"vet",
"ineffassign",
"unparam",
"unconvert",
"misspell"
],
"Deadline": "500s",
"Vendor": true,
"Cyclo": 11
}

View File

@ -2,26 +2,32 @@ schema = 3
[mod] [mod]
[mod."cloud.google.com/go"] [mod."cloud.google.com/go"]
version = "v0.102.1" version = "v0.105.0"
hash = "sha256-rv3MHFvIrN6AcrmWcWGSQwgaZLbjJMmJFi3bsfHoiO4=" hash = "sha256-2nYtHjuN9ghGcM6aPlOxyNNarHebHtj0Xec48sWwdaI="
[mod."cloud.google.com/go/compute"] [mod."cloud.google.com/go/compute"]
version = "v1.7.0" version = "v1.12.1"
hash = "sha256-g+n7L36LC+NP4KaiEu9fCMn6S9fkxjp4PCLOp/oXV38=" hash = "sha256-mMsdL+6R1KuFeAFqEJv8oq/cmRc9hSluEisCpGP0GTc="
[mod."cloud.google.com/go/compute/metadata"]
version = "v0.2.1"
hash = "sha256-gqjkb6y5POkTWXGQtCvgygvXqoLkESB+cykKp7Mp3jI="
[mod."cloud.google.com/go/iam"] [mod."cloud.google.com/go/iam"]
version = "v0.4.0" version = "v0.7.0"
hash = "sha256-sPtj6QPPC/QrkDXJW4Y7rMIHk5l1y9XV/DgM47eEtvg=" hash = "sha256-2UTJ/BbZ+YMGJhyo3HRPUYVDXW6+B5znFdqiutboYtA="
[mod."cloud.google.com/go/storage"] [mod."cloud.google.com/go/storage"]
version = "v1.22.1" version = "v1.27.0"
hash = "sha256-YZt05wru0kacyi6moTgvocavActKpXx7FlLh+o0HGDs=" hash = "sha256-V4B6A1Ms8cemB5Cs6nAtUe1N1ldaI9oqTdzGU2FUhrc="
[mod."cosmossdk.io/errors"] [mod."cosmossdk.io/errors"]
version = "v1.0.0-beta.7" version = "v1.0.0-beta.7"
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU=" hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
[mod."cosmossdk.io/math"] [mod."cosmossdk.io/math"]
version = "v1.0.0-beta.3" version = "v1.0.0-beta.4"
hash = "sha256-lTQ27ZlL+kWlc+S//sJmyiOwaf9qS+YLv61I4OXi9XE=" hash = "sha256-UYdq/46EubyjxkldGike8FlwJLWGCB576VB7th285ao="
[mod."filippo.io/edwards25519"] [mod."filippo.io/edwards25519"]
version = "v1.0.0-rc.1" version = "v1.0.0-rc.1"
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ=" hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
[mod."github.com/99designs/gqlgen"]
version = "v0.17.22"
hash = "sha256-Cu3nAqFbsV7DH+4UZvX83ScxJtPlvOyD7ptUPXnwGng="
[mod."github.com/99designs/keyring"] [mod."github.com/99designs/keyring"]
version = "v1.1.7-0.20210622111912-ef00f8ac3d76" version = "v1.1.7-0.20210622111912-ef00f8ac3d76"
hash = "sha256-oCalyOZWegRgKHZ1GvYHNkrMKh51j8cOE/K4yBPM5Oc=" hash = "sha256-oCalyOZWegRgKHZ1GvYHNkrMKh51j8cOE/K4yBPM5Oc="
@ -38,6 +44,9 @@ schema = 3
[mod."github.com/Workiva/go-datastructures"] [mod."github.com/Workiva/go-datastructures"]
version = "v1.0.53" version = "v1.0.53"
hash = "sha256-W6qOvqu8sokMlZrpOF1SWG138H0/BotywKNLlDF8Zug=" hash = "sha256-W6qOvqu8sokMlZrpOF1SWG138H0/BotywKNLlDF8Zug="
[mod."github.com/agnivade/levenshtein"]
version = "v1.1.1"
hash = "sha256-tgv2s8XIcWjscv1pP87TOIUV4vADT2px1Lo/MQCTBjM="
[mod."github.com/armon/go-metrics"] [mod."github.com/armon/go-metrics"]
version = "v0.4.1" version = "v0.4.1"
hash = "sha256-usxTUHA0QQMdM6sHi2z51nmnEKMbA0qUilxJFpWHlYE=" hash = "sha256-usxTUHA0QQMdM6sHi2z51nmnEKMbA0qUilxJFpWHlYE="
@ -57,8 +66,8 @@ schema = 3
version = "v0.22.1" version = "v0.22.1"
hash = "sha256-hBU+roIELcmbW2Gz7eGZzL9qNA1bakq5wNxqCgs4TKc=" hash = "sha256-hBU+roIELcmbW2Gz7eGZzL9qNA1bakq5wNxqCgs4TKc="
[mod."github.com/btcsuite/btcd/btcec/v2"] [mod."github.com/btcsuite/btcd/btcec/v2"]
version = "v2.2.0" version = "v2.3.2"
hash = "sha256-cwoIqi0SiAaGEBtuQKip9OVirKIeJw5fUoWo7x/xfOc=" hash = "sha256-natWs+yIAuD1UI07iZtjPilroQLfXizFn3lNOiOT83U="
[mod."github.com/btcsuite/btcd/chaincfg/chainhash"] [mod."github.com/btcsuite/btcd/chaincfg/chainhash"]
version = "v1.0.1" version = "v1.0.1"
hash = "sha256-vix0j/KGNvoKjhlKgVeSLY6un2FHeIEoZWMC4z3yvZ4=" hash = "sha256-vix0j/KGNvoKjhlKgVeSLY6un2FHeIEoZWMC4z3yvZ4="
@ -84,35 +93,36 @@ schema = 3
version = "v0.7.9" version = "v0.7.9"
hash = "sha256-ZWIXIXcHGjeCNgMrpXymry8/8esDDauGFfF/+gEoO1Y=" hash = "sha256-ZWIXIXcHGjeCNgMrpXymry8/8esDDauGFfF/+gEoO1Y="
[mod."github.com/confio/ics23/go"] [mod."github.com/confio/ics23/go"]
version = "v0.7.0" version = "v0.8.0"
hash = "sha256-FjUQfDKtX+/13+UjJzbYPAkgM4GPZ0vk+dKz7/iRetw=" hash = "sha256-mFKxFHp7RaE1L5NdtH9H9px2Cy6I5uOZVnFOgE8Nrew="
replaced = "github.com/cosmos/cosmos-sdk/ics23/go"
[mod."github.com/cosmos/btcutil"] [mod."github.com/cosmos/btcutil"]
version = "v1.0.4" version = "v1.0.5"
hash = "sha256-JvcBXBdjdmnaW/nyf/tw/uaOAGn1b78yxrtl2/Rs3kA=" hash = "sha256-t572Sr5iiHcuMKLMWa2i+LBAt192oa+G1oA371tG/eI="
[mod."github.com/cosmos/cosmos-proto"] [mod."github.com/cosmos/cosmos-proto"]
version = "v1.0.0-alpha7" version = "v1.0.0-beta.1"
hash = "sha256-2wCH+toTF2A6MfFjOa13muEH5oBCcxAhZEqirNOrBA0=" hash = "sha256-oATkuj+fM5eBn+ywO+w/tL0AFSIEkx0J3Yz+VhVe0QA="
[mod."github.com/cosmos/cosmos-sdk"] [mod."github.com/cosmos/cosmos-sdk"]
version = "v0.46.2-0.20220920160224-9454b97ccb77" version = "v0.46.7"
hash = "sha256-zwOsdcoPbEzn+q/UmW6/CauW65V6a4z/7k8DXPCvKb0=" hash = "sha256-54DCF8lrnA1oUmBJlbUlWXOP5UbenRInUROn5P5I9qI="
[mod."github.com/cosmos/go-bip39"] [mod."github.com/cosmos/go-bip39"]
version = "v1.0.0" version = "v1.0.0"
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA=" hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
[mod."github.com/cosmos/gogoproto"]
version = "v1.4.3"
hash = "sha256-Y/NL76ay/oAl8mS3skkK5ula0/xudqbwW1o22lZjKRg="
[mod."github.com/cosmos/gorocksdb"] [mod."github.com/cosmos/gorocksdb"]
version = "v1.2.0" version = "v1.2.0"
hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY=" hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY="
[mod."github.com/cosmos/iavl"] [mod."github.com/cosmos/iavl"]
version = "v0.19.2-0.20220916140702-9b6be3095313" version = "v0.19.4"
hash = "sha256-49xr/7/4L1wZ45eW5lE7C4SlcbGf4gBY+662SfJiWPQ=" hash = "sha256-EmpRZ48pjPFq/fIHneut9Vyo5QJATfb3ZO7KzWnqs9g="
[mod."github.com/cosmos/ibc-go/v5"] [mod."github.com/cosmos/ibc-go/v5"]
version = "v5.0.0" version = "v5.2.0"
hash = "sha256-sDZdmuGohaaBF7bxrjo9PWJnmoF+VOkjySYhsFixPz4=" hash = "sha256-Gfqhdz9ZKEgb7LCkHiXCwYZYUYluQ+vMew/GkssfVj8="
[mod."github.com/cosmos/ledger-cosmos-go"] [mod."github.com/cosmos/ledger-cosmos-go"]
version = "v0.11.1" version = "v0.12.1"
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA=" hash = "sha256-9+nr+/r4MyiogddS0JcXOuriPqXP4nxln8ts+mYQRcg="
[mod."github.com/cosmos/ledger-go"]
version = "v0.9.2"
hash = "sha256-0YI+0A6wFBjiebBwzWOQjkgXkTakCrf7Gjg2xEaQdoM="
[mod."github.com/creachadair/taskgroup"] [mod."github.com/creachadair/taskgroup"]
version = "v0.3.2" version = "v0.3.2"
hash = "sha256-Y261IO/d9xjV0UScqHvo31broxvnKn4IQQC9Mu6jNkE=" hash = "sha256-Y261IO/d9xjV0UScqHvo31broxvnKn4IQQC9Mu6jNkE="
@ -156,17 +166,20 @@ schema = 3
version = "v1.0.0" version = "v1.0.0"
hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo=" hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo="
[mod."github.com/ethereum/go-ethereum"] [mod."github.com/ethereum/go-ethereum"]
version = "v1.10.19" version = "v1.10.26"
hash = "sha256-7FPnTGcCb8Xd1QVR+6PmGTaHdTY1mm/8osFTW1JLuG8=" hash = "sha256-gkMEwJ4rOgn12amD4QpZ4th/10uyTTeoFmpseuKDQPs="
[mod."github.com/felixge/httpsnoop"] [mod."github.com/felixge/httpsnoop"]
version = "v1.0.1" version = "v1.0.1"
hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk=" hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk="
[mod."github.com/fsnotify/fsnotify"] [mod."github.com/fsnotify/fsnotify"]
version = "v1.5.4" version = "v1.6.0"
hash = "sha256-iPuInpDAJvDeSTr6to713J/fTOWdQIWlLXWAuWIs2Bw=" hash = "sha256-DQesOCweQPEwmAn6s7DCP/Dwy8IypC+osbpfsvpkdP0="
[mod."github.com/gballet/go-libpcsclite"] [mod."github.com/gballet/go-libpcsclite"]
version = "v0.0.0-20190607065134-2772fd86a8ff" version = "v0.0.0-20190607065134-2772fd86a8ff"
hash = "sha256-Nr5ocU9s1F2Lhx/Zq6/nIo+KkKEqMjDYOEs3yWRC48g=" hash = "sha256-Nr5ocU9s1F2Lhx/Zq6/nIo+KkKEqMjDYOEs3yWRC48g="
[mod."github.com/gibson042/canonicaljson-go"]
version = "v1.0.3"
hash = "sha256-CZc2lBZ5ivP0o7K+Cz3ermWOahY6C27rVrI+UI+XCS4="
[mod."github.com/go-kit/kit"] [mod."github.com/go-kit/kit"]
version = "v0.12.0" version = "v0.12.0"
hash = "sha256-5RkXo6s0oye8etgD5qy+AvkkkNsQ6jc0kWJj6flA4GM=" hash = "sha256-5RkXo6s0oye8etgD5qy+AvkkkNsQ6jc0kWJj6flA4GM="
@ -176,6 +189,9 @@ schema = 3
[mod."github.com/go-logfmt/logfmt"] [mod."github.com/go-logfmt/logfmt"]
version = "v0.5.1" version = "v0.5.1"
hash = "sha256-t50m9ffvW8PiGvO+2svnLI+N/XaWaBS+ZlhwrEQn2gU=" hash = "sha256-t50m9ffvW8PiGvO+2svnLI+N/XaWaBS+ZlhwrEQn2gU="
[mod."github.com/go-logr/logr"]
version = "v1.2.3"
hash = "sha256-2L7k6GfrcW3GXXYr1FYIu20aZBjIF0cTKdte6D4riH8="
[mod."github.com/go-ole/go-ole"] [mod."github.com/go-ole/go-ole"]
version = "v1.2.6" version = "v1.2.6"
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs=" hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
@ -211,8 +227,8 @@ schema = 3
version = "v1.0.1" version = "v1.0.1"
hash = "sha256-1PIeFGgUL4BK/StL/D12pg9bEQ5HfMT/fMLdus4pZTs=" hash = "sha256-1PIeFGgUL4BK/StL/D12pg9bEQ5HfMT/fMLdus4pZTs="
[mod."github.com/google/go-cmp"] [mod."github.com/google/go-cmp"]
version = "v0.5.8" version = "v0.5.9"
hash = "sha256-8zkIo+Sr1NXMnj3PNmvjX2sZKnAKWXOFvmnX7D9bwxQ=" hash = "sha256-lQc4O00R3QSMGs9LP8Sy7A9kj0cqV5rrUdpnGeipIyg="
[mod."github.com/google/orderedcode"] [mod."github.com/google/orderedcode"]
version = "v0.0.1" version = "v0.0.1"
hash = "sha256-KrExYovtUQrHGI1mPQf57jGw8soz7eWOC2xqEaV0uGk=" hash = "sha256-KrExYovtUQrHGI1mPQf57jGw8soz7eWOC2xqEaV0uGk="
@ -220,14 +236,11 @@ schema = 3
version = "v1.3.0" version = "v1.3.0"
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y=" hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
[mod."github.com/googleapis/enterprise-certificate-proxy"] [mod."github.com/googleapis/enterprise-certificate-proxy"]
version = "v0.1.0" version = "v0.2.0"
hash = "sha256-fxaElfiGGh1mLmltkFpVFdiuaagrLZLTW9btVpK13wg=" hash = "sha256-5gxsS5kDLqNFBkQ4eK6GS/sNn+aFknm6jjfteO+6jl4="
[mod."github.com/googleapis/gax-go/v2"] [mod."github.com/googleapis/gax-go/v2"]
version = "v2.4.0" version = "v2.6.0"
hash = "sha256-zzat4+3iF2XBTQ6RZAUgsCbfK0HgO0nYhM4utA5dqz0=" hash = "sha256-sSsncbJmv0n5jB3G7tHY1Zr2ucCusIeTrXZH4A8QqYI="
[mod."github.com/googleapis/go-type-adapters"]
version = "v1.0.0"
hash = "sha256-u3ajruRV/EN2E1WKet/zoe3zmRrAy4C5F2Dx8bpQwoc="
[mod."github.com/gorilla/handlers"] [mod."github.com/gorilla/handlers"]
version = "v1.5.1" version = "v1.5.1"
hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU=" hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU="
@ -289,8 +302,26 @@ schema = 3
version = "v0.15.0" version = "v0.15.0"
hash = "sha256-9oqKb5Y3hjleOFE2BczbEzLH6q2Jg7kUTP/M8Yk4Ne4=" hash = "sha256-9oqKb5Y3hjleOFE2BczbEzLH6q2Jg7kUTP/M8Yk4Ne4="
[mod."github.com/inconshreveable/mousetrap"] [mod."github.com/inconshreveable/mousetrap"]
version = "v1.0.0" version = "v1.0.1"
hash = "sha256-ogTuLrV40FwS4ueo4hh6hi1wPywOI+LyIqfNjsibwNY=" hash = "sha256-ZTP9pLgwAAvHYK5A4PqwWCHGt00x5zMSOpCPoomQ3Sg="
[mod."github.com/ipfs/go-block-format"]
version = "v0.0.2"
hash = "sha256-bgYso07OxWcHQx0ZxjE/G80798DnhywUSvqBb0jK48g="
[mod."github.com/ipfs/go-cid"]
version = "v0.3.2"
hash = "sha256-S7iT1bGU84EgKvScz4uJL+3o1hJ17nP5ANha1B6MVfg="
[mod."github.com/ipfs/go-ipfs-util"]
version = "v0.0.1"
hash = "sha256-Wht/WTcDwoPEwzyZZm1XoFhn3h8fWmg3xuUqBDvmB8k="
[mod."github.com/ipfs/go-ipld-cbor"]
version = "v0.0.6"
hash = "sha256-bb7jO2s1Wy0V9Uu9U3jON9E1BJh6IKYbEEfB/oglvpU="
[mod."github.com/ipfs/go-ipld-format"]
version = "v0.0.1"
hash = "sha256-LZjVFuwSwHzwxl7ZTskSFQr3kXD/qUWAmVVRCcblZFE="
[mod."github.com/ipld/go-ipld-prime"]
version = "v0.18.0"
hash = "sha256-wHkeWxIwyaKku0J8bzQ2gggWJls1ORHhHewY092BA3c="
[mod."github.com/jackpal/go-nat-pmp"] [mod."github.com/jackpal/go-nat-pmp"]
version = "v1.0.2" version = "v1.0.2"
hash = "sha256-L1D4Yoxnzihs795GZ+Q3AZsFP5c4iqyjTeyrudzPXtw=" hash = "sha256-L1D4Yoxnzihs795GZ+Q3AZsFP5c4iqyjTeyrudzPXtw="
@ -304,8 +335,11 @@ schema = 3
version = "v0.0.0-20190712205309-48d3d31d256d" version = "v0.0.0-20190712205309-48d3d31d256d"
hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q=" hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q="
[mod."github.com/klauspost/compress"] [mod."github.com/klauspost/compress"]
version = "v1.15.9" version = "v1.15.11"
hash = "sha256-ctPxlVq0c/SoNPVsP66RjxUjTHys3diW2Apxjyc9WdE=" hash = "sha256-9MXm0TObg6DyqnYMIw3IChrorHc2ILf5djZYoM0e1J0="
[mod."github.com/klauspost/cpuid/v2"]
version = "v2.0.9"
hash = "sha256-0rHlHzEVaDdkVbRJDhnAJjfJUmAHOYjXN5u7VoCi5uk="
[mod."github.com/lib/pq"] [mod."github.com/lib/pq"]
version = "v1.10.6" version = "v1.10.6"
hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM=" hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM="
@ -319,8 +353,8 @@ schema = 3
version = "v0.9.0" version = "v0.9.0"
hash = "sha256-Fe2OPoyRExZejwtUBivKhfJAJW7o9b1eyYpgDlWQ1No=" hash = "sha256-Fe2OPoyRExZejwtUBivKhfJAJW7o9b1eyYpgDlWQ1No="
[mod."github.com/mattn/go-colorable"] [mod."github.com/mattn/go-colorable"]
version = "v0.1.12" version = "v0.1.13"
hash = "sha256-Y1vCt0ShrCz4wSmwsppCfeLPLKrWusc2zM2lUFwDMyI=" hash = "sha256-qb3Qbo0CELGRIzvw7NVM1g/aayaz4Tguppk9MD2/OI8="
[mod."github.com/mattn/go-isatty"] [mod."github.com/mattn/go-isatty"]
version = "v0.0.16" version = "v0.0.16"
hash = "sha256-YMaPZvShDfA98vqw1+zWWl7M1IT4nHPGBrAt7kHo8Iw=" hash = "sha256-YMaPZvShDfA98vqw1+zWWl7M1IT4nHPGBrAt7kHo8Iw="
@ -334,11 +368,14 @@ schema = 3
version = "v0.1.1" version = "v0.1.1"
hash = "sha256-SoKy4Mwkbm0J2yQLDcIcBbo/J6auTNdlZslTvJrSknM=" hash = "sha256-SoKy4Mwkbm0J2yQLDcIcBbo/J6auTNdlZslTvJrSknM="
[mod."github.com/mimoo/StrobeGo"] [mod."github.com/mimoo/StrobeGo"]
version = "v0.0.0-20181016162300-f8f6d4d2b643" version = "v0.0.0-20210601165009-122bf33a46e0"
hash = "sha256-ih5WfC48IniPuAHUpC6upOabZA1/DssTAcxhZe6A/dE=" hash = "sha256-rmw70RHsbeOnema++aFCPdswADMVKtb7KGF3msOI7ak="
[mod."github.com/minio/highwayhash"] [mod."github.com/minio/highwayhash"]
version = "v1.0.2" version = "v1.0.2"
hash = "sha256-UeHeepKtToyA5e/w3KdmpbCn+4medesZG0cAcU6P2cY=" hash = "sha256-UeHeepKtToyA5e/w3KdmpbCn+4medesZG0cAcU6P2cY="
[mod."github.com/minio/sha256-simd"]
version = "v1.0.0"
hash = "sha256-oEo/BoMqSLdwSjrhHTiFjl5Om4MVLNQXDJINk6Z110Y="
[mod."github.com/mitchellh/go-homedir"] [mod."github.com/mitchellh/go-homedir"]
version = "v1.1.0" version = "v1.1.0"
hash = "sha256-oduBKXHAQG8X6aqLEpqZHs5DOKe84u6WkBwi4W6cv3k=" hash = "sha256-oduBKXHAQG8X6aqLEpqZHs5DOKe84u6WkBwi4W6cv3k="
@ -348,18 +385,36 @@ schema = 3
[mod."github.com/mitchellh/mapstructure"] [mod."github.com/mitchellh/mapstructure"]
version = "v1.5.0" version = "v1.5.0"
hash = "sha256-ztVhGQXs67MF8UadVvG72G3ly0ypQW0IRDdOOkjYwoE=" hash = "sha256-ztVhGQXs67MF8UadVvG72G3ly0ypQW0IRDdOOkjYwoE="
[mod."github.com/mr-tron/base58"]
version = "v1.2.0"
hash = "sha256-8FzMu3kHUbBX10pUdtGf59Ag7BNupx8ZHeUaodR1/Vk="
[mod."github.com/mtibben/percent"] [mod."github.com/mtibben/percent"]
version = "v0.2.1" version = "v0.2.1"
hash = "sha256-Zj1lpCP6mKQ0UUTMs2By4LC414ou+iJzKkK+eBHfEcc=" hash = "sha256-Zj1lpCP6mKQ0UUTMs2By4LC414ou+iJzKkK+eBHfEcc="
[mod."github.com/multiformats/go-base32"]
version = "v0.0.3"
hash = "sha256-L18a2v2c5XenmJcwB1BmN0XzDFY45H0ougcZwrGVl7g="
[mod."github.com/multiformats/go-base36"]
version = "v0.1.0"
hash = "sha256-QGoZm4HrdKWwmbJNbaTW0PvDdvPYrhx10znwhIFnFNM="
[mod."github.com/multiformats/go-multibase"]
version = "v0.0.3"
hash = "sha256-yH1bl+jSJlAvPSqg9Z7xF4JS2fpoNUqH8wCDbU87ZDA="
[mod."github.com/multiformats/go-multihash"]
version = "v0.2.0"
hash = "sha256-4pBq4HNCgos2Ic0FDw2WhoPOL5VL1FHLbiHvnO8oZSc="
[mod."github.com/multiformats/go-varint"]
version = "v0.0.6"
hash = "sha256-QlY6AzrSB/8IrlINPi8J8uw1J0SOa2UMTtlo79fg9gM="
[mod."github.com/olekukonko/tablewriter"] [mod."github.com/olekukonko/tablewriter"]
version = "v0.0.5" version = "v0.0.5"
hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4=" hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4="
[mod."github.com/onsi/ginkgo/v2"] [mod."github.com/onsi/ginkgo/v2"]
version = "v2.2.0" version = "v2.5.1"
hash = "sha256-+VzAN6pB5DwEqT/KHdhgfPnWBtyIIcHi1J4HQkqCvvU=" hash = "sha256-VB29+H9k7l6il63oXJvsjamSUhsw/e99iI/BeTCderA="
[mod."github.com/onsi/gomega"] [mod."github.com/onsi/gomega"]
version = "v1.20.2" version = "v1.24.1"
hash = "sha256-3SGyvhWVlR3tYojnRSDr2SRToontAtw4hbZX+agn/Hs=" hash = "sha256-REfxQTDRcO23GnmJfOW8/MmPJf9oE2grVvvGiC1eSbo="
[mod."github.com/pelletier/go-toml"] [mod."github.com/pelletier/go-toml"]
version = "v1.9.5" version = "v1.9.5"
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc=" hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="
@ -375,6 +430,9 @@ schema = 3
[mod."github.com/pmezard/go-difflib"] [mod."github.com/pmezard/go-difflib"]
version = "v1.0.0" version = "v1.0.0"
hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA=" hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA="
[mod."github.com/polydawn/refmt"]
version = "v0.0.0-20201211092308-30ac6d18308e"
hash = "sha256-oicfIWyK51U0LaNW0qgg5enH866TM6vsJExw98whjio="
[mod."github.com/prometheus/client_golang"] [mod."github.com/prometheus/client_golang"]
version = "v1.12.2" version = "v1.12.2"
hash = "sha256-d8xHyML/FImuPmFOy7UGW/y85NPLzJYL6IFhR3s7XzE=" hash = "sha256-d8xHyML/FImuPmFOy7UGW/y85NPLzJYL6IFhR3s7XzE="
@ -385,8 +443,8 @@ schema = 3
version = "v0.34.0" version = "v0.34.0"
hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA=" hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA="
[mod."github.com/prometheus/procfs"] [mod."github.com/prometheus/procfs"]
version = "v0.7.3" version = "v0.8.0"
hash = "sha256-ik0WpnpSjMwifPYfQTfu/eb5ilNj+eLJF0d5Dftp8A8=" hash = "sha256-hgrilokQsXCOCCvwgOSfuErxoFAQpXM/+zNJKcMVHyM="
[mod."github.com/prometheus/tsdb"] [mod."github.com/prometheus/tsdb"]
version = "v0.7.1" version = "v0.7.1"
hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA=" hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA="
@ -394,8 +452,8 @@ schema = 3
version = "v0.1.7" version = "v0.1.7"
hash = "sha256-/bfnXHBmN8vviPL7D85IzcEVXCaWyjbPPNyauzEcQ8Q=" hash = "sha256-/bfnXHBmN8vviPL7D85IzcEVXCaWyjbPPNyauzEcQ8Q="
[mod."github.com/rcrowley/go-metrics"] [mod."github.com/rcrowley/go-metrics"]
version = "v0.0.0-20200313005456-10cdbea86bc0" version = "v0.0.0-20201227073835-cf1acfcdf475"
hash = "sha256-xHqWWd4/RyAxqb80zjnrqHnHtWPfVTyByE+vDfbT52E=" hash = "sha256-10ytHQ1SpMKYTiKuOPdEMuOVa8HVvv9ryYSIF9BHEBI="
[mod."github.com/regen-network/cosmos-proto"] [mod."github.com/regen-network/cosmos-proto"]
version = "v0.3.1" version = "v0.3.1"
hash = "sha256-Bchbq/Hg72EA7Hevs8+PNuENuQaZAzk3qeVjMqFMUxc=" hash = "sha256-Bchbq/Hg72EA7Hevs8+PNuENuQaZAzk3qeVjMqFMUxc="
@ -409,20 +467,23 @@ schema = 3
version = "v1.27.0" version = "v1.27.0"
hash = "sha256-BxQtP2TROeSSpj9l1irocuSfxn55UL4ugzB/og7r8eE=" hash = "sha256-BxQtP2TROeSSpj9l1irocuSfxn55UL4ugzB/og7r8eE="
[mod."github.com/sasha-s/go-deadlock"] [mod."github.com/sasha-s/go-deadlock"]
version = "v0.2.1-0.20190427202633-1595213edefa" version = "v0.3.1"
hash = "sha256-BBOohTR+ktgJHAoYWh39/ui8MczcJECloc7tvxVBE50=" hash = "sha256-2CBEi9/iN/OMt7wEIG+hRjgDH6CRWIgibGGGy1dQ78I="
[mod."github.com/shirou/gopsutil"] [mod."github.com/shirou/gopsutil"]
version = "v3.21.4-0.20210419000835-c7a38de76ee5+incompatible" version = "v3.21.4-0.20210419000835-c7a38de76ee5+incompatible"
hash = "sha256-oqIqyFquWabIE6DID6uTEc8oFEmM1rVu2ATn3toiCEg=" hash = "sha256-oqIqyFquWabIE6DID6uTEc8oFEmM1rVu2ATn3toiCEg="
[mod."github.com/spaolacci/murmur3"]
version = "v1.1.0"
hash = "sha256-RWD4PPrlAsZZ8Xy356MBxpj+/NZI7w2XOU14Ob7/Y9M="
[mod."github.com/spf13/afero"] [mod."github.com/spf13/afero"]
version = "v1.8.2" version = "v1.9.2"
hash = "sha256-ERuG4GK1LOn72DRbT9URpo1QoVIm2A3mPtlf+xSPgx8=" hash = "sha256-R1mir7Fu95QK+YL99U14RGbLJzxqWRH5rSFpssgJvzA="
[mod."github.com/spf13/cast"] [mod."github.com/spf13/cast"]
version = "v1.5.0" version = "v1.5.0"
hash = "sha256-Pdp+wC5FWqyJKzyYHb7JCcV9BoJk/sxQw6nLyuLJvuQ=" hash = "sha256-Pdp+wC5FWqyJKzyYHb7JCcV9BoJk/sxQw6nLyuLJvuQ="
[mod."github.com/spf13/cobra"] [mod."github.com/spf13/cobra"]
version = "v1.5.0" version = "v1.6.1"
hash = "sha256-rcyHWrxshA5DVpxrSba5X4NjppqOGrJ64QkUKKnfW2E=" hash = "sha256-80B5HcYdFisz6QLYkTyka7f9Dr6AfcVyPwp3QChoXwU="
[mod."github.com/spf13/jwalterweatherman"] [mod."github.com/spf13/jwalterweatherman"]
version = "v1.1.0" version = "v1.1.0"
hash = "sha256-62BQtqTLF/eVrTOr7pUXE7AiHRjOVC8jQs3/Ehmflfs=" hash = "sha256-62BQtqTLF/eVrTOr7pUXE7AiHRjOVC8jQs3/Ehmflfs="
@ -430,17 +491,17 @@ schema = 3
version = "v1.0.5" version = "v1.0.5"
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw=" hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
[mod."github.com/spf13/viper"] [mod."github.com/spf13/viper"]
version = "v1.13.0" version = "v1.14.0"
hash = "sha256-yHviS3lMo1hB6jwyiU3zpyGtxP6v9AsyZUKiLeCVz+k=" hash = "sha256-qn3VzD339HZIub5QP4aWVciSufAfVb9llbmQZ8pfDEs="
[mod."github.com/status-im/keycard-go"] [mod."github.com/status-im/keycard-go"]
version = "v0.0.0-20200402102358-957c09536969" version = "v0.0.0-20200402102358-957c09536969"
hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk=" hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk="
[mod."github.com/stretchr/objx"] [mod."github.com/stretchr/objx"]
version = "v0.4.0" version = "v0.5.0"
hash = "sha256-W6ycaeD/okr4udpCAGDsByr3OmiR0fuBzJUXHaHEFC0=" hash = "sha256-nY4mvP0f0Ry1IKMKQAYNuioA5h4red4mmQqeGZw6EF0="
[mod."github.com/stretchr/testify"] [mod."github.com/stretchr/testify"]
version = "v1.8.0" version = "v1.8.1"
hash = "sha256-LDxBAebK+A06y4vbH7cd1sVBOameIY81Xm8/9OPZh7o=" hash = "sha256-3e0vOJLgCMAan+GfaGN8RGZdarh5iCavM6flf6YMNPk="
[mod."github.com/subosito/gotenv"] [mod."github.com/subosito/gotenv"]
version = "v1.4.1" version = "v1.4.1"
hash = "sha256-aHAUs8Gh+BREUulljWr7vBZQg1BLu/M/8UfNK8CWSn8=" hash = "sha256-aHAUs8Gh+BREUulljWr7vBZQg1BLu/M/8UfNK8CWSn8="
@ -457,8 +518,8 @@ schema = 3
version = "v0.16.0" version = "v0.16.0"
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0=" hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
[mod."github.com/tendermint/tendermint"] [mod."github.com/tendermint/tendermint"]
version = "v0.34.21" version = "v0.34.24"
hash = "sha256-C1KW6Wd4TwsFC09IHt8Jo3dozEk/Q2ZVdTapM8btEJ0=" hash = "sha256-3HFTv4XgN535RDaJ5OwUS+fnJHgkmLTwU7CNU2ilxEQ="
[mod."github.com/tendermint/tm-db"] [mod."github.com/tendermint/tm-db"]
version = "v0.6.7" version = "v0.6.7"
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo=" hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
@ -474,9 +535,18 @@ schema = 3
[mod."github.com/ulikunitz/xz"] [mod."github.com/ulikunitz/xz"]
version = "v0.5.8" version = "v0.5.8"
hash = "sha256-bfG3dssBUn+mSOAuKL+a/DTGGLUA+eASgLoGv/Gkqs0=" hash = "sha256-bfG3dssBUn+mSOAuKL+a/DTGGLUA+eASgLoGv/Gkqs0="
[mod."github.com/vektah/gqlparser/v2"]
version = "v2.5.1"
hash = "sha256-sfwSSafdEXEv/ca/EOjgaPEdezewuqdE+5AuwhsHxYU="
[mod."github.com/whyrusleeping/cbor-gen"]
version = "v0.0.0-20200123233031-1cdf64d27158"
hash = "sha256-E+9b4eXoLe95J6/n2Y12z15tMnxPoxdJtHe9B4mLFDA="
[mod."github.com/zondax/hid"] [mod."github.com/zondax/hid"]
version = "v0.9.1-0.20220302062450-5552068d2266" version = "v0.9.1"
hash = "sha256-IZea8SHuLQxlltm1avieRVI054TWZg2jEoplodvNtwk=" hash = "sha256-hSVmN/f/lQHFhF60o6ej78ELC0MMoqQgqIX2hHjdTXg="
[mod."github.com/zondax/ledger-go"]
version = "v0.14.0"
hash = "sha256-RozTPSNs4RerZ4DQMBcGmvREjoRtH1G69xjhccYjIOk="
[mod."go.etcd.io/bbolt"] [mod."go.etcd.io/bbolt"]
version = "v1.3.6" version = "v1.3.6"
hash = "sha256-DenVAmyN22xUiivk6fdJp4C9ZnUJXCMDUf8E0goRRV4=" hash = "sha256-DenVAmyN22xUiivk6fdJp4C9ZnUJXCMDUf8E0goRRV4="
@ -484,47 +554,47 @@ schema = 3
version = "v0.23.0" version = "v0.23.0"
hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg=" hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg="
[mod."golang.org/x/crypto"] [mod."golang.org/x/crypto"]
version = "v0.0.0-20220622213112-05595931fe9d" version = "v0.3.0"
hash = "sha256-2c4wvwiQ0DJSJsApfmNoxCxx1siRCiJvW9hhrGlcvds=" hash = "sha256-Un9wPqz8u/xpV98T4IqE6RMXIPhGCIm2prsNkHP3cjg="
[mod."golang.org/x/exp"] [mod."golang.org/x/exp"]
version = "v0.0.0-20220722155223-a9213eeb770e" version = "v0.0.0-20220722155223-a9213eeb770e"
hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4=" hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4="
[mod."golang.org/x/net"] [mod."golang.org/x/net"]
version = "v0.0.0-20220726230323-06994584191e" version = "v0.4.0"
hash = "sha256-VFJB2BjvFZnp0zoJLX4iinV/P6Cn7XUlsKwBGCdVjlU=" hash = "sha256-7IwGZh/xg4mQz88cJio2Ov5d3jGRXKj1itlAja/EAbQ="
[mod."golang.org/x/oauth2"] [mod."golang.org/x/oauth2"]
version = "v0.0.0-20220622183110-fd043fe589d2" version = "v0.0.0-20221014153046-6fdb5e3db783"
hash = "sha256-VLffpTpx3DlUzXB8mKiJfFzm4ZmgnLSUuLB5Ir0WQUg=" hash = "sha256-IoygidVNqyAZmN+3macDeIefK8hhJToygpcqlwehdYQ="
[mod."golang.org/x/sync"] [mod."golang.org/x/sync"]
version = "v0.0.0-20220722155255-886fb9371eb4" version = "v0.1.0"
hash = "sha256-ZZyIlxh+nqsOiWHstW7eHXN7RhHnbSL2eDIzcve07Q0=" hash = "sha256-Hygjq9euZ0qz6TvHYQwOZEjNiTbTh1nSLRAWZ6KFGR8="
[mod."golang.org/x/sys"] [mod."golang.org/x/sys"]
version = "v0.0.0-20220811171246-fbc7d0a398ab" version = "v0.3.0"
hash = "sha256-acnc9aKY/SyebObLasV+gowfB0S+6ehz3hnUgAmQmSU=" hash = "sha256-TIHhfYbZ99sCU1ZMikxwomXH5AEtD/lA1VMMW+UAhbU="
[mod."golang.org/x/term"] [mod."golang.org/x/term"]
version = "v0.0.0-20220722155259-a9ba230a4035" version = "v0.3.0"
hash = "sha256-9uM1OONzbsa6bz2iKk767hAaCuafi58bdTF7at03fWY=" hash = "sha256-NKv2o8wz8DB/2W2h/muGEIHb+S06mBXZxhG254RpQ5s="
[mod."golang.org/x/text"] [mod."golang.org/x/text"]
version = "v0.3.7" version = "v0.5.0"
hash = "sha256-XH2pUzzQx95O0rak00grQvfACfL+EmZiV7ZzJBkX+XY=" hash = "sha256-ztH+xQyM/clOcQl+y/UEPcfNKbc3xApMbEPDDZ9up0o="
[mod."golang.org/x/xerrors"] [mod."golang.org/x/xerrors"]
version = "v0.0.0-20220609144429-65e65417b02f" version = "v0.0.0-20220907171357-04be3eba64a2"
hash = "sha256-tl8pv3oddbz2+KoIp7PFDKsxjQF8ocjPF8XPsY3sw38=" hash = "sha256-6+zueutgefIYmgXinOflz8qGDDDj0Zhv+2OkGhBTKno="
[mod."google.golang.org/api"] [mod."google.golang.org/api"]
version = "v0.93.0" version = "v0.102.0"
hash = "sha256-W17B79osAhObMbrCHlgywEPg9yIPx0ZISDhp9JwFE5A=" hash = "sha256-q8t08Wu0qzOQOmhY4GSoUrhqLTW/TeXiKhio+5ONfe4="
[mod."google.golang.org/appengine"] [mod."google.golang.org/appengine"]
version = "v1.6.7" version = "v1.6.7"
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4=" hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
[mod."google.golang.org/genproto"] [mod."google.golang.org/genproto"]
version = "v0.0.0-20220815135757-37a418bb8959" version = "v0.0.0-20221116193143-41c2ba794472"
hash = "sha256-uS60VVZDdn6kNV24bmOmSTuwz4lBqVM+9XK176GGL2s=" hash = "sha256-uQuxuOvWRsdMii5M5QresisVd1E+Ss8s2WfR2n7QSXk="
[mod."google.golang.org/grpc"] [mod."google.golang.org/grpc"]
version = "v1.49.0" version = "v1.51.0"
hash = "sha256-x4+/XjxI2HY8fZYMiEV7Kv+2SrnlmaTJX3tBl+dPUoI=" hash = "sha256-RzH5DU13D/ulxxOouIKpdNt8eHdff7mrEnB+JUupbLU="
[mod."google.golang.org/protobuf"] [mod."google.golang.org/protobuf"]
version = "v1.28.1" version = "v1.28.2-0.20220831092852-f930b1dc76e8"
hash = "sha256-sTJYgvlv5is7vHNxcuigF2lNASp0QonhUgnrguhfHSU=" hash = "sha256-li5hXlXwTJ5LIZ8bVki1AZ6UFI2gXHl33JwdX1dOrtM="
[mod."gopkg.in/ini.v1"] [mod."gopkg.in/ini.v1"]
version = "v1.67.0" version = "v1.67.0"
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4=" hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
@ -537,6 +607,9 @@ schema = 3
[mod."gopkg.in/yaml.v3"] [mod."gopkg.in/yaml.v3"]
version = "v3.0.1" version = "v3.0.1"
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU=" hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
[mod."lukechampine.com/blake3"]
version = "v1.1.6"
hash = "sha256-pKVTpuCcqGSn8s11Jq33yrXewQLvycuAoxKJEdbZ7rA="
[mod."nhooyr.io/websocket"] [mod."nhooyr.io/websocket"]
version = "v1.8.6" version = "v1.8.6"
hash = "sha256-DyaiCc/1iELrl6JSpz6WYMtFwUiSCOSoNF8IhSyP1ag=" hash = "sha256-DyaiCc/1iELrl6JSpz6WYMtFwUiSCOSoNF8IhSyP1ag="

View File

@ -3,11 +3,11 @@ package indexer
import ( import (
"fmt" "fmt"
errorsmod "cosmossdk.io/errors"
rpctypes "github.com/cerc-io/laconicd/rpc/types" rpctypes "github.com/cerc-io/laconicd/rpc/types"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante" authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
@ -110,12 +110,12 @@ func (kv *KVIndexer) IndexBlock(block *tmtypes.Block, txResults []*abci.Response
ethTxIndex++ ethTxIndex++
if err := saveTxResult(kv.clientCtx.Codec, batch, txHash, &txResult); err != nil { if err := saveTxResult(kv.clientCtx.Codec, batch, txHash, &txResult); err != nil {
return sdkerrors.Wrapf(err, "IndexBlock %d", height) return errorsmod.Wrapf(err, "IndexBlock %d", height)
} }
} }
} }
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
return sdkerrors.Wrapf(err, "IndexBlock %d, write batch", block.Height) return errorsmod.Wrapf(err, "IndexBlock %d, write batch", block.Height)
} }
return nil return nil
} }
@ -134,14 +134,14 @@ func (kv *KVIndexer) FirstIndexedBlock() (int64, error) {
func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) { func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) {
bz, err := kv.db.Get(TxHashKey(hash)) bz, err := kv.db.Get(TxHashKey(hash))
if err != nil { if err != nil {
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex()) return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
} }
if len(bz) == 0 { if len(bz) == 0 {
return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex()) return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex())
} }
var txKey ethermint.TxResult var txKey ethermint.TxResult
if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil { if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil {
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex()) return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
} }
return &txKey, nil return &txKey, nil
} }
@ -150,7 +150,7 @@ func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error)
func (kv *KVIndexer) GetByBlockAndIndex(blockNumber int64, txIndex int32) (*ethermint.TxResult, error) { func (kv *KVIndexer) GetByBlockAndIndex(blockNumber int64, txIndex int32) (*ethermint.TxResult, error) {
bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex)) bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex))
if err != nil { if err != nil {
return nil, sdkerrors.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex) return nil, errorsmod.Wrapf(err, "GetByBlockAndIndex %d %d", blockNumber, txIndex)
} }
if len(bz) == 0 { if len(bz) == 0 {
return nil, fmt.Errorf("tx not found, block: %d, eth-index: %d", blockNumber, txIndex) return nil, fmt.Errorf("tx not found, block: %d, eth-index: %d", blockNumber, txIndex)
@ -174,7 +174,7 @@ func TxIndexKey(blockNumber int64, txIndex int32) []byte {
func LoadLastBlock(db dbm.DB) (int64, error) { func LoadLastBlock(db dbm.DB) (int64, error) {
it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1}) it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
if err != nil { if err != nil {
return 0, sdkerrors.Wrap(err, "LoadLastBlock") return 0, errorsmod.Wrap(err, "LoadLastBlock")
} }
defer it.Close() defer it.Close()
if !it.Valid() { if !it.Valid() {
@ -187,7 +187,7 @@ func LoadLastBlock(db dbm.DB) (int64, error) {
func LoadFirstBlock(db dbm.DB) (int64, error) { func LoadFirstBlock(db dbm.DB) (int64, error) {
it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1}) it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
if err != nil { if err != nil {
return 0, sdkerrors.Wrap(err, "LoadFirstBlock") return 0, errorsmod.Wrap(err, "LoadFirstBlock")
} }
defer it.Close() defer it.Close()
if !it.Valid() { if !it.Valid() {
@ -213,10 +213,10 @@ func isEthTx(tx sdk.Tx) bool {
func saveTxResult(codec codec.Codec, batch dbm.Batch, txHash common.Hash, txResult *ethermint.TxResult) error { func saveTxResult(codec codec.Codec, batch dbm.Batch, txHash common.Hash, txResult *ethermint.TxResult) error {
bz := codec.MustMarshal(txResult) bz := codec.MustMarshal(txResult)
if err := batch.Set(TxHashKey(txHash), bz); err != nil { if err := batch.Set(TxHashKey(txHash), bz); err != nil {
return sdkerrors.Wrap(err, "set tx-hash key") return errorsmod.Wrap(err, "set tx-hash key")
} }
if err := batch.Set(TxIndexKey(txResult.Height, txResult.EthTxIndex), txHash.Bytes()); err != nil { if err := batch.Set(TxIndexKey(txResult.Height, txResult.EthTxIndex), txHash.Bytes()); err != nil {
return sdkerrors.Wrap(err, "set tx-index key") return errorsmod.Wrap(err, "set tx-index key")
} }
return nil return nil
} }

View File

@ -1,12 +1,12 @@
#!/bin/bash #!/bin/bash
KEY="mykey" KEY="mykey"
CHAINID="ethermint_9000-1" CHAINID="laconic_2345678-1"
MONIKER="localtestnet" MONIKER="localtestnet"
KEYRING="test" KEYRING="test"
KEYALGO="eth_secp256k1" KEYALGO="eth_secp256k1"
LOGLEVEL="info" LOGLEVEL="info"
# to trace evm # trace evm
TRACE="--trace" TRACE="--trace"
# TRACE="" # TRACE=""

5
mlc_config.json Normal file
View File

@ -0,0 +1,5 @@
{
"retryOn429": true,
"retryCount": 3,
"fallbackRetryDelay": "20s"
}

View File

@ -15,7 +15,7 @@ COPY . .
RUN make build-linux RUN make build-linux
# Final image # Final image
FROM golang:1.18 as final FROM golang:1.19 as final
WORKDIR / WORKDIR /

View File

@ -27,7 +27,7 @@ import sources.nixpkgs {
dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; }; dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; };
}; };
}) })
(_: pkgs: { test-env = import ./testenv.nix { inherit pkgs; }; }) (_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; })
(_: pkgs: { (_: pkgs: {
cosmovisor = pkgs.buildGo118Module rec { cosmovisor = pkgs.buildGo118Module rec {
name = "cosmovisor"; name = "cosmovisor";

View File

@ -1,4 +1,4 @@
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit }: { lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit, nixosTests }:
let let
# A list of binaries to put into separate outputs # A list of binaries to put into separate outputs
@ -7,19 +7,18 @@ let
"clef" "clef"
]; ];
in in buildGoModule rec {
buildGoModule rec {
pname = "go-ethereum"; pname = "go-ethereum";
version = "1.10.19"; version = "1.10.25";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "ethereum"; owner = "ethereum";
repo = pname; repo = pname;
rev = "v${version}"; rev = "v${version}";
sha256 = "0f6n9rg42ph47mvykc9f0lf99yzwqy4jm7mlzyks4l6i6fl1g3q1"; sha256 = "sha256-mnf0kMfQEEQMricZJfyF7ZB/2F1dyPBx9iT2v/rGh1U=";
}; };
vendorSha256 = "1s5yfpk2yn7f3zwjl2fdrh6c63ki2b8rlmnlss27yxibsidaj0yd"; vendorSha256 = "sha256-Dj+xN8lr98LJyYr2FwJ7yUIJkUeUrr1fkcbj4hShJI0=";
doCheck = false; doCheck = false;
@ -47,14 +46,19 @@ buildGoModule rec {
"cmd/utils" "cmd/utils"
]; ];
# Following upstream: https://github.com/ethereum/go-ethereum/blob/v1.10.25/build/ci.go#L218
tags = [ "urfave_cli_no_docs" ];
# Fix for usb-related segmentation faults on darwin # Fix for usb-related segmentation faults on darwin
propagatedBuildInputs = propagatedBuildInputs =
lib.optionals stdenv.isDarwin [ libobjc IOKit ]; lib.optionals stdenv.isDarwin [ libobjc IOKit ];
passthru.tests = { inherit (nixosTests) geth; };
meta = with lib; { meta = with lib; {
homepage = "https://geth.ethereum.org/"; homepage = "https://geth.ethereum.org/";
description = "Official golang implementation of the Ethereum protocol"; description = "Official golang implementation of the Ethereum protocol";
license = with licenses; [ lgpl3Plus gpl3Plus ]; license = with licenses; [ lgpl3Plus gpl3Plus ];
maintainers = with maintainers; [ adisbladis lionello RaghavSood ]; maintainers = with maintainers; [ adisbladis RaghavSood ];
}; };
} }

50
nix/sources.json Normal file
View File

@ -0,0 +1,50 @@
{
"cosmos-sdk": {
"branch": "main",
"description": ":chains: A Framework for Building High Value Public Blockchains :sparkles:",
"homepage": "https://cosmos.network/",
"owner": "cosmos",
"repo": "cosmos-sdk",
"rev": "b6c77e6c819f8a51166649eaef125d1bfb276f04",
"sha256": "09ns4yfxyfi7c7n5g69zv32m1rdssdl48c1akmv1y2vz6ayz4v02",
"type": "tarball",
"url": "https://github.com/cosmos/cosmos-sdk/archive/b6c77e6c819f8a51166649eaef125d1bfb276f04.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"gomod2nix": {
"branch": "master",
"description": "Convert applications using Go modules to Nix expressions",
"homepage": null,
"owner": "tweag",
"repo": "gomod2nix",
"rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58",
"sha256": "0li17ynbg2wg0xqy655m5rmcw905sbv7d4ir35z7s5pg1yhhzxkp",
"type": "tarball",
"url": "https://github.com/tweag/gomod2nix/archive/40d32f82fc60d66402eb0972e6e368aeab3faf58.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"niv": {
"branch": "master",
"description": "Easy dependency management for Nix projects",
"homepage": "https://github.com/nmattia/niv",
"owner": "nmattia",
"repo": "niv",
"rev": "e0ca65c81a2d7a4d82a189f1e23a48d59ad42070",
"sha256": "1pq9nh1d8nn3xvbdny8fafzw87mj7gsmp6pxkdl65w2g18rmcmzx",
"type": "tarball",
"url": "https://github.com/nmattia/niv/archive/e0ca65c81a2d7a4d82a189f1e23a48d59ad42070.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixpkgs": {
"branch": "master",
"description": "Nix Packages collection",
"homepage": "",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ea2c6a6dda1aa35a80139a512a9dee375b0946e7",
"sha256": "0nd4nn9ryqa80ssw3j2kmr8wa73p2xz1hyxp280cdzqlmdfgw1lm",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/ea2c6a6dda1aa35a80139a512a9dee375b0946e7.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

View File

@ -1,18 +1,38 @@
{ pkgs }: { poetry2nix, lib, python310 }:
pkgs.poetry2nix.mkPoetryEnv { poetry2nix.mkPoetryEnv {
projectDir = ../tests/integration_tests; projectDir = ../tests/integration_tests;
python = pkgs.python39; python = python310;
overrides = pkgs.poetry2nix.overrides.withDefaults (self: super: { overrides = poetry2nix.overrides.withDefaults (lib.composeManyExtensions [
(self: super:
let
buildSystems = {
eth-bloom = [ "setuptools" ];
pystarport = [ "poetry" ];
durations = [ "setuptools" ];
multitail2 = [ "setuptools" ];
pytest-github-actions-annotate-failures = [ "setuptools" ];
flake8-black = [ "setuptools" ];
multiaddr = [ "setuptools" ];
};
in
lib.mapAttrs
(attr: systems: super.${attr}.overridePythonAttrs
(old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ map (a: self.${a}) systems;
}))
buildSystems
)
(self: super: {
eth-bloom = super.eth-bloom.overridePythonAttrs { eth-bloom = super.eth-bloom.overridePythonAttrs {
preConfigure = '' preConfigure = ''
substituteInPlace setup.py --replace \'setuptools-markdown\' "" substituteInPlace setup.py --replace \'setuptools-markdown\' ""
''; '';
}; };
pyyaml-include = super.pyyaml-include.overridePythonAttrs {
pystarport = super.pystarport.overridePythonAttrs ( preConfigure = ''
old: { substituteInPlace setup.py --replace "setup()" "setup(version=\"1.3\")"
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.poetry ]; '';
} };
); })
}); ]);
} }

8
proto/buf.gen.gogo.yaml Normal file
View File

@ -0,0 +1,8 @@
version: v1
plugins:
- name: gocosmos
out: .
opt: plugins=grpc,google/protobuf/duration.proto=google/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/orm/v1alpha1/orm.proto=github.com/cosmos/cosmos-sdk/api/cosmos/orm/v1alpha1
- name: grpc-gateway
out: .
opt: logtostderr=true,allow_colon_final_segments=true

View File

@ -0,0 +1,15 @@
version: v1
plugins:
- name: gocosmos
out: .
opt: plugins=grpc,google/protobuf/duration.proto=google/protobuf/duration.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/wrappers.proto=github.com/gogo/protobuf/types,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/orm/v1alpha1/orm.proto=github.com/cosmos/cosmos-sdk/api/cosmos/orm/v1alpha1
- name: grpc-gateway
out: .
opt: logtostderr=true
- name: swagger
out: ./tmp-swagger-gen
opt:
- logtostderr=true
- fqn_for_swagger_name=true
- simple_operation_ids=true
strategy: all

19
proto/buf.lock Normal file
View File

@ -0,0 +1,19 @@
# Generated by buf. DO NOT EDIT.
version: v1
deps:
- remote: buf.build
owner: cosmos
repository: cosmos-proto
commit: 1935555c206d4afb9e94615dfd0fad31
- remote: buf.build
owner: cosmos
repository: cosmos-sdk
commit: 508e19f5f37549e3a471a2a59b903c00
- remote: buf.build
owner: cosmos
repository: gogo-proto
commit: 34d970b699f84aa382f3c29773a60836
- remote: buf.build
owner: googleapis
repository: googleapis
commit: 783e4b5374fa488ab068d08af9658438

View File

@ -1,4 +1,10 @@
version: v1 version: v1
name: buf.build/cerc-io/laconicd
deps:
- buf.build/cosmos/cosmos-sdk
- buf.build/cosmos/cosmos-proto
- buf.build/cosmos/gogo-proto
- buf.build/googleapis/googleapis
lint: lint:
use: use:
- DEFAULT - DEFAULT

View File

@ -11,11 +11,13 @@ option go_package = "github.com/cerc-io/laconicd/crypto/ethsecp256k1";
message PubKey { message PubKey {
option (gogoproto.goproto_stringer) = false; option (gogoproto.goproto_stringer) = false;
// key is the public key in byte form
bytes key = 1; bytes key = 1;
} }
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements // PrivKey defines a type alias for an ecdsa.PrivateKey that implements
// Tendermint's PrivateKey interface. // Tendermint's PrivateKey interface.
message PrivKey { message PrivKey {
// key is the private key in byte form
bytes key = 1; bytes key = 1;
} }

View File

@ -7,18 +7,18 @@ option go_package = "github.com/cerc-io/laconicd/x/evm/types";
// Params defines the EVM module parameters // Params defines the EVM module parameters
message Params { message Params {
// evm denom represents the token denomination used to run the EVM state // evm_denom represents the token denomination used to run the EVM state
// transitions. // transitions.
string evm_denom = 1 [(gogoproto.moretags) = "yaml:\"evm_denom\""]; string evm_denom = 1 [(gogoproto.moretags) = "yaml:\"evm_denom\""];
// enable create toggles state transitions that use the vm.Create function // enable_create toggles state transitions that use the vm.Create function
bool enable_create = 2 [(gogoproto.moretags) = "yaml:\"enable_create\""]; bool enable_create = 2 [(gogoproto.moretags) = "yaml:\"enable_create\""];
// enable call toggles state transitions that use the vm.Call function // enable_call toggles state transitions that use the vm.Call function
bool enable_call = 3 [(gogoproto.moretags) = "yaml:\"enable_call\""]; bool enable_call = 3 [(gogoproto.moretags) = "yaml:\"enable_call\""];
// extra eips defines the additional EIPs for the vm.Config // extra_eips defines the additional EIPs for the vm.Config
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""]; repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
// chain config defines the EVM chain configuration parameters // chain_config defines the EVM chain configuration parameters
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false]; ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
// Allow unprotected transactions defines if replay-protected (i.e non EIP155 // allow_unprotected_txs defines if replay-protected (i.e non EIP155
// signed) transactions can be executed on the state machine. // signed) transactions can be executed on the state machine.
bool allow_unprotected_txs = 6; bool allow_unprotected_txs = 6;
} }
@ -26,67 +26,67 @@ message Params {
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values // ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
// instead of *big.Int. // instead of *big.Int.
message ChainConfig { message ChainConfig {
// Homestead switch block (nil no fork, 0 = already homestead) // homestead_block switch (nil no fork, 0 = already homestead)
string homestead_block = 1 [ string homestead_block = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"homestead_block\"" (gogoproto.moretags) = "yaml:\"homestead_block\""
]; ];
// TheDAO hard-fork switch block (nil no fork) // dao_fork_block corresponds to TheDAO hard-fork switch block (nil no fork)
string dao_fork_block = 2 [ string dao_fork_block = 2 [
(gogoproto.customname) = "DAOForkBlock", (gogoproto.customname) = "DAOForkBlock",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"dao_fork_block\"" (gogoproto.moretags) = "yaml:\"dao_fork_block\""
]; ];
// Whether the nodes supports or opposes the DAO hard-fork // dao_fork_support defines whether the nodes supports or opposes the DAO hard-fork
bool dao_fork_support = 3 bool dao_fork_support = 3
[(gogoproto.customname) = "DAOForkSupport", (gogoproto.moretags) = "yaml:\"dao_fork_support\""]; [(gogoproto.customname) = "DAOForkSupport", (gogoproto.moretags) = "yaml:\"dao_fork_support\""];
// EIP150 implements the Gas price changes // eip150_block: EIP150 implements the Gas price changes
// (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork) // (https://github.com/ethereum/EIPs/issues/150) EIP150 HF block (nil no fork)
string eip150_block = 4 [ string eip150_block = 4 [
(gogoproto.customname) = "EIP150Block", (gogoproto.customname) = "EIP150Block",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"eip150_block\"" (gogoproto.moretags) = "yaml:\"eip150_block\""
]; ];
// EIP150 HF hash (needed for header only clients as only gas pricing changed) // eip150_hash: EIP150 HF hash (needed for header only clients as only gas pricing changed)
string eip150_hash = 5 [(gogoproto.customname) = "EIP150Hash", (gogoproto.moretags) = "yaml:\"byzantium_block\""]; string eip150_hash = 5 [(gogoproto.customname) = "EIP150Hash", (gogoproto.moretags) = "yaml:\"byzantium_block\""];
// EIP155Block HF block // eip155_block: EIP155Block HF block
string eip155_block = 6 [ string eip155_block = 6 [
(gogoproto.customname) = "EIP155Block", (gogoproto.customname) = "EIP155Block",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"eip155_block\"" (gogoproto.moretags) = "yaml:\"eip155_block\""
]; ];
// EIP158 HF block // eip158_block: EIP158 HF block
string eip158_block = 7 [ string eip158_block = 7 [
(gogoproto.customname) = "EIP158Block", (gogoproto.customname) = "EIP158Block",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"eip158_block\"" (gogoproto.moretags) = "yaml:\"eip158_block\""
]; ];
// Byzantium switch block (nil no fork, 0 = already on byzantium) // byzantium_block: Byzantium switch block (nil no fork, 0 = already on byzantium)
string byzantium_block = 8 [ string byzantium_block = 8 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"byzantium_block\"" (gogoproto.moretags) = "yaml:\"byzantium_block\""
]; ];
// Constantinople switch block (nil no fork, 0 = already activated) // constantinople_block: Constantinople switch block (nil no fork, 0 = already activated)
string constantinople_block = 9 [ string constantinople_block = 9 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"constantinople_block\"" (gogoproto.moretags) = "yaml:\"constantinople_block\""
]; ];
// Petersburg switch block (nil same as Constantinople) // petersburg_block: Petersburg switch block (nil same as Constantinople)
string petersburg_block = 10 [ string petersburg_block = 10 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"petersburg_block\"" (gogoproto.moretags) = "yaml:\"petersburg_block\""
]; ];
// Istanbul switch block (nil no fork, 0 = already on istanbul) // istanbul_block: Istanbul switch block (nil no fork, 0 = already on istanbul)
string istanbul_block = 11 [ string istanbul_block = 11 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"istanbul_block\"" (gogoproto.moretags) = "yaml:\"istanbul_block\""
]; ];
// Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated) // muir_glacier_block: Eip-2384 (bomb delay) switch block (nil no fork, 0 = already activated)
string muir_glacier_block = 12 [ string muir_glacier_block = 12 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"muir_glacier_block\"" (gogoproto.moretags) = "yaml:\"muir_glacier_block\""
]; ];
// Berlin switch block (nil = no fork, 0 = already on berlin) // berlin_block: Berlin switch block (nil = no fork, 0 = already on berlin)
string berlin_block = 13 [ string berlin_block = 13 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"berlin_block\"" (gogoproto.moretags) = "yaml:\"berlin_block\""
@ -94,12 +94,12 @@ message ChainConfig {
// DEPRECATED: EWASM, YOLOV3 and Catalyst block have been deprecated // DEPRECATED: EWASM, YOLOV3 and Catalyst block have been deprecated
reserved 14, 15, 16; reserved 14, 15, 16;
reserved "yolo_v3_block", "ewasm_block", "catalyst_block"; reserved "yolo_v3_block", "ewasm_block", "catalyst_block";
// London switch block (nil = no fork, 0 = already on london) // london_block: London switch block (nil = no fork, 0 = already on london)
string london_block = 17 [ string london_block = 17 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"london_block\"" (gogoproto.moretags) = "yaml:\"london_block\""
]; ];
// Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) // arrow_glacier_block: Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated)
string arrow_glacier_block = 18 [ string arrow_glacier_block = 18 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"arrow_glacier_block\"" (gogoproto.moretags) = "yaml:\"arrow_glacier_block\""
@ -107,21 +107,34 @@ message ChainConfig {
// DEPRECATED: merge fork block was deprecated: https://github.com/ethereum/go-ethereum/pull/24904 // DEPRECATED: merge fork block was deprecated: https://github.com/ethereum/go-ethereum/pull/24904
reserved 19; reserved 19;
reserved "merge_fork_block"; reserved "merge_fork_block";
// EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated) // gray_glacier_block: EIP-5133 (bomb delay) switch block (nil = no fork, 0 = already activated)
string gray_glacier_block = 20 [ string gray_glacier_block = 20 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"gray_glacier_block\"" (gogoproto.moretags) = "yaml:\"gray_glacier_block\""
]; ];
// Virtual fork after The Merge to use as a network splitter // merge_netsplit_block: Virtual fork after The Merge to use as a network splitter
string merge_netsplit_block = 21 [ string merge_netsplit_block = 21 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"merge_netsplit_block\"" (gogoproto.moretags) = "yaml:\"merge_netsplit_block\""
]; ];
// shanghai_block switch block (nil = no fork, 0 = already on shanghai)
string shanghai_block = 22 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"shanghai_block\""
];
// cancun_block switch block (nil = no fork, 0 = already on cancun)
string cancun_block = 23 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.moretags) = "yaml:\"cancun_block\""
];
} }
// State represents a single Storage key value pair item. // State represents a single Storage key value pair item.
message State { message State {
// key is the stored key
string key = 1; string key = 1;
// value is the stored value for the given key
string value = 2; string value = 2;
} }
@ -129,38 +142,38 @@ message State {
// with a given hash. It it used for import/export data as transactions are not // with a given hash. It it used for import/export data as transactions are not
// persisted on blockchain state after an upgrade. // persisted on blockchain state after an upgrade.
message TransactionLogs { message TransactionLogs {
// hash of the transaction
string hash = 1; string hash = 1;
// logs is an array of Logs for the given transaction hash
repeated Log logs = 2; repeated Log logs = 2;
} }
// Log represents an protobuf compatible Ethereum Log that defines a contract // Log represents an protobuf compatible Ethereum Log that defines a contract
// log event. These events are generated by the LOG opcode and stored/indexed by // log event. These events are generated by the LOG opcode and stored/indexed by
// the node. // the node.
//
// NOTE: address, topics and data are consensus fields. The rest of the fields
// are derived, i.e. filled in by the nodes, but not secured by consensus.
message Log { message Log {
// Consensus fields:
// address of the contract that generated the event // address of the contract that generated the event
string address = 1; string address = 1;
// list of topics provided by the contract. // topics is a list of topics provided by the contract.
repeated string topics = 2; repeated string topics = 2;
// supplied by the contract, usually ABI-encoded // data which is supplied by the contract, usually ABI-encoded
bytes data = 3; bytes data = 3;
// Derived fields. These fields are filled in by the node // block_number of the block in which the transaction was included
// but not secured by consensus.
// block in which the transaction was included
uint64 block_number = 4 [(gogoproto.jsontag) = "blockNumber"]; uint64 block_number = 4 [(gogoproto.jsontag) = "blockNumber"];
// hash of the transaction // tx_hash is the transaction hash
string tx_hash = 5 [(gogoproto.jsontag) = "transactionHash"]; string tx_hash = 5 [(gogoproto.jsontag) = "transactionHash"];
// index of the transaction in the block // tx_index of the transaction in the block
uint64 tx_index = 6 [(gogoproto.jsontag) = "transactionIndex"]; uint64 tx_index = 6 [(gogoproto.jsontag) = "transactionIndex"];
// hash of the block in which the transaction was included // block_hash of the block in which the transaction was included
string block_hash = 7 [(gogoproto.jsontag) = "blockHash"]; string block_hash = 7 [(gogoproto.jsontag) = "blockHash"];
// index of the log in the block // index of the log in the block
uint64 index = 8 [(gogoproto.jsontag) = "logIndex"]; uint64 index = 8 [(gogoproto.jsontag) = "logIndex"];
// The Removed field is true if this log was reverted due to a chain // removed is true if this log was reverted due to a chain
// reorganisation. You must pay attention to this field if you receive logs // reorganisation. You must pay attention to this field if you receive logs
// through a filter query. // through a filter query.
bool removed = 9; bool removed = 9;
@ -191,9 +204,9 @@ message TxResult {
message AccessTuple { message AccessTuple {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
// hex formatted ethereum address // address is a hex formatted ethereum address
string address = 1; string address = 1;
// hex formatted hashes of the storage keys // storage_keys are hex formatted hashes of the storage keys
repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"]; repeated string storage_keys = 2 [(gogoproto.jsontag) = "storageKeys"];
} }
@ -204,25 +217,27 @@ message TraceConfig {
reserved 4, 7; reserved 4, 7;
reserved "disable_memory", "disable_return_data"; reserved "disable_memory", "disable_return_data";
// custom javascript tracer // tracer is a custom javascript tracer
string tracer = 1; string tracer = 1;
// overrides the default timeout of 5 seconds for JavaScript-based tracing // timeout overrides the default timeout of 5 seconds for JavaScript-based tracing
// calls // calls
string timeout = 2; string timeout = 2;
// number of blocks the tracer is willing to go back // reexec defines the number of blocks the tracer is willing to go back
uint64 reexec = 3; uint64 reexec = 3;
// disable stack capture // disable_stack switches stack capture
bool disable_stack = 5 [(gogoproto.jsontag) = "disableStack"]; bool disable_stack = 5 [(gogoproto.jsontag) = "disableStack"];
// disable storage capture // disable_storage switches storage capture
bool disable_storage = 6 [(gogoproto.jsontag) = "disableStorage"]; bool disable_storage = 6 [(gogoproto.jsontag) = "disableStorage"];
// print output during capture end // debug can be used to print output during capture end
bool debug = 8; bool debug = 8;
// maximum length of output, but zero means unlimited // limit defines the maximum length of output, but zero means unlimited
int32 limit = 9; int32 limit = 9;
// Chain overrides, can be used to execute a trace using future fork rules // overrides can be used to execute a trace using future fork rules
ChainConfig overrides = 10; ChainConfig overrides = 10;
// enable memory capture // enable_memory switches memory capture
bool enable_memory = 11 [(gogoproto.jsontag) = "enableMemory"]; bool enable_memory = 11 [(gogoproto.jsontag) = "enableMemory"];
// enable return data capture // enable_return_data switches the capture of return data
bool enable_return_data = 12 [(gogoproto.jsontag) = "enableReturnData"]; bool enable_return_data = 12 [(gogoproto.jsontag) = "enableReturnData"];
// tracer_json_config configures the tracer using a JSON string
string tracer_json_config = 13 [(gogoproto.jsontag) = "tracerConfig"];
} }

View File

@ -1,8 +1,8 @@
syntax = "proto3"; syntax = "proto3";
package ethermint.evm.v1; package ethermint.evm.v1;
import "gogoproto/gogo.proto";
import "ethermint/evm/v1/evm.proto"; import "ethermint/evm/v1/evm.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/cerc-io/laconicd/x/evm/types"; option go_package = "github.com/cerc-io/laconicd/x/evm/types";

View File

@ -1,11 +1,11 @@
syntax = "proto3"; syntax = "proto3";
package ethermint.evm.v1; package ethermint.evm.v1;
import "gogoproto/gogo.proto";
import "cosmos/base/query/v1beta1/pagination.proto"; import "cosmos/base/query/v1beta1/pagination.proto";
import "google/api/annotations.proto";
import "ethermint/evm/v1/evm.proto"; import "ethermint/evm/v1/evm.proto";
import "ethermint/evm/v1/tx.proto"; import "ethermint/evm/v1/tx.proto";
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto"; import "google/protobuf/timestamp.proto";
option go_package = "github.com/cerc-io/laconicd/x/evm/types"; option go_package = "github.com/cerc-io/laconicd/x/evm/types";
@ -89,7 +89,7 @@ message QueryAccountRequest {
message QueryAccountResponse { message QueryAccountResponse {
// balance is the balance of the EVM denomination. // balance is the balance of the EVM denomination.
string balance = 1; string balance = 1;
// code hash is the hex-formatted code bytes from the EOA. // code_hash is the hex-formatted code bytes from the EOA.
string code_hash = 2; string code_hash = 2;
// nonce is the account's sequence number. // nonce is the account's sequence number.
uint64 nonce = 3; uint64 nonce = 3;
@ -112,7 +112,7 @@ message QueryCosmosAccountResponse {
string cosmos_address = 1; string cosmos_address = 1;
// sequence is the account's sequence number. // sequence is the account's sequence number.
uint64 sequence = 2; uint64 sequence = 2;
// account_number is the account numbert // account_number is the account number
uint64 account_number = 3; uint64 account_number = 3;
} }
@ -157,7 +157,7 @@ message QueryStorageRequest {
option (gogoproto.equal) = false; option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
/// address is the ethereum hex address to query the storage state for. // address is the ethereum hex address to query the storage state for.
string address = 1; string address = 1;
// key defines the key of the storage state // key defines the key of the storage state
@ -167,7 +167,7 @@ message QueryStorageRequest {
// QueryStorageResponse is the response type for the Query/Storage RPC // QueryStorageResponse is the response type for the Query/Storage RPC
// method. // method.
message QueryStorageResponse { message QueryStorageResponse {
// key defines the storage state value hash associated with the given key. // value defines the storage state value hash associated with the given key.
string value = 1; string value = 1;
} }
@ -198,7 +198,7 @@ message QueryTxLogsRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 2; cosmos.base.query.v1beta1.PageRequest pagination = 2;
} }
// QueryTxLogs is the response type for the Query/TxLogs RPC method. // QueryTxLogsResponse is the response type for the Query/TxLogs RPC method.
message QueryTxLogsResponse { message QueryTxLogsResponse {
// logs represents the ethereum logs generated from the given transaction. // logs represents the ethereum logs generated from the given transaction.
repeated Log logs = 1; repeated Log logs = 1;
@ -217,60 +217,73 @@ message QueryParamsResponse {
// EthCallRequest defines EthCall request // EthCallRequest defines EthCall request
message EthCallRequest { message EthCallRequest {
// same json format as the json rpc api. // args uses the same json format as the json rpc api.
bytes args = 1; bytes args = 1;
// the default gas cap to be used // gas_cap defines the default gas cap to be used
uint64 gas_cap = 2; uint64 gas_cap = 2;
// proposer_address of the requested block in hex format
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// chain_id is the eip155 chain id parsed from the requested block header
int64 chain_id = 4;
} }
// EstimateGasResponse defines EstimateGas response // EstimateGasResponse defines EstimateGas response
message EstimateGasResponse { message EstimateGasResponse {
// the estimated gas // gas returns the estimated gas
uint64 gas = 1; uint64 gas = 1;
} }
// QueryTraceTxRequest defines TraceTx request // QueryTraceTxRequest defines TraceTx request
message QueryTraceTxRequest { message QueryTraceTxRequest {
// msgEthereumTx for the requested transaction // msg is the MsgEthereumTx for the requested transaction
MsgEthereumTx msg = 1; MsgEthereumTx msg = 1;
// tx_index is not necessary anymore // tx_index is not necessary anymore
reserved 2; reserved 2;
reserved "tx_index"; reserved "tx_index";
// TraceConfig holds extra parameters to trace functions. // trace_config holds extra parameters to trace functions.
TraceConfig trace_config = 3; TraceConfig trace_config = 3;
// the predecessor transactions included in the same block // predecessors is an array of transactions included in the same block
// need to be replayed first to get correct context for tracing. // need to be replayed first to get correct context for tracing.
repeated MsgEthereumTx predecessors = 4; repeated MsgEthereumTx predecessors = 4;
// block number of requested transaction // block_number of requested transaction
int64 block_number = 5; int64 block_number = 5;
// block hex hash of requested transaction // block_hash of requested transaction
string block_hash = 6; string block_hash = 6;
// block time of requested transaction // block_time of requested transaction
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// proposer_address is the proposer of the requested block
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// chain_id is the the eip155 chain id parsed from the requested block header
int64 chain_id = 9;
} }
// QueryTraceTxResponse defines TraceTx response // QueryTraceTxResponse defines TraceTx response
message QueryTraceTxResponse { message QueryTraceTxResponse {
// response serialized in bytes // data is the response serialized in bytes
bytes data = 1; bytes data = 1;
} }
// QueryTraceBlockRequest defines TraceTx request // QueryTraceBlockRequest defines TraceTx request
message QueryTraceBlockRequest { message QueryTraceBlockRequest {
// txs messages in the block // txs is an array of messages in the block
repeated MsgEthereumTx txs = 1; repeated MsgEthereumTx txs = 1;
// TraceConfig holds extra parameters to trace functions. // trace_config holds extra parameters to trace functions.
TraceConfig trace_config = 3; TraceConfig trace_config = 3;
// block number // block_number of the traced block
int64 block_number = 5; int64 block_number = 5;
// block hex hash // block_hash (hex) of the traced block
string block_hash = 6; string block_hash = 6;
// block time // block_time of the traced block
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// proposer_address is the address of the requested block
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// chain_id is the eip155 chain id parsed from the requested block header
int64 chain_id = 9;
} }
// QueryTraceBlockResponse defines TraceBlock response // QueryTraceBlockResponse defines TraceBlock response
message QueryTraceBlockResponse { message QueryTraceBlockResponse {
// data is the response serialized in bytes
bytes data = 1; bytes data = 1;
} }
@ -278,7 +291,8 @@ message QueryTraceBlockResponse {
// fee. // fee.
message QueryBaseFeeRequest {} message QueryBaseFeeRequest {}
// BaseFeeResponse returns the EIP1559 base fee. // QueryBaseFeeResponse returns the EIP1559 base fee.
message QueryBaseFeeResponse { message QueryBaseFeeResponse {
// base_fee is the EIP1559 base fee
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
} }

View File

@ -1,11 +1,11 @@
syntax = "proto3"; syntax = "proto3";
package ethermint.evm.v1; package ethermint.evm.v1;
import "cosmos_proto/cosmos.proto";
import "ethermint/evm/v1/evm.proto";
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "google/api/annotations.proto"; import "google/api/annotations.proto";
import "google/protobuf/any.proto"; import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
import "ethermint/evm/v1/evm.proto";
option go_package = "github.com/cerc-io/laconicd/x/evm/types"; option go_package = "github.com/cerc-io/laconicd/x/evm/types";
@ -21,15 +21,14 @@ service Msg {
message MsgEthereumTx { message MsgEthereumTx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
// inner transaction data // data is inner transaction data of the Ethereum transaction
google.protobuf.Any data = 1; google.protobuf.Any data = 1;
// caches
// DEPRECATED: encoded storage size of the transaction // size is the encoded storage size of the transaction (DEPRECATED)
double size = 2 [(gogoproto.jsontag) = "-"]; double size = 2 [(gogoproto.jsontag) = "-"];
// transaction hash in hex format // hash of the transaction in hex format
string hash = 3 [(gogoproto.moretags) = "rlp:\"-\""]; string hash = 3 [(gogoproto.moretags) = "rlp:\"-\""];
// ethereum signer address in hex format. This address value is checked // from is the ethereum signer address in hex format. This address value is checked
// against the address derived from the signature (V, R, S) using the // against the address derived from the signature (V, R, S) using the
// secp256k1 elliptic curve // secp256k1 elliptic curve
string from = 4; string from = 4;
@ -44,16 +43,16 @@ message LegacyTx {
// nonce corresponds to the account nonce (transaction sequence). // nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 1; uint64 nonce = 1;
// gas price defines the value for each gas unit // gas_price defines the value for each gas unit
string gas_price = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string gas_price = 2 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
// gas defines the gas limit defined for the transaction. // gas defines the gas limit defined for the transaction.
uint64 gas = 3 [(gogoproto.customname) = "GasLimit"]; uint64 gas = 3 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient // to is the hex formatted address of the recipient
string to = 4; string to = 4;
// value defines the unsigned integer value of the transaction amount. // value defines the unsigned integer value of the transaction amount.
string value = 5 string value = 5
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"]; [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
// input defines the data payload bytes of the transaction. // data is the data payload bytes of the transaction.
bytes data = 6; bytes data = 6;
// v defines the signature value // v defines the signature value
bytes v = 7; bytes v = 7;
@ -68,7 +67,7 @@ message AccessListTx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
option (cosmos_proto.implements_interface) = "TxData"; option (cosmos_proto.implements_interface) = "TxData";
// destination EVM chain ID // chain_id of the destination EVM chain
string chain_id = 1 [ string chain_id = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "ChainID", (gogoproto.customname) = "ChainID",
@ -76,17 +75,18 @@ message AccessListTx {
]; ];
// nonce corresponds to the account nonce (transaction sequence). // nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 2; uint64 nonce = 2;
// gas price defines the value for each gas unit // gas_price defines the value for each gas unit
string gas_price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string gas_price = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
// gas defines the gas limit defined for the transaction. // gas defines the gas limit defined for the transaction.
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"]; uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient // to is the recipient address in hex format
string to = 5; string to = 5;
// value defines the unsigned integer value of the transaction amount. // value defines the unsigned integer value of the transaction amount.
string value = 6 string value = 6
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"]; [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
// input defines the data payload bytes of the transaction. // data is the data payload bytes of the transaction.
bytes data = 7; bytes data = 7;
// accesses is an array of access tuples
repeated AccessTuple accesses = 8 repeated AccessTuple accesses = 8
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false]; [(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
// v defines the signature value // v defines the signature value
@ -102,7 +102,7 @@ message DynamicFeeTx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
option (cosmos_proto.implements_interface) = "TxData"; option (cosmos_proto.implements_interface) = "TxData";
// destination EVM chain ID // chain_id of the destination EVM chain
string chain_id = 1 [ string chain_id = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.customname) = "ChainID", (gogoproto.customname) = "ChainID",
@ -110,19 +110,20 @@ message DynamicFeeTx {
]; ];
// nonce corresponds to the account nonce (transaction sequence). // nonce corresponds to the account nonce (transaction sequence).
uint64 nonce = 2; uint64 nonce = 2;
// gas tip cap defines the max value for the gas tip // gas_tip_cap defines the max value for the gas tip
string gas_tip_cap = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string gas_tip_cap = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
// gas fee cap defines the max value for the gas fee // gas_fee_cap defines the max value for the gas fee
string gas_fee_cap = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string gas_fee_cap = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
// gas defines the gas limit defined for the transaction. // gas defines the gas limit defined for the transaction.
uint64 gas = 5 [(gogoproto.customname) = "GasLimit"]; uint64 gas = 5 [(gogoproto.customname) = "GasLimit"];
// hex formatted address of the recipient // to is the hex formatted address of the recipient
string to = 6; string to = 6;
// value defines the the transaction amount. // value defines the the transaction amount.
string value = 7 string value = 7
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"]; [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.customname) = "Amount"];
// input defines the data payload bytes of the transaction. // data is the data payload bytes of the transaction.
bytes data = 8; bytes data = 8;
// accesses is an array of access tuples
repeated AccessTuple accesses = 9 repeated AccessTuple accesses = 9
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false]; [(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
// v defines the signature value // v defines the signature value
@ -133,6 +134,7 @@ message DynamicFeeTx {
bytes s = 12; bytes s = 12;
} }
// ExtensionOptionsEthereumTx is an extension option for ethereum transactions
message ExtensionOptionsEthereumTx { message ExtensionOptionsEthereumTx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
} }
@ -141,18 +143,18 @@ message ExtensionOptionsEthereumTx {
message MsgEthereumTxResponse { message MsgEthereumTxResponse {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
// ethereum transaction hash in hex format. This hash differs from the // hash of the ethereum transaction in hex format. This hash differs from the
// Tendermint sha256 hash of the transaction bytes. See // Tendermint sha256 hash of the transaction bytes. See
// https://github.com/tendermint/tendermint/issues/6539 for reference // https://github.com/tendermint/tendermint/issues/6539 for reference
string hash = 1; string hash = 1;
// logs contains the transaction hash and the proto-compatible ethereum // logs contains the transaction hash and the proto-compatible ethereum
// logs. // logs.
repeated Log logs = 2; repeated Log logs = 2;
// returned data from evm function (result or data supplied with revert // ret is the returned data from evm function (result or data supplied with revert
// opcode) // opcode)
bytes ret = 3; bytes ret = 3;
// vm error is the error returned by vm execution // vm_error is the error returned by vm execution
string vm_error = 4; string vm_error = 4;
// gas consumed by the transaction // gas_used specifies how much gas was consumed by the transaction
uint64 gas_used = 5; uint64 gas_used = 5;
} }

View File

@ -7,26 +7,26 @@ option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
// Params defines the EVM module parameters // Params defines the EVM module parameters
message Params { message Params {
// no base fee forces the EIP-1559 base fee to 0 (needed for 0 price calls) // no_base_fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
bool no_base_fee = 1; bool no_base_fee = 1;
// base fee change denominator bounds the amount the base fee can change // base_fee_change_denominator bounds the amount the base fee can change
// between blocks. // between blocks.
uint32 base_fee_change_denominator = 2; uint32 base_fee_change_denominator = 2;
// elasticity multiplier bounds the maximum gas limit an EIP-1559 block may // elasticity_multiplier bounds the maximum gas limit an EIP-1559 block may
// have. // have.
uint32 elasticity_multiplier = 3; uint32 elasticity_multiplier = 3;
// DEPRECATED: initial base fee for EIP-1559 blocks. // DEPRECATED: initial base fee for EIP-1559 blocks.
reserved 4; reserved 4;
reserved "initial_base_fee"; reserved "initial_base_fee";
// height at which the base fee calculation is enabled. // enable_height defines at which block height the base fee calculation is enabled.
int64 enable_height = 5; int64 enable_height = 5;
// base fee for EIP-1559 blocks. // base_fee for EIP-1559 blocks.
string base_fee = 6 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; string base_fee = 6 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false];
// min_gas_price defines the minimum gas price value for cosmos and eth transactions // min_gas_price defines the minimum gas price value for cosmos and eth transactions
string min_gas_price = 7 string min_gas_price = 7
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
// min gas denominator bounds the minimum gasUsed to be charged // min_gas_multiplier bounds the minimum gas used to be charged
// to senders based on GasLimit // to senders based on gas limit
string min_gas_multiplier = 8 string min_gas_multiplier = 8
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
} }

View File

@ -1,8 +1,8 @@
syntax = "proto3"; syntax = "proto3";
package ethermint.feemarket.v1; package ethermint.feemarket.v1;
import "gogoproto/gogo.proto";
import "ethermint/feemarket/v1/feemarket.proto"; import "ethermint/feemarket/v1/feemarket.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/cerc-io/laconicd/x/feemarket/types"; option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
@ -14,7 +14,7 @@ message GenesisState {
// Zero by default. // Zero by default.
reserved 2; reserved 2;
reserved "base_fee"; reserved "base_fee";
// block gas is the amount of gas wanted on the last block before the upgrade. // block_gas is the amount of gas wanted on the last block before the upgrade.
// Zero by default. // Zero by default.
uint64 block_gas = 3; uint64 block_gas = 3;
} }

View File

@ -3,8 +3,8 @@ package ethermint.feemarket.v1;
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
// import "cosmos/base/query/v1beta1/pagination.proto"; // import "cosmos/base/query/v1beta1/pagination.proto";
import "google/api/annotations.proto";
import "ethermint/feemarket/v1/feemarket.proto"; import "ethermint/feemarket/v1/feemarket.proto";
import "google/api/annotations.proto";
option go_package = "github.com/cerc-io/laconicd/x/feemarket/types"; option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
@ -39,8 +39,9 @@ message QueryParamsResponse {
// fee. // fee.
message QueryBaseFeeRequest {} message QueryBaseFeeRequest {}
// BaseFeeResponse returns the EIP1559 base fee. // QueryBaseFeeResponse returns the EIP1559 base fee.
message QueryBaseFeeResponse { message QueryBaseFeeResponse {
// base_fee is the EIP1559 base fee
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"]; string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
} }
@ -50,5 +51,6 @@ message QueryBlockGasRequest {}
// QueryBlockGasResponse returns block gas used for a given height. // QueryBlockGasResponse returns block gas used for a given height.
message QueryBlockGasResponse { message QueryBlockGasResponse {
// gas is the returned block gas
int64 gas = 1; int64 gas = 1;
} }

View File

@ -16,7 +16,10 @@ message EthAccount {
option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI"; option (cosmos_proto.implements_interface) = "github.com/cosmos/cosmos-sdk/x/auth/types.AccountI";
// base_account is an authtypes.BaseAccount
cosmos.auth.v1beta1.BaseAccount base_account = 1 cosmos.auth.v1beta1.BaseAccount base_account = 1
[(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""]; [(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"base_account\""];
// code_hash is the hash calculated from the code contents
string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""]; string code_hash = 2 [(gogoproto.moretags) = "yaml:\"code_hash\""];
} }

View File

@ -9,21 +9,22 @@ option go_package = "github.com/cerc-io/laconicd/types";
message TxResult { message TxResult {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
// the block height // height of the blockchain
int64 height = 1; int64 height = 1;
// cosmos tx index // tx_index of the cosmos transaction
uint32 tx_index = 2; uint32 tx_index = 2;
// the msg index in a batch tx // msg_index in a batch transaction
uint32 msg_index = 3; uint32 msg_index = 3;
// eth tx index, the index in the list of valid eth tx in the block, // eth_tx_index is the index in the list of valid eth tx in the block,
// aka. the transaction list returned by eth_getBlock api. // aka. the transaction list returned by eth_getBlock api.
int32 eth_tx_index = 4; int32 eth_tx_index = 4;
// if the eth tx is failed // failed is true if the eth transaction did not go succeed
bool failed = 5; bool failed = 5;
// gas used by tx, if exceeds block gas limit, // gas_used by the transaction. If it exceeds the block gas limit,
// it's set to gas limit which is what's actually deducted by ante handler. // it's set to gas limit, which is what's actually deducted by ante handler.
uint64 gas_used = 6; uint64 gas_used = 6;
// the cumulative gas used within current batch tx // cumulative_gas_used specifies the cumulated amount of gas used for all
// processed messages within the current batch transaction.
uint64 cumulative_gas_used = 7; uint64 cumulative_gas_used = 7;
} }

View File

@ -5,19 +5,21 @@ import "gogoproto/gogo.proto";
option go_package = "github.com/cerc-io/laconicd/types"; option go_package = "github.com/cerc-io/laconicd/types";
// ExtensionOptionsWeb3Tx is an extension option that specifies the typed chain id,
// the fee payer as well as its signature data.
message ExtensionOptionsWeb3Tx { message ExtensionOptionsWeb3Tx {
option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_getters) = false;
// typed data chain id used only in EIP712 Domain and should match // typed_data_chain_id is used only in EIP712 Domain and should match
// Ethereum network ID in a Web3 provider (e.g. Metamask). // Ethereum network ID in a Web3 provider (e.g. Metamask).
uint64 typed_data_chain_id = 1 uint64 typed_data_chain_id = 1
[(gogoproto.jsontag) = "typedDataChainID,omitempty", (gogoproto.customname) = "TypedDataChainID"]; [(gogoproto.jsontag) = "typedDataChainID,omitempty", (gogoproto.customname) = "TypedDataChainID"];
// fee payer is an account address for the fee payer. It will be validated // fee_payer is an account address for the fee payer. It will be validated
// during EIP712 signature checking. // during EIP712 signature checking.
string fee_payer = 2 [(gogoproto.jsontag) = "feePayer,omitempty"]; string fee_payer = 2 [(gogoproto.jsontag) = "feePayer,omitempty"];
// fee payer sig is a signature data from the fee paying account, // fee_payer_sig is a signature data from the fee paying account,
// allows to perform fee delegation when using EIP712 Domain. // allows to perform fee delegation when using EIP712 Domain.
bytes fee_payer_sig = 3 [(gogoproto.jsontag) = "feePayerSig,omitempty"]; bytes fee_payer_sig = 3 [(gogoproto.jsontag) = "feePayerSig,omitempty"];
} }

View File

@ -75,16 +75,10 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
return nil, err return nil, err
} }
// check for proof
var proofStr string
if proof != nil {
proofStr = proof.String()
}
storageProofs[i] = rpctypes.StorageResult{ storageProofs[i] = rpctypes.StorageResult{
Key: key, Key: key,
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)), Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
Proof: []string{proofStr}, Proof: GetHexProofs(proof),
} }
} }
@ -105,12 +99,6 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
return nil, err return nil, err
} }
// check for proof
var accProofStr string
if proof != nil {
accProofStr = proof.String()
}
balance, ok := sdkmath.NewIntFromString(res.Balance) balance, ok := sdkmath.NewIntFromString(res.Balance)
if !ok { if !ok {
return nil, errors.New("invalid balance") return nil, errors.New("invalid balance")
@ -118,7 +106,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
return &rpctypes.AccountResult{ return &rpctypes.AccountResult{
Address: address, Address: address,
AccountProof: []string{accProofStr}, AccountProof: GetHexProofs(proof),
Balance: (*hexutil.Big)(balance.BigInt()), Balance: (*hexutil.Big)(balance.BigInt()),
CodeHash: common.HexToHash(res.CodeHash), CodeHash: common.HexToHash(res.CodeHash),
Nonce: hexutil.Uint64(res.Nonce), Nonce: hexutil.Uint64(res.Nonce),

View File

@ -0,0 +1,408 @@
package backend
import (
"fmt"
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
"github.com/cerc-io/laconicd/rpc/backend/mocks"
rpctypes "github.com/cerc-io/laconicd/rpc/types"
"github.com/cerc-io/laconicd/tests"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
)
func (suite *BackendTestSuite) TestGetCode() {
blockNr := rpctypes.NewBlockNumber(big.NewInt(1))
contractCode := []byte("0xef616c92f3cfc9e92dc270d6acff9cea213cecc7020a76ee4395af09bdceb4837a1ebdb5735e11e7d3adb6104e0c3ac55180b4ddf5e54d022cc5e8837f6a4f971b")
testCases := []struct {
name string
addr common.Address
blockNrOrHash rpctypes.BlockNumberOrHash
registerMock func(common.Address)
expPass bool
expCode hexutil.Bytes
}{
{
"fail - BlockHash and BlockNumber are both nil ",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{},
func(addr common.Address) {},
false,
nil,
},
{
"fail - query client errors on getting Code",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(addr common.Address) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterCodeError(queryClient, addr)
},
false,
nil,
},
{
"pass",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(addr common.Address) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterCode(queryClient, addr, contractCode)
},
true,
contractCode,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset
tc.registerMock(tc.addr)
code, err := suite.backend.GetCode(tc.addr, tc.blockNrOrHash)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expCode, code)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetProof() {
blockNrInvalid := rpctypes.NewBlockNumber(big.NewInt(1))
blockNr := rpctypes.NewBlockNumber(big.NewInt(4))
address1 := tests.GenerateAddress()
testCases := []struct {
name string
addr common.Address
storageKeys []string
blockNrOrHash rpctypes.BlockNumberOrHash
registerMock func(rpctypes.BlockNumber, common.Address)
expPass bool
expAccRes *rpctypes.AccountResult
}{
{
"fail - BlockNumeber = 1 (invalidBlockNumber)",
address1,
[]string{},
rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterAccount(queryClient, addr, blockNrInvalid.Int64())
},
false,
&rpctypes.AccountResult{},
},
{
"fail - Block doesn't exist)",
address1,
[]string{},
rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, bn.Int64())
},
false,
&rpctypes.AccountResult{},
},
{
"pass",
address1,
[]string{"0x0"},
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
suite.backend.ctx = rpctypes.ContextWithHeight(bn.Int64())
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterAccount(queryClient, addr, bn.Int64())
// Use the IAVL height if a valid tendermint height is passed in.
ivalHeight := bn.Int64() - 1
RegisterABCIQueryWithOptions(
client,
bn.Int64(),
"store/evm/key",
evmtypes.StateKey(address1, common.HexToHash("0x0").Bytes()),
tmrpcclient.ABCIQueryOptions{Height: ivalHeight, Prove: true},
)
RegisterABCIQueryWithOptions(
client,
bn.Int64(),
"store/acc/key",
authtypes.AddressStoreKey(sdk.AccAddress(address1.Bytes())),
tmrpcclient.ABCIQueryOptions{Height: ivalHeight, Prove: true},
)
},
true,
&rpctypes.AccountResult{
Address: address1,
AccountProof: []string{""},
Balance: (*hexutil.Big)(big.NewInt(0)),
CodeHash: common.HexToHash(""),
Nonce: 0x0,
StorageHash: common.Hash{},
StorageProof: []rpctypes.StorageResult{
{
Key: "0x0",
Value: (*hexutil.Big)(big.NewInt(2)),
Proof: []string{""},
},
},
},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
tc.registerMock(*tc.blockNrOrHash.BlockNumber, tc.addr)
accRes, err := suite.backend.GetProof(tc.addr, tc.storageKeys, tc.blockNrOrHash)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expAccRes, accRes)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetStorageAt() {
blockNr := rpctypes.NewBlockNumber(big.NewInt(1))
testCases := []struct {
name string
addr common.Address
key string
blockNrOrHash rpctypes.BlockNumberOrHash
registerMock func(common.Address, string, string)
expPass bool
expStorage hexutil.Bytes
}{
{
"fail - BlockHash and BlockNumber are both nil",
tests.GenerateAddress(),
"0x0",
rpctypes.BlockNumberOrHash{},
func(addr common.Address, key string, storage string) {},
false,
nil,
},
{
"fail - query client errors on getting Storage",
tests.GenerateAddress(),
"0x0",
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(addr common.Address, key string, storage string) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterStorageAtError(queryClient, addr, key)
},
false,
nil,
},
{
"pass",
tests.GenerateAddress(),
"0x0",
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(addr common.Address, key string, storage string) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterStorageAt(queryClient, addr, key, storage)
},
true,
hexutil.Bytes{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
tc.registerMock(tc.addr, tc.key, tc.expStorage.String())
storage, err := suite.backend.GetStorageAt(tc.addr, tc.key, tc.blockNrOrHash)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expStorage, storage)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetBalance() {
blockNr := rpctypes.NewBlockNumber(big.NewInt(1))
testCases := []struct {
name string
addr common.Address
blockNrOrHash rpctypes.BlockNumberOrHash
registerMock func(rpctypes.BlockNumber, common.Address)
expPass bool
expBalance *hexutil.Big
}{
{
"fail - BlockHash and BlockNumber are both nil",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{},
func(bn rpctypes.BlockNumber, addr common.Address) {
},
false,
nil,
},
{
"fail - tendermint client failed to get block",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, bn.Int64())
},
false,
nil,
},
{
"fail - query client failed to get balance",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalanceError(queryClient, addr, bn.Int64())
},
false,
nil,
},
{
"fail - invalid balance",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalanceInvalid(queryClient, addr, bn.Int64())
},
false,
nil,
},
{
"fail - pruned node state",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalanceNegative(queryClient, addr, bn.Int64())
},
false,
nil,
},
{
"pass",
tests.GenerateAddress(),
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalance(queryClient, addr, bn.Int64())
},
true,
(*hexutil.Big)(big.NewInt(1)),
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
// avoid nil pointer reference
if tc.blockNrOrHash.BlockNumber != nil {
tc.registerMock(*tc.blockNrOrHash.BlockNumber, tc.addr)
}
balance, err := suite.backend.GetBalance(tc.addr, tc.blockNrOrHash)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expBalance, balance)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGetTransactionCount() {
testCases := []struct {
name string
accExists bool
blockNum rpctypes.BlockNumber
registerMock func(common.Address, rpctypes.BlockNumber)
expPass bool
expTxCount hexutil.Uint64
}{
{
"pass - account doesn't exist",
false,
rpctypes.NewBlockNumber(big.NewInt(1)),
func(addr common.Address, bn rpctypes.BlockNumber) {},
true,
hexutil.Uint64(0),
},
// TODO: Error mocking the GetAccount call - problem with Any type
//{
// "pass - returns the number of transactions at the given address up to the given block number",
// true,
// rpctypes.NewBlockNumber(big.NewInt(1)),
// func(addr common.Address, bn rpctypes.BlockNumber) {
// client := suite.backend.clientCtx.Client.(*mocks.Client)
// account, err := suite.backend.clientCtx.AccountRetriever.GetAccount(suite.backend.clientCtx, suite.acc)
// suite.Require().NoError(err)
// request := &authtypes.QueryAccountRequest{Address: sdk.AccAddress(suite.acc.Bytes()).String()}
// requestMarshal, _ := request.Marshal()
// RegisterABCIQueryAccount(
// client,
// requestMarshal,
// tmrpcclient.ABCIQueryOptions{Height: int64(1), Prove: false},
// account,
// )
// },
// true,
// hexutil.Uint64(0),
//},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest()
addr := tests.GenerateAddress()
if tc.accExists {
addr = common.BytesToAddress(suite.acc.Bytes())
}
tc.registerMock(addr, tc.blockNum)
txCount, err := suite.backend.GetTransactionCount(addr, tc.blockNum)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expTxCount, *txCount)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -5,13 +5,11 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/cerc-io/laconicd/crypto/hd"
rpctypes "github.com/cerc-io/laconicd/rpc/types" rpctypes "github.com/cerc-io/laconicd/rpc/types"
"github.com/cerc-io/laconicd/server/config" "github.com/cerc-io/laconicd/server/config"
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/cosmos/cosmos-sdk/client" "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/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -21,7 +19,6 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
) )
@ -162,23 +159,6 @@ func NewBackend(
panic(err) panic(err)
} }
algos, _ := clientCtx.Keyring.SupportedAlgorithms()
if !algos.Contains(hd.EthSecp256k1) {
kr, err := keyring.New(
sdk.KeyringServiceName(),
viper.GetString(flags.FlagKeyringBackend),
clientCtx.KeyringDir,
clientCtx.Input,
clientCtx.Codec,
hd.EthSecp256k1Option(),
)
if err != nil {
panic(err)
}
clientCtx = clientCtx.WithKeyring(kr)
}
return &Backend{ return &Backend{
ctx: context.Background(), ctx: context.Background(),
clientCtx: clientCtx, clientCtx: clientCtx,

View File

@ -2,12 +2,13 @@ package backend
import ( import (
"bufio" "bufio"
"fmt"
"math/big" "math/big"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
@ -25,52 +26,76 @@ import (
"github.com/cerc-io/laconicd/indexer" "github.com/cerc-io/laconicd/indexer"
"github.com/cerc-io/laconicd/rpc/backend/mocks" "github.com/cerc-io/laconicd/rpc/backend/mocks"
rpctypes "github.com/cerc-io/laconicd/rpc/types" rpctypes "github.com/cerc-io/laconicd/rpc/types"
"github.com/cerc-io/laconicd/tests"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
) )
type BackendTestSuite struct { type BackendTestSuite struct {
suite.Suite suite.Suite
backend *Backend backend *Backend
acc sdk.AccAddress
signer keyring.Signer
} }
func TestBackendTestSuite(t *testing.T) { func TestBackendTestSuite(t *testing.T) {
suite.Run(t, new(BackendTestSuite)) suite.Run(t, new(BackendTestSuite))
} }
const ChainID = "ethermint_9000-1"
// SetupTest is executed before every BackendTestSuite test // SetupTest is executed before every BackendTestSuite test
func (suite *BackendTestSuite) SetupTest() { func (suite *BackendTestSuite) SetupTest() {
ctx := server.NewDefaultContext() ctx := server.NewDefaultContext()
ctx.Viper.Set("telemetry.global-labels", []interface{}{}) ctx.Viper.Set("telemetry.global-labels", []interface{}{})
baseDir := suite.T().TempDir() baseDir := suite.T().TempDir()
nodeDirName := fmt.Sprintf("node") nodeDirName := "node"
clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli") clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli")
keyRing, err := suite.generateTestKeyring(clientDir) keyRing, err := suite.generateTestKeyring(clientDir)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// Create Account with set sequence
suite.acc = sdk.AccAddress(tests.GenerateAddress().Bytes())
accounts := map[string]client.TestAccount{}
accounts[suite.acc.String()] = client.TestAccount{
Address: suite.acc,
Num: uint64(1),
Seq: uint64(1),
}
priv, err := ethsecp256k1.GenerateKey()
suite.signer = tests.NewSigner(priv)
suite.Require().NoError(err)
encodingConfig := encoding.MakeConfig(app.ModuleBasics) encodingConfig := encoding.MakeConfig(app.ModuleBasics)
clientCtx := client.Context{}.WithChainID("ethermint_9000-1"). clientCtx := client.Context{}.WithChainID(ChainID).
WithHeight(1). WithHeight(1).
WithTxConfig(encodingConfig.TxConfig). WithTxConfig(encodingConfig.TxConfig).
WithKeyringDir(clientDir). WithKeyringDir(clientDir).
WithKeyring(keyRing) WithKeyring(keyRing).
WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts})
allowUnprotectedTxs := false allowUnprotectedTxs := false
idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx) idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx)
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer) suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer)
suite.backend.queryClient.QueryClient = mocks.NewQueryClient(suite.T()) suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T())
suite.backend.clientCtx.Client = mocks.NewClient(suite.T()) suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T())
suite.backend.ctx = rpctypes.ContextWithHeight(1) suite.backend.ctx = rpctypes.ContextWithHeight(1)
// Add codec
encCfg := encoding.MakeConfig(app.ModuleBasics)
suite.backend.clientCtx.Codec = encCfg.Codec
} }
// buildEthereumTx returns an example legacy Ethereum transaction // buildEthereumTx returns an example legacy Ethereum transaction
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) { func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
msgEthereumTx := evmtypes.NewTx( msgEthereumTx := evmtypes.NewTx(
big.NewInt(1), suite.backend.chainID,
uint64(0), uint64(0),
&common.Address{}, &common.Address{},
big.NewInt(0), big.NewInt(0),
@ -120,6 +145,7 @@ func (suite *BackendTestSuite) buildFormattedBlock(
uint64(header.Height), uint64(header.Height),
uint64(0), uint64(0),
baseFee, baseFee,
suite.backend.chainID,
) )
suite.Require().NoError(err) suite.Require().NoError(err)
ethRPCTxs = []interface{}{rpcTx} ethRPCTxs = []interface{}{rpcTx}
@ -145,3 +171,25 @@ func (suite *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Ke
encCfg := encoding.MakeConfig(app.ModuleBasics) encCfg := encoding.MakeConfig(app.ModuleBasics)
return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...) return keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, encCfg.Codec, []keyring.Option{hd.EthSecp256k1Option()}...)
} }
func (suite *BackendTestSuite) signAndEncodeEthTx(msgEthereumTx *evmtypes.MsgEthereumTx) []byte {
from, priv := tests.NewAddrKey()
signer := tests.NewSigner(priv)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParamsWithoutHeader(queryClient, 1)
ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig())
msgEthereumTx.From = from.String()
err := msgEthereumTx.Sign(ethSigner, signer)
suite.Require().NoError(err)
tx, err := msgEthereumTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
suite.Require().NoError(err)
txEncoder := suite.backend.clientCtx.TxConfig.TxEncoder()
txBz, err := txEncoder(tx)
suite.Require().NoError(err)
return txBz
}

View File

@ -376,6 +376,7 @@ func (b *Backend) RPCBlockFromTendermintBlock(
uint64(block.Height), uint64(block.Height),
uint64(txIndex), uint64(txIndex),
baseFee, baseFee,
b.chainID,
) )
if err != nil { if err != nil {
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error()) b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())

View File

@ -30,9 +30,9 @@ func (suite *BackendTestSuite) TestBlockNumber() {
{ {
"fail - invalid block header height", "fail - invalid block header height",
func() { func() {
height := int64(1)
var header metadata.MD var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) height := int64(1)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParamsInvalidHeight(queryClient, &header, int64(height)) RegisterParamsInvalidHeight(queryClient, &header, int64(height))
}, },
0x0, 0x0,
@ -41,9 +41,9 @@ func (suite *BackendTestSuite) TestBlockNumber() {
{ {
"fail - invalid block header", "fail - invalid block header",
func() { func() {
height := int64(1)
var header metadata.MD var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) height := int64(1)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParamsInvalidHeader(queryClient, &header, int64(height)) RegisterParamsInvalidHeader(queryClient, &header, int64(height))
}, },
0x0, 0x0,
@ -52,9 +52,9 @@ func (suite *BackendTestSuite) TestBlockNumber() {
{ {
"pass - app state header height 1", "pass - app state header height 1",
func() { func() {
height := int64(1)
var header metadata.MD var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) height := int64(1)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, int64(height)) RegisterParams(queryClient, &header, int64(height))
}, },
0x1, 0x1,
@ -161,7 +161,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() {
blockRes, _ = RegisterBlockResults(client, blockNum.Int64()) blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
RegisterConsensusParams(client, height) RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
}, },
@ -183,7 +183,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() {
blockRes, _ = RegisterBlockResults(client, blockNum.Int64()) blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
RegisterConsensusParams(client, height) RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
}, },
@ -306,7 +306,7 @@ func (suite *BackendTestSuite) TestGetBlockByHash() {
blockRes, _ = RegisterBlockResults(client, height) blockRes, _ = RegisterBlockResults(client, height)
RegisterConsensusParams(client, height) RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
}, },
@ -329,7 +329,7 @@ func (suite *BackendTestSuite) TestGetBlockByHash() {
blockRes, _ = RegisterBlockResults(client, height) blockRes, _ = RegisterBlockResults(client, height)
RegisterConsensusParams(client, height) RegisterConsensusParams(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
}, },
@ -552,9 +552,9 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() {
"fail - blockNum < 0 with app state height error", "fail - blockNum < 0 with app state height error",
ethrpc.BlockNumber(-1), ethrpc.BlockNumber(-1),
func(_ ethrpc.BlockNumber) { func(_ ethrpc.BlockNumber) {
appHeight := int64(1)
var header metadata.MD var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) appHeight := int64(1)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParamsError(queryClient, &header, appHeight) RegisterParamsError(queryClient, &header, appHeight)
}, },
false, false,
@ -564,9 +564,9 @@ func (suite *BackendTestSuite) TestTendermintBlockByNumber() {
"pass - blockNum < 0 with app state height >= 1", "pass - blockNum < 0 with app state height >= 1",
ethrpc.BlockNumber(-1), ethrpc.BlockNumber(-1),
func(blockNum ethrpc.BlockNumber) { func(blockNum ethrpc.BlockNumber) {
appHeight := int64(1)
var header metadata.MD var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) appHeight := int64(1)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, appHeight) RegisterParams(queryClient, &header, appHeight)
tmHeight := appHeight tmHeight := appHeight
@ -901,7 +901,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
false, false,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
@ -925,7 +925,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
true, true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFeeError(queryClient) RegisterBaseFeeError(queryClient)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
@ -949,7 +949,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
true, true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccountError(queryClient) RegisterValidatorAccountError(queryClient)
@ -973,7 +973,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
true, true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
@ -1003,7 +1003,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
true, true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
@ -1027,7 +1027,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
false, false,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
@ -1051,7 +1051,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
}, },
true, true,
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) { func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
RegisterValidatorAccount(queryClient, validator) RegisterValidatorAccount(queryClient, validator)
@ -1088,6 +1088,7 @@ func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() {
uint64(header.Height), uint64(header.Height),
uint64(0), uint64(0),
tc.baseFee, tc.baseFee,
suite.backend.chainID,
) )
suite.Require().NoError(err) suite.Require().NoError(err)
ethRPCTxs = []interface{}{rpcTx} ethRPCTxs = []interface{}{rpcTx}
@ -1237,7 +1238,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
expResultBlock, _ = RegisterBlock(client, height, nil) expResultBlock, _ = RegisterBlock(client, height, nil)
RegisterBlockResults(client, height) RegisterBlockResults(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFeeError(queryClient) RegisterBaseFeeError(queryClient)
}, },
true, true,
@ -1252,7 +1253,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
expResultBlock, _ = RegisterBlock(client, height, nil) expResultBlock, _ = RegisterBlock(client, height, nil)
RegisterBlockResults(client, height) RegisterBlockResults(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
true, true,
@ -1267,7 +1268,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
expResultBlock, _ = RegisterBlock(client, height, bz) expResultBlock, _ = RegisterBlock(client, height, bz)
RegisterBlockResults(client, height) RegisterBlockResults(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
true, true,
@ -1347,7 +1348,7 @@ func (suite *BackendTestSuite) TestHeaderByHash() {
expResultBlock, _ = RegisterBlockByHash(client, hash, bz) expResultBlock, _ = RegisterBlockByHash(client, hash, bz)
RegisterBlockResults(client, height) RegisterBlockResults(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFeeError(queryClient) RegisterBaseFeeError(queryClient)
}, },
true, true,
@ -1362,7 +1363,7 @@ func (suite *BackendTestSuite) TestHeaderByHash() {
expResultBlock, _ = RegisterBlockByHash(client, hash, nil) expResultBlock, _ = RegisterBlockByHash(client, hash, nil)
RegisterBlockResults(client, height) RegisterBlockResults(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
true, true,
@ -1377,7 +1378,7 @@ func (suite *BackendTestSuite) TestHeaderByHash() {
expResultBlock, _ = RegisterBlockByHash(client, hash, bz) expResultBlock, _ = RegisterBlockByHash(client, hash, bz)
RegisterBlockResults(client, height) RegisterBlockResults(client, height)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
true, true,
@ -1444,7 +1445,7 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() {
RegisterBlock(client, height, nil) RegisterBlock(client, height, nil)
RegisterBlockResults(client, blockNum.Int64()) RegisterBlockResults(client, blockNum.Int64())
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
baseFee := sdk.NewInt(1) baseFee := sdk.NewInt(1)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
@ -1470,7 +1471,7 @@ func (suite *BackendTestSuite) TestEthBlockByNumber() {
RegisterBlock(client, height, bz) RegisterBlock(client, height, bz)
RegisterBlockResults(client, blockNum.Int64()) RegisterBlockResults(client, blockNum.Int64())
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
baseFee := sdk.NewInt(1) baseFee := sdk.NewInt(1)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
@ -1535,7 +1536,7 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() {
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}}, TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
}, },
func(baseFee sdk.Int, blockNum int64) { func(baseFee sdk.Int, blockNum int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
ethtypes.NewBlock( ethtypes.NewBlock(
@ -1570,7 +1571,7 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() {
}, },
}, },
func(baseFee sdk.Int, blockNum int64) { func(baseFee sdk.Int, blockNum int64) {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBaseFee(queryClient, baseFee) RegisterBaseFee(queryClient, baseFee)
}, },
ethtypes.NewBlock( ethtypes.NewBlock(

View File

@ -7,11 +7,12 @@ import (
"fmt" "fmt"
"math/big" "math/big"
errorsmod "cosmossdk.io/errors"
rpctypes "github.com/cerc-io/laconicd/rpc/types" rpctypes "github.com/cerc-io/laconicd/rpc/types"
ethermint "github.com/cerc-io/laconicd/types" ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types" evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -68,7 +69,7 @@ func (b *Backend) Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, g
} }
for _, tx := range pending { for _, tx := range pending {
// FIXME does Resend api possible at all? https://github.com/cerc-io/laconicd/issues/905 // FIXME does Resend api possible at all? https://github.com/evmos/ethermint/issues/905
p, err := evmtypes.UnwrapEthereumMsg(tx, common.Hash{}) p, err := evmtypes.UnwrapEthereumMsg(tx, common.Hash{})
if err != nil { if err != nil {
// not valid ethereum tx // not valid ethereum tx
@ -150,7 +151,7 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) {
syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync) syncCtx := b.clientCtx.WithBroadcastMode(flags.BroadcastSync)
rsp, err := syncCtx.BroadcastTx(txBytes) rsp, err := syncCtx.BroadcastTx(txBytes)
if rsp != nil && rsp.Code != 0 { if rsp != nil && rsp.Code != 0 {
err = sdkerrors.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog) err = errorsmod.ABCIError(rsp.Codespace, rsp.Code, rsp.RawLog)
} }
if err != nil { if err != nil {
b.logger.Error("failed to broadcast tx", "error", err.Error()) b.logger.Error("failed to broadcast tx", "error", err.Error())
@ -268,6 +269,8 @@ func (b *Backend) SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.Transac
Value: args.Value, Value: args.Value,
Data: input, Data: input,
AccessList: args.AccessList, AccessList: args.AccessList,
ChainID: args.ChainID,
Nonce: args.Nonce,
} }
blockNr := rpctypes.NewBlockNumber(big.NewInt(0)) blockNr := rpctypes.NewBlockNumber(big.NewInt(0))
@ -298,17 +301,19 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
return 0, err return 0, err
} }
req := evmtypes.EthCallRequest{ header, err := b.TendermintBlockByNumber(blockNr)
Args: bz,
GasCap: b.RPCGasCap(),
}
_, err = b.TendermintBlockByNumber(blockNr)
if err != nil { if err != nil {
// the error message imitates geth behavior // the error message imitates geth behavior
return 0, errors.New("header not found") return 0, errors.New("header not found")
} }
req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ChainId: b.chainID.Int64(),
}
// From ContextWithHeight: if the provided height is 0, // From ContextWithHeight: if the provided height is 0,
// it will return an empty context and the gRPC query will use // it will return an empty context and the gRPC query will use
// the latest block height for querying. // the latest block height for querying.
@ -328,10 +333,17 @@ func (b *Backend) DoCall(
if err != nil { if err != nil {
return nil, err return nil, err
} }
header, err := b.TendermintBlockByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return nil, errors.New("header not found")
}
req := evmtypes.EthCallRequest{ req := evmtypes.EthCallRequest{
Args: bz, Args: bz,
GasCap: b.RPCGasCap(), GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ChainId: b.chainID.Int64(),
} }
// From ContextWithHeight: if the provided height is 0, // From ContextWithHeight: if the provided height is 0,

493
rpc/backend/call_tx_test.go Normal file
View File

@ -0,0 +1,493 @@
package backend
import (
"encoding/json"
"fmt"
"math/big"
"github.com/cerc-io/laconicd/rpc/backend/mocks"
rpctypes "github.com/cerc-io/laconicd/rpc/types"
"github.com/cerc-io/laconicd/tests"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
"google.golang.org/grpc/metadata"
)
func (suite *BackendTestSuite) TestResend() {
txNonce := (hexutil.Uint64)(1)
baseFee := sdk.NewInt(1)
gasPrice := new(hexutil.Big)
toAddr := tests.GenerateAddress()
chainID := (*hexutil.Big)(suite.backend.chainID)
callArgs := evmtypes.TransactionArgs{
From: nil,
To: &toAddr,
Gas: nil,
GasPrice: nil,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Value: gasPrice,
Nonce: &txNonce,
Input: nil,
Data: nil,
AccessList: nil,
ChainID: chainID,
}
testCases := []struct {
name string
registerMock func()
args evmtypes.TransactionArgs
gasPrice *hexutil.Big
gasLimit *hexutil.Uint64
expHash common.Hash
expPass bool
}{
{
"fail - Missing transaction nonce ",
func() {},
evmtypes.TransactionArgs{
Nonce: nil,
},
nil,
nil,
common.Hash{},
false,
},
{
"pass - Can't set Tx defaults BaseFee disabled",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFeeDisabled(queryClient)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
ChainID: callArgs.ChainID,
},
nil,
nil,
common.Hash{},
true,
},
{
"pass - Can't set Tx defaults ",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterFeeMarketParams(feeMarketClient, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
},
nil,
nil,
common.Hash{},
true,
},
{
"pass - MaxFeePerGas is nil",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFeeDisabled(queryClient)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
MaxPriorityFeePerGas: nil,
GasPrice: nil,
MaxFeePerGas: nil,
},
nil,
nil,
common.Hash{},
true,
},
{
"fail - GasPrice and (MaxFeePerGas or MaxPriorityPerGas specified",
func() {},
evmtypes.TransactionArgs{
Nonce: &txNonce,
MaxPriorityFeePerGas: nil,
GasPrice: gasPrice,
MaxFeePerGas: gasPrice,
},
nil,
nil,
common.Hash{},
false,
},
{
"fail - Block error",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlockError(client, 1)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
},
nil,
nil,
common.Hash{},
false,
},
{
"pass - MaxFeePerGas is nil",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
GasPrice: nil,
MaxPriorityFeePerGas: gasPrice,
MaxFeePerGas: gasPrice,
ChainID: callArgs.ChainID,
},
nil,
nil,
common.Hash{},
true,
},
{
"pass - Chain Id is nil",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
MaxPriorityFeePerGas: gasPrice,
ChainID: nil,
},
nil,
nil,
common.Hash{},
true,
},
{
"fail - Pending transactions error",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
RegisterEstimateGas(queryClient, callArgs)
RegisterParams(queryClient, &header, 1)
RegisterParamsWithoutHeader(queryClient, 1)
RegisterUnconfirmedTxsError(client, nil)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
To: &toAddr,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Value: gasPrice,
Gas: nil,
ChainID: callArgs.ChainID,
},
gasPrice,
nil,
common.Hash{},
false,
},
{
"fail - Not Ethereum txs",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, baseFee)
RegisterEstimateGas(queryClient, callArgs)
RegisterParams(queryClient, &header, 1)
RegisterParamsWithoutHeader(queryClient, 1)
RegisterUnconfirmedTxsEmpty(client, nil)
},
evmtypes.TransactionArgs{
Nonce: &txNonce,
To: &toAddr,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Value: gasPrice,
Gas: nil,
ChainID: callArgs.ChainID,
},
gasPrice,
nil,
common.Hash{},
false,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
hash, err := suite.backend.Resend(tc.args, tc.gasPrice, tc.gasLimit)
if tc.expPass {
suite.Require().Equal(tc.expHash, hash)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestSendRawTransaction() {
ethTx, bz := suite.buildEthereumTx()
rlpEncodedBz, _ := rlp.EncodeToBytes(ethTx.AsTransaction())
cosmosTx, _ := ethTx.BuildTx(suite.backend.clientCtx.TxConfig.NewTxBuilder(), "aphoton")
txBytes, _ := suite.backend.clientCtx.TxConfig.TxEncoder()(cosmosTx)
testCases := []struct {
name string
registerMock func()
rawTx []byte
expHash common.Hash
expPass bool
}{
{
"fail - empty bytes",
func() {},
[]byte{},
common.Hash{},
false,
},
{
"fail - no RLP encoded bytes",
func() {},
bz,
common.Hash{},
false,
},
{
"fail - unprotected transactions",
func() {
suite.backend.allowUnprotectedTxs = false
},
rlpEncodedBz,
common.Hash{},
false,
},
{
"fail - failed to get evm params",
func() {
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
suite.backend.allowUnprotectedTxs = true
RegisterParamsWithoutHeaderError(queryClient, 1)
},
rlpEncodedBz,
common.Hash{},
false,
},
{
"fail - failed to broadcast transaction",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
suite.backend.allowUnprotectedTxs = true
RegisterParamsWithoutHeader(queryClient, 1)
RegisterBroadcastTxError(client, txBytes)
},
rlpEncodedBz,
common.HexToHash(ethTx.Hash),
false,
},
{
"pass - Gets the correct transaction hash of the eth transaction",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
suite.backend.allowUnprotectedTxs = true
RegisterParamsWithoutHeader(queryClient, 1)
RegisterBroadcastTx(client, txBytes)
},
rlpEncodedBz,
common.HexToHash(ethTx.Hash),
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
hash, err := suite.backend.SendRawTransaction(tc.rawTx)
if tc.expPass {
suite.Require().Equal(tc.expHash, hash)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestDoCall() {
_, bz := suite.buildEthereumTx()
gasPrice := (*hexutil.Big)(big.NewInt(1))
toAddr := tests.GenerateAddress()
chainID := (*hexutil.Big)(suite.backend.chainID)
callArgs := evmtypes.TransactionArgs{
From: nil,
To: &toAddr,
Gas: nil,
GasPrice: nil,
MaxFeePerGas: gasPrice,
MaxPriorityFeePerGas: gasPrice,
Value: gasPrice,
Input: nil,
Data: nil,
AccessList: nil,
ChainID: chainID,
}
argsBz, err := json.Marshal(callArgs)
suite.Require().NoError(err)
testCases := []struct {
name string
registerMock func()
blockNum rpctypes.BlockNumber
callArgs evmtypes.TransactionArgs
expEthTx *evmtypes.MsgEthereumTxResponse
expPass bool
}{
{
"fail - Invalid request",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, bz)
RegisterEthCallError(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()})
},
rpctypes.BlockNumber(1),
callArgs,
&evmtypes.MsgEthereumTxResponse{},
false,
},
{
"pass - Returned transaction response",
func() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBlock(client, 1, bz)
RegisterEthCall(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()})
},
rpctypes.BlockNumber(1),
callArgs,
&evmtypes.MsgEthereumTxResponse{},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
msgEthTx, err := suite.backend.DoCall(tc.callArgs, tc.blockNum)
if tc.expPass {
suite.Require().Equal(tc.expEthTx, msgEthTx)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *BackendTestSuite) TestGasPrice() {
defaultGasPrice := (*hexutil.Big)(big.NewInt(1))
testCases := []struct {
name string
registerMock func()
expGas *hexutil.Big
expPass bool
}{
{
"pass - get the default gas price",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
RegisterFeeMarketParams(feeMarketClient, 1)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, sdk.NewInt(1))
},
defaultGasPrice,
true,
},
{
"fail - can't get gasFee, FeeMarketParams error",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient)
RegisterFeeMarketParamsError(feeMarketClient, 1)
RegisterParams(queryClient, &header, 1)
RegisterBlock(client, 1, nil)
RegisterBlockResults(client, 1)
RegisterBaseFee(queryClient, sdk.NewInt(1))
},
defaultGasPrice,
false,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("case %s", tc.name), func() {
suite.SetupTest() // reset test and queries
tc.registerMock()
gasPrice, err := suite.backend.GasPrice()
if tc.expPass {
suite.Require().Equal(tc.expGas, gasPrice)
} else {
suite.Require().Error(err)
}
})
}
}

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