feat: remaining record content types to support #79
113
.clang-format
113
.clang-format
@ -1,115 +1,6 @@
|
||||
---
|
||||
Language: Proto
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
RawStringFormats:
|
||||
- Delimiters:
|
||||
- pb
|
||||
Language: TextProto
|
||||
BasedOnStyle: google
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
ColumnLimit: 120
|
||||
IndentWidth: 2
|
||||
...
|
||||
|
5
.flake8
Normal file
5
.flake8
Normal 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
5
.github/CODEOWNERS
vendored
@ -1,4 +1,5 @@
|
||||
# CODEOWNERS: https://help.github.com/articles/about-codeowners/
|
||||
|
||||
# Primary repo maintainers
|
||||
* @fedekunze @khoslaventures @jolube
|
||||
# Primary (global) repo maintainers
|
||||
|
||||
* @evmos/core-engineering
|
||||
|
15
.github/workflows/build.yml
vendored
15
.github/workflows/build.yml
vendored
@ -17,16 +17,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
id: git_diff
|
||||
with:
|
||||
SUFFIX_FILTER: |
|
||||
.go
|
||||
.mod
|
||||
.sum
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- run: |
|
||||
make build
|
||||
if: env.GIT_DIFF
|
||||
|
23
.github/workflows/codeql-analysis.yml
vendored
23
.github/workflows/codeql-analysis.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go', 'javascript' ]
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
@ -40,21 +40,33 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
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.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
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).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
|
||||
- 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.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@ -68,4 +80,5 @@ jobs:
|
||||
# make release
|
||||
|
||||
- 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
28
.github/workflows/dependencies.yml
vendored
Normal 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
|
12
.github/workflows/deploy-contract.yml
vendored
12
.github/workflows/deploy-contract.yml
vendored
@ -23,14 +23,14 @@ jobs:
|
||||
node-version: '12.x'
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
- uses: technote-space/get-diff-action@v6.0.1
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
id: git_diff
|
||||
with:
|
||||
SUFFIX_FILTER: |
|
||||
.go
|
||||
.mod
|
||||
.sum
|
||||
.sol
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test contract
|
||||
run: |
|
||||
sudo make contract-tools
|
||||
|
5
.github/workflows/goreleaser.yml
vendored
5
.github/workflows/goreleaser.yml
vendored
@ -13,9 +13,10 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- name: release dry run
|
||||
run: make release-dry-run
|
||||
- name: setup release environment
|
||||
|
12
.github/workflows/linkchecker.yml
vendored
12
.github/workflows/linkchecker.yml
vendored
@ -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"
|
30
.github/workflows/lint.yml
vendored
30
.github/workflows/lint.yml
vendored
@ -13,20 +13,40 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
# Required: setup-go, for all versions v3.0.0+ of golangci-lint
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.0
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- uses: golangci/golangci-lint-action@v3
|
||||
- uses: golangci/golangci-lint-action@v3.3.1
|
||||
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
|
||||
github-token: ${{ secrets.github_token }}
|
||||
# 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
|
24
.github/workflows/proto.yml
vendored
24
.github/workflows/proto.yml
vendored
@ -3,6 +3,8 @@ name: Protobuf
|
||||
# This workflow is only run when a .proto file has been changed
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "proto/**"
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
@ -10,21 +12,17 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- 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:
|
||||
PATTERNS: |
|
||||
**/**.proto
|
||||
- name: lint
|
||||
run: make proto-lint
|
||||
if: env.GIT_DIFF
|
||||
breakage:
|
||||
input: "proto"
|
||||
|
||||
break-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- 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:
|
||||
PATTERNS: |
|
||||
**/**.proto
|
||||
- name: check-breakage
|
||||
run: make proto-check-breaking
|
||||
if: env.GIT_DIFF
|
||||
input: "proto"
|
||||
against: "https://github.com/${{ github.repository }}.git#branch=${{ github.event.pull_request.base.ref }},ref=HEAD~1,subdir=proto"
|
||||
|
7
.github/workflows/security.yml
vendored
7
.github/workflows/security.yml
vendored
@ -7,6 +7,9 @@ on:
|
||||
|
||||
jobs:
|
||||
Gosec:
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO111MODULE: on
|
||||
@ -14,7 +17,7 @@ jobs:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v3
|
||||
- name: Get Diff
|
||||
uses: technote-space/get-diff-action@v6.0.1
|
||||
uses: technote-space/get-diff-action@v6.1.2
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/*.go
|
||||
@ -27,7 +30,7 @@ jobs:
|
||||
args: '-no-fail -fmt sarif -out results.sarif -exclude=G701,G703 ./...'
|
||||
if: "env.GIT_DIFF_FILTERED != ''"
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
# Path to SARIF file relative to the root of the repository
|
||||
sarif_file: results.sarif
|
||||
|
20
.github/workflows/semgrep.yml
vendored
20
.github/workflows/semgrep.yml
vendored
@ -10,14 +10,19 @@ on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
jobs:
|
||||
# Update from: https://semgrep.dev/docs/semgrep-ci/sample-ci-configs/#github-actions
|
||||
semgrep:
|
||||
name: Scan
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: returntocorp/semgrep
|
||||
if: (github.actor != 'dependabot[bot]')
|
||||
steps:
|
||||
- name: Permission issue fix
|
||||
run: git config --global --add safe.directory /__w/laconicd/laconicd
|
||||
- uses: actions/checkout@v3
|
||||
- name: Get Diff
|
||||
uses: technote-space/get-diff-action@v6.0.1
|
||||
uses: technote-space/get-diff-action@v6.1.2
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/*.go
|
||||
@ -26,16 +31,15 @@ jobs:
|
||||
**/*.sol
|
||||
go.mod
|
||||
go.sum
|
||||
- uses: returntocorp/semgrep-action@v1
|
||||
with:
|
||||
publishToken: ${{ secrets.SEMGREP_APP_TOKEN }}
|
||||
- uses: actions/checkout@v3
|
||||
- run: semgrep scan --sarif --output=semgrep.sarif --config auto
|
||||
env:
|
||||
# Upload findings to GitHub Advanced Security Dashboard [step 1/2]
|
||||
# See also the next step.
|
||||
generateSarif: "1"
|
||||
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
|
||||
if: "env.GIT_DIFF_FILTERED != ''"
|
||||
# Upload findings to GitHub Advanced Security Dashboard [step 2/2]
|
||||
- name: Upload SARIF file for GitHub Advanced Security Dashboard
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: semgrep.sarif
|
||||
if: "env.GIT_DIFF_FILTERED != ''"
|
||||
|
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal 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"
|
121
.github/workflows/test.yml
vendored
121
.github/workflows/test.yml
vendored
@ -20,10 +20,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
@ -45,10 +45,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- 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
|
||||
with:
|
||||
PATTERNS: |
|
||||
@ -66,10 +66,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.19
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.sol
|
||||
@ -81,37 +81,16 @@ jobs:
|
||||
make test-rpc
|
||||
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:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - uses: cachix/install-nix-action@v18
|
||||
# - uses: cachix/cachix-action@v11
|
||||
# - uses: cachix/cachix-action@v12
|
||||
# with:
|
||||
# name: ethermint
|
||||
# signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
||||
# - uses: technote-space/get-diff-action@v6.1.1
|
||||
# - uses: technote-space/get-diff-action@v6.1.2
|
||||
# with:
|
||||
# PATTERNS: |
|
||||
# **/**.sol
|
||||
@ -142,89 +121,9 @@ jobs:
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - uses: cachix/install-nix-action@v18
|
||||
# - uses: cachix/cachix-action@v11
|
||||
# - uses: cachix/cachix-action@v12
|
||||
# with:
|
||||
# name: ethermint
|
||||
# signingKey: "${{ secrets.CACHIX_SIGNING_KEY }}"
|
||||
# - name: 'instantiate integration test env'
|
||||
# run: nix-store -r $(nix-instantiate tests/integration_tests/shell.nix)
|
||||
|
||||
test-sim-nondeterminism:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation nondeterminism
|
||||
run: |
|
||||
make test-sim-nondeterminism
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-random-genesis-fast:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation with random genesis
|
||||
run: |
|
||||
make test-sim-random-genesis-fast
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-import-export:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Simulation of import and export genesis
|
||||
run: |
|
||||
make test-sim-import-export
|
||||
if: env.GIT_DIFF
|
||||
|
||||
test-sim-after-import:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.18
|
||||
check-latest: true
|
||||
- uses: actions/checkout@v3
|
||||
- uses: technote-space/get-diff-action@v6.1.1
|
||||
with:
|
||||
PATTERNS: |
|
||||
**/**.go
|
||||
go.mod
|
||||
go.sum
|
||||
- name: Test simulation after import
|
||||
run: |
|
||||
make test-sim-after-import
|
||||
if: env.GIT_DIFF
|
||||
# run: nix-store -r "$(nix-instantiate tests/integration_tests/shell.nix)"
|
||||
|
14
.gitignore
vendored
14
.gitignore
vendored
@ -13,6 +13,7 @@
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
.dccache
|
||||
|
||||
# Build
|
||||
*.test
|
||||
@ -34,10 +35,14 @@ keyring_test_cosmos
|
||||
./**/node_modules
|
||||
./**/dist
|
||||
secret.yml
|
||||
artifacts/*
|
||||
tmp-swagger-gen
|
||||
github.com/
|
||||
# vue/
|
||||
|
||||
# Local docker volume mappings
|
||||
localnet-setup
|
||||
.testnets
|
||||
|
||||
# Testing
|
||||
coverage.txt
|
||||
@ -55,6 +60,7 @@ vagrant
|
||||
# IDE
|
||||
.idea/
|
||||
*.iml
|
||||
*.code-workspace
|
||||
|
||||
# Graphviz
|
||||
dependency-graph.png
|
||||
@ -69,6 +75,8 @@ dependency-graph.png
|
||||
*.abi
|
||||
|
||||
# Node.js
|
||||
tests/**/node_modules/*
|
||||
tests-solidity/**/node_modules/*
|
||||
**/**.json
|
||||
**/node_modules
|
||||
|
||||
|
||||
# OpenZeppelin contracts
|
||||
contracts/@openzeppelin/*
|
||||
|
2766
.gitleaks.toml
Normal file
2766
.gitleaks.toml
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,47 +6,35 @@ run:
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- goconst
|
||||
- gocritic
|
||||
- gofmt
|
||||
- goimports
|
||||
- gofumpt
|
||||
- revive
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
# - lll TODO: enable
|
||||
- lll
|
||||
- misspell
|
||||
- nakedret
|
||||
- prealloc
|
||||
- exportloopref
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
# - typecheck #TODO: enable
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- nolintlint
|
||||
- asciicheck
|
||||
# - exhaustive
|
||||
- exportloopref
|
||||
- gofumpt
|
||||
- gomodguard
|
||||
# - nestif
|
||||
# - nlreturn
|
||||
- noctx
|
||||
- rowserrcheck
|
||||
# - whitespace
|
||||
# - wsl
|
||||
disable:
|
||||
- typecheck
|
||||
- whitespace
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
@ -59,6 +47,8 @@ issues:
|
||||
max-same-issues: 50
|
||||
|
||||
linters-settings:
|
||||
lll:
|
||||
line-length: 150
|
||||
dogsled:
|
||||
max-blank-identifiers: 3
|
||||
golint:
|
||||
@ -73,7 +63,7 @@ linters-settings:
|
||||
require-explanation: false
|
||||
require-specific: false
|
||||
gofumpt:
|
||||
lang-version: "1.17"
|
||||
lang-version: "1.19"
|
||||
gomodguard:
|
||||
blocked:
|
||||
versions: # List of blocked module version constraints
|
||||
|
21
.markdownlint.yml
Normal file
21
.markdownlint.yml
Normal 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
3
.markdownlintignore
Normal file
@ -0,0 +1,3 @@
|
||||
CHANGELOG.md
|
||||
docs/api/proto-docs.md
|
||||
docs/node_modules
|
28
.mergify.yml
28
.mergify.yml
@ -4,7 +4,7 @@ queue_rules:
|
||||
- "#approved-reviews-by>1"
|
||||
|
||||
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:
|
||||
- "#approved-reviews-by>1"
|
||||
- base=main
|
||||
@ -12,22 +12,30 @@ pull_request_rules:
|
||||
actions:
|
||||
queue:
|
||||
name: default
|
||||
merge:
|
||||
method: squash
|
||||
commit_message: title+body
|
||||
- name: backport patches to v0.9.x branch
|
||||
commit_message_template: |
|
||||
{{ title }} (#{{ number }})
|
||||
{{ body }}
|
||||
- name: backport patches to main branch
|
||||
conditions:
|
||||
- base=main
|
||||
- label=backport/0.9.x
|
||||
- label=backport/main
|
||||
actions:
|
||||
backport:
|
||||
branches:
|
||||
- release/v0.9.x
|
||||
- name: backport patches to v0.7.x branch
|
||||
- main
|
||||
- name: backport patches to v0.20.x branch
|
||||
conditions:
|
||||
- base=main
|
||||
- label=backport/0.7.x
|
||||
- label=backport/0.20.x
|
||||
actions:
|
||||
backport:
|
||||
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
174
.protolint.yml
Normal 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
3
.solhint.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "solhint:default"
|
||||
}
|
31
.yamllint
Normal file
31
.yamllint
Normal 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
|
75
CHANGELOG.md
75
CHANGELOG.md
@ -36,7 +36,57 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
# 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
|
||||
|
||||
@ -63,11 +113,30 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (rpc) [#1561](https://github.com/evmos/ethermint/pull/1561) Fix call to `NewMnemonic` in `personal_newAccount`
|
||||
* (cli) [#1550](https://github.com/evmos/ethermint/pull/1550) Fix signature algorithm validation and default for Ledger.
|
||||
* (eip712) [#1543](https://github.com/evmos/ethermint/pull/1543) Improve error handling for EIP-712 encoding config initialization.
|
||||
* (app) [#1505](https://github.com/evmos/ethermint/pull/1505) Setup gRPC node service with the application.
|
||||
* (server) [#1497](https://github.com/evmos/ethermint/pull/1497) Fix telemetry server setup for observability
|
||||
* (rpc) [#1442](https://github.com/evmos/ethermint/pull/1442) Fix decoding of `finalized` block number.
|
||||
* (rpc) [#1179](https://github.com/evmos/ethermint/pull/1179) Fix gas used in traceTransaction response.
|
||||
* (rpc) [#1284](https://github.com/evmos/ethermint/pull/1284) Fix internal trace response upon incomplete `eth_sendTransaction` call.
|
||||
* (rpc) [#1340](https://github.com/evmos/ethermint/pull/1340) Fix error response when `eth_estimateGas` height provided is not found.
|
||||
* (rpc) [#1354](https://github.com/evmos/ethermint/pull/1354) Fix grpc query failure(`BaseFee` and `EthCall`) on legacy block states.
|
||||
* (cli) [#1362](https://github.com/evmos/ethermint/pull/1362) Fix `index-eth-tx` error when the indexer db is empty.
|
||||
* (state) [#1320](https://github.com/evmos/ethermint/pull/1320) Fix codehash check mismatch when the code has been deleted in the evm state.
|
||||
* (rpc) [#1392](https://github.com/evmos/ethermint/pull/1392) Allow fill the proposer address in json-rpc through tendermint api, and pass explicitly to grpc query handler.
|
||||
* (rpc) [#1431](https://github.com/evmos/ethermint/pull/1431) Align hex-strings proof fields in `eth_getProof` as Ethereum.
|
||||
* (proto) [#1466](https://github.com/evmos/ethermint/pull/1466) Fix proto scripts and upgrade them to mirror current cosmos-sdk scripts
|
||||
* (rpc) [#1405](https://github.com/evmos/ethermint/pull/1405) Fix uninitialized chain ID field in gRPC requests.
|
||||
* (analytics) [#1434](https://github.com/evmos/ethermint/pull/1434) Remove unbound labels from custom tendermint metrics.
|
||||
* (rpc) [#1484](https://github.com/evmos/ethermint/pull/1484) Align empty account result for old blocks as ethereum instead of return account not found error.
|
||||
* (rpc) [#1503](https://github.com/evmos/ethermint/pull/1503) Fix block hashes returned on JSON-RPC filter `eth_newBlockFilter`.
|
||||
* (ante) [#1566](https://github.com/evmos/ethermint/pull/1566) Fix `gasWanted` on `EthGasConsumeDecorator` ante handler when running transaction in `ReCheckMode`
|
||||
|
||||
## [v0.19.3] - 2022-10-14
|
||||
|
||||
* (deps) [1381](https://github.com/evmos/ethermint/pull/1381) Bump sdk to `v0.45.9`
|
||||
|
||||
## [v0.19.2] - 2022-08-29
|
||||
|
||||
@ -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.
|
||||
* (rpc) [tharsis#1081](https://github.com/evmos/ethermint/pull/1081) fix `debug_getBlockRlp`/`debug_printBlock` don't filter failed transactions.
|
||||
* (ante) [tharsis#1111](https://github.com/evmos/ethermint/pull/1111) Move CanTransfer decorator before GasConsume decorator
|
||||
* (types) [tharsis#1112](https://github.com/cosmos/ethermint/pull/1112) Add `GetBaseAccount` to avoid invalid account error when create vesting account.
|
||||
* (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
|
||||
|
||||
@ -633,7 +702,7 @@ the Tracer type used to collect execution traces from the EVM transaction execut
|
||||
|
||||
### Improvements
|
||||
|
||||
* (deps) [tharsis#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/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+.
|
||||
* (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)
|
||||
|
@ -17,7 +17,7 @@ COPY . .
|
||||
RUN make build
|
||||
|
||||
# Final image
|
||||
FROM alpine:3.16.2
|
||||
FROM alpine:3.17.0
|
||||
|
||||
# Install ca-certificates
|
||||
RUN apk add --update ca-certificates jq
|
||||
|
155
Makefile
Executable file → Normal file
155
Makefile
Executable file → Normal file
@ -14,7 +14,6 @@ SIMAPP = ./app
|
||||
HTTPS_GIT := https://github.com/cerc-io/laconicd.git
|
||||
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
||||
DOCKER := $(shell which docker)
|
||||
DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf:1.0.0-rc8
|
||||
# RocksDB is a native dependency, so we don't assume the library is installed.
|
||||
# Instead, it must be explicitly enabled and we warn when it is not.
|
||||
ENABLE_ROCKSDB ?= false
|
||||
@ -111,6 +110,12 @@ ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
|
||||
BUILD_FLAGS += -trimpath
|
||||
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.
|
||||
# include contrib/devtools/Makefile
|
||||
|
||||
@ -158,7 +163,7 @@ clean:
|
||||
|
||||
all: build
|
||||
|
||||
build-all: tools build lint test
|
||||
build-all: tools build lint test vulncheck
|
||||
|
||||
.PHONY: distclean clean build-all
|
||||
|
||||
@ -167,7 +172,7 @@ build-all: tools build lint test
|
||||
###############################################################################
|
||||
|
||||
PACKAGE_NAME:=github.com/cerc-io/laconicd
|
||||
GOLANG_CROSS_VERSION = v1.18
|
||||
GOLANG_CROSS_VERSION = v1.19
|
||||
GOPATH ?= '$(HOME)/go'
|
||||
release-dry-run:
|
||||
docker run \
|
||||
@ -276,6 +281,10 @@ go.sum: go.mod
|
||||
go mod verify
|
||||
go mod tidy
|
||||
|
||||
vulncheck: $(BUILDDIR)/
|
||||
GOBIN=$(BUILDDIR) go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
$(BUILDDIR)/govulncheck ./...
|
||||
|
||||
###############################################################################
|
||||
### Documentation ###
|
||||
###############################################################################
|
||||
@ -330,9 +339,6 @@ test-import:
|
||||
test-rpc:
|
||||
./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" -r "true"
|
||||
|
||||
test-integration:
|
||||
./scripts/integration-test-all.sh -t "integration" -q 1 -z 1 -s 2 -m "integration" -r "true"
|
||||
|
||||
run-integration-tests:
|
||||
@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)
|
||||
|
||||
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:
|
||||
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
|
||||
@ -427,74 +388,62 @@ format-fix:
|
||||
### 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)
|
||||
containerProtoGen=$(PROJECT_NAME)-proto-gen-$(protoVer)
|
||||
containerProtoGenAny=$(PROJECT_NAME)-proto-gen-any-$(protoVer)
|
||||
containerProtoGenSwagger=$(PROJECT_NAME)-proto-gen-swagger-$(protoVer)
|
||||
containerProtoFmt=$(PROJECT_NAME)-proto-fmt-$(protoVer)
|
||||
protoImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
|
||||
# ------
|
||||
# NOTE: cosmos/proto-builder image is needed because clang-format is not installed
|
||||
# on the tendermintdev/sdk-proto-gen docker image.
|
||||
# Link to the cosmos/proto-builder docker images:
|
||||
# https://github.com/cosmos/cosmos-sdk/pkgs/container/proto-builder
|
||||
#
|
||||
protoCosmosVer=0.11.2
|
||||
protoCosmosName=ghcr.io/cosmos/proto-builder:$(protoCosmosVer)
|
||||
protoCosmosImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoCosmosName)
|
||||
# ------
|
||||
# NOTE: Link to the yoheimuta/protolint docker images:
|
||||
# https://hub.docker.com/r/yoheimuta/protolint/tags
|
||||
#
|
||||
protolintVer=0.42.2
|
||||
protolintName=yoheimuta/protolint:$(protolintVer)
|
||||
protolintImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protolintName)
|
||||
|
||||
|
||||
# ------
|
||||
# NOTE: If you are experiencing problems running these commands, try deleting
|
||||
# the docker images and execute the desired command again.
|
||||
#
|
||||
proto-all: proto-format proto-lint proto-gen
|
||||
|
||||
proto-gen:
|
||||
@echo "Generating Protobuf files"
|
||||
@if docker ps -a --format '{{.Names}}' | grep -Eq "^${containerProtoGen}$$"; then docker start -a $(containerProtoGen); else docker run --name $(containerProtoGen) -v $(CURDIR):/workspace --workdir /workspace $(protoImageName) \
|
||||
sh ./scripts/protocgen.sh; fi
|
||||
$(protoImage) sh ./scripts/protocgen.sh
|
||||
|
||||
proto-swagger-gen:
|
||||
@echo "Generating Protobuf Swagger"
|
||||
@./scripts/proto-tools-installer.sh
|
||||
@./scripts/protoc-swagger-gen.sh
|
||||
|
||||
# TODO: Rethink API docs generation
|
||||
# proto-swagger-gen:
|
||||
# @echo "Generating Protobuf Swagger"
|
||||
# $(protoImage) sh ./scripts/protoc-swagger-gen.sh
|
||||
|
||||
proto-format:
|
||||
@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 \
|
||||
find ./ -not -path "./third_party/*" -name "*.proto" -exec clang-format -i {} \; ; fi
|
||||
$(protoCosmosImage) find ./ -name *.proto -exec clang-format -i {} \;
|
||||
|
||||
# NOTE: The linter configuration lives in .protolint.yaml
|
||||
proto-lint:
|
||||
@$(DOCKER_BUF) lint --error-format=json
|
||||
@echo "Linting Protobuf files"
|
||||
$(protolintImage) lint ./proto
|
||||
|
||||
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
|
||||
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
|
||||
.PHONY: proto-all proto-gen proto-gen-any proto-format proto-lint proto-check-breaking
|
||||
|
||||
###############################################################################
|
||||
### Localnet ###
|
||||
|
@ -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.
|
||||
|
||||
**Note**: Requires [Go 1.18+](https://golang.org/dl/)
|
||||
**Note**: Requires [Go 1.19+](https://golang.org/dl/)
|
||||
|
||||
## Installation
|
||||
|
||||
|
62
SECURITY.md
Normal file
62
SECURITY.md
Normal 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 you’ve 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 [Immunefi’s 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 vulnerability’s 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 Evmos’s 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)
|
@ -6,8 +6,10 @@ import (
|
||||
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
@ -44,14 +46,14 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
// handle as *evmtypes.MsgEthereumTx
|
||||
anteHandler = newEthAnteHandler(options)
|
||||
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
|
||||
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
|
||||
anteHandler = newCosmosAnteHandlerEip712(options)
|
||||
// Deprecated: Handle as normal Cosmos SDK tx, except signature is checked for Legacy EIP712 representation
|
||||
anteHandler = NewLegacyCosmosAnteHandlerEip712(options)
|
||||
case "/ethermint.types.v1.ExtensionOptionDynamicFeeTx":
|
||||
// cosmos-sdk tx with dynamic fee extension
|
||||
anteHandler = newCosmosAnteHandler(options)
|
||||
default:
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownExtensionOptions,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrUnknownExtensionOptions,
|
||||
"rejecting tx with unsupported extension option: %s", typeURL,
|
||||
)
|
||||
}
|
||||
@ -65,7 +67,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
case sdk.Tx:
|
||||
anteHandler = newCosmosAnteHandler(options)
|
||||
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)
|
||||
@ -74,7 +76,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
|
||||
func Recover(logger tmlog.Logger, err *error) {
|
||||
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 {
|
||||
logger.Error(
|
||||
@ -99,12 +101,48 @@ var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsu
|
||||
func DefaultSigVerificationGasConsumer(
|
||||
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
|
||||
) error {
|
||||
// support for ethereum ECDSA secp256k1 keys
|
||||
_, ok := sig.PubKey.(*ethsecp256k1.PubKey)
|
||||
if ok {
|
||||
pubkey := sig.PubKey
|
||||
switch pubkey := pubkey.(type) {
|
||||
case *ethsecp256k1.PubKey:
|
||||
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
|
||||
return nil
|
||||
}
|
||||
|
||||
case multisig.PubKey:
|
||||
// Multisig keys
|
||||
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected %T, got, %T", &signing.MultiSignatureData{}, sig.Data)
|
||||
}
|
||||
return ConsumeMultisignatureVerificationGas(meter, multisignature, pubkey, params, sig.Sequence)
|
||||
|
||||
default:
|
||||
return authante.DefaultSigVerificationGasConsumer(meter, sig, params)
|
||||
}
|
||||
}
|
||||
|
||||
// ConsumeMultisignatureVerificationGas consumes gas from a GasMeter for verifying a multisig pubkey signature
|
||||
func ConsumeMultisignatureVerificationGas(
|
||||
meter sdk.GasMeter, sig *signing.MultiSignatureData, pubkey multisig.PubKey,
|
||||
params authtypes.Params, accSeq uint64,
|
||||
) error {
|
||||
size := sig.BitArray.Count()
|
||||
sigIndex := 0
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
if !sig.BitArray.GetIndex(i) {
|
||||
continue
|
||||
}
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: pubkey.GetPubKeys()[i],
|
||||
Data: sig.Signatures[sigIndex],
|
||||
Sequence: accSeq,
|
||||
}
|
||||
err := DefaultSigVerificationGasConsumer(meter, sigV2, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sigIndex++
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -2,24 +2,36 @@ package ante_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
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/x/auth/migrations/legacytx"
|
||||
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/authz"
|
||||
|
||||
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"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
ethparams "github.com/ethereum/go-ethereum/params"
|
||||
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
)
|
||||
|
||||
func (suite AnteTestSuite) TestAnteHandler() {
|
||||
@ -337,6 +349,17 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
return txBuilder.GetTx()
|
||||
}, 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",
|
||||
func() sdk.Tx {
|
||||
@ -364,7 +387,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
from, grantee, &banktypes.SendAuthorization{SpendLimit: gasAmount}, &expiresAt,
|
||||
)
|
||||
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,
|
||||
},
|
||||
|
||||
@ -397,10 +420,65 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||
amount := sdk.NewCoins(coinAmount)
|
||||
gas := uint64(200000)
|
||||
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
txBuilder := suite.CreateTestEIP712MsgSubmitEvidence(from, privKey, "ethermint_9000-1", gas, amount)
|
||||
return txBuilder.GetTx()
|
||||
}, 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",
|
||||
func() sdk.Tx {
|
||||
@ -496,6 +574,301 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
||||
return tx
|
||||
}, 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 {
|
||||
@ -914,3 +1287,93 @@ func (suite AnteTestSuite) TestAnteHandlerWithParams() {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -3,15 +3,17 @@ package ante
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
ibcante "github.com/cosmos/ibc-go/v5/modules/core/ante"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"github.com/cerc-io/laconicd/ethereum/eip712"
|
||||
@ -19,6 +21,7 @@ import (
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
)
|
||||
|
||||
var ethermintCodec codec.ProtoCodecMarshaler
|
||||
@ -29,19 +32,47 @@ func init() {
|
||||
ethermintCodec = codec.NewProtoCodec(registry)
|
||||
}
|
||||
|
||||
// Eip712SigVerificationDecorator Verify all signatures for a tx and return an error if any are invalid. Note,
|
||||
// the Eip712SigVerificationDecorator decorator will not get executed on ReCheck.
|
||||
// Deprecated: NewLegacyCosmosAnteHandlerEip712 creates an AnteHandler to process legacy EIP-712
|
||||
// transactions, as defined by the presence of an ExtensionOptionsWeb3Tx extension.
|
||||
func NewLegacyCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
|
||||
return sdk.ChainAnteDecorators(
|
||||
RejectMessagesDecorator{}, // reject MsgEthereumTxs
|
||||
authante.NewSetUpContextDecorator(),
|
||||
authante.NewValidateBasicDecorator(),
|
||||
authante.NewTxTimeoutHeightDecorator(),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
authante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
authante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
authante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
// SetPubKeyDecorator must be called before all signature verification decorators
|
||||
authante.NewSetPubKeyDecorator(options.AccountKeeper),
|
||||
authante.NewValidateSigCountDecorator(options.AccountKeeper),
|
||||
authante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
|
||||
// Note: signature verification uses EIP instead of the cosmos signature validator
|
||||
NewLegacyEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
||||
authante.NewIncrementSequenceDecorator(options.AccountKeeper),
|
||||
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
|
||||
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
|
||||
)
|
||||
}
|
||||
|
||||
// Deprecated: LegacyEip712SigVerificationDecorator Verify all signatures for a tx and return an error if any are invalid. Note,
|
||||
// the LegacyEip712SigVerificationDecorator decorator will not get executed on ReCheck.
|
||||
// NOTE: As of v0.20.0, EIP-712 signature verification is handled by the ethsecp256k1 public key (see ethsecp256k1.go)
|
||||
//
|
||||
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
|
||||
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||
type Eip712SigVerificationDecorator struct {
|
||||
type LegacyEip712SigVerificationDecorator struct {
|
||||
ak evmtypes.AccountKeeper
|
||||
signModeHandler authsigning.SignModeHandler
|
||||
}
|
||||
|
||||
// NewEip712SigVerificationDecorator creates a new Eip712SigVerificationDecorator
|
||||
func NewEip712SigVerificationDecorator(ak evmtypes.AccountKeeper, signModeHandler authsigning.SignModeHandler) Eip712SigVerificationDecorator {
|
||||
return Eip712SigVerificationDecorator{
|
||||
// Deprecated: NewLegacyEip712SigVerificationDecorator creates a new LegacyEip712SigVerificationDecorator
|
||||
func NewLegacyEip712SigVerificationDecorator(
|
||||
ak evmtypes.AccountKeeper,
|
||||
signModeHandler authsigning.SignModeHandler,
|
||||
) LegacyEip712SigVerificationDecorator {
|
||||
return LegacyEip712SigVerificationDecorator{
|
||||
ak: ak,
|
||||
signModeHandler: signModeHandler,
|
||||
}
|
||||
@ -49,7 +80,7 @@ func NewEip712SigVerificationDecorator(ak evmtypes.AccountKeeper, signModeHandle
|
||||
|
||||
// AnteHandle handles validation of EIP712 signed cosmos txs.
|
||||
// it is not run on RecheckTx
|
||||
func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
func (svd LegacyEip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
tx sdk.Tx,
|
||||
simulate bool,
|
||||
next sdk.AnteHandler,
|
||||
@ -61,12 +92,12 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
|
||||
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||
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)
|
||||
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.
|
||||
@ -80,12 +111,16 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
|
||||
// EIP712 allows just one signature
|
||||
if len(sigs) != 1 {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
|
||||
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
|
||||
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
|
||||
@ -100,13 +135,13 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context,
|
||||
// retrieve pubkey
|
||||
pubKey := acc.GetPubKey()
|
||||
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.
|
||||
if sig.Sequence != acc.GetSequence() {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrWrongSequence,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrWrongSequence,
|
||||
"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 {
|
||||
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)
|
||||
@ -150,12 +185,12 @@ func VerifySignature(
|
||||
switch data := sigData.(type) {
|
||||
case *signing.SingleSignatureData:
|
||||
if data.SignMode != signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrNotSupported, "unexpected SignatureData %T: wrong SignMode", sigData)
|
||||
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 {
|
||||
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),
|
||||
@ -163,7 +198,7 @@ func VerifySignature(
|
||||
|
||||
msgs := tx.GetMsgs()
|
||||
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(
|
||||
@ -180,33 +215,33 @@ func VerifySignature(
|
||||
|
||||
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
|
||||
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)
|
||||
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()
|
||||
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)
|
||||
if !ok {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "unknown extension option")
|
||||
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "unknown extension option")
|
||||
}
|
||||
|
||||
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 {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
|
||||
return errorsmod.Wrap(errortypes.ErrUnknownExtensionOptions, "no feePayer on ExtensionOptionsWeb3Tx")
|
||||
}
|
||||
feePayer, err := sdk.AccAddressFromBech32(extOpt.FeePayer)
|
||||
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{
|
||||
@ -215,17 +250,17 @@ func VerifySignature(
|
||||
|
||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
feePayerSig := extOpt.FeePayerSig
|
||||
if len(feePayerSig) != ethcrypto.SignatureLength {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "signature length doesn't match typical [R||S||V] signature 65 bytes")
|
||||
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)
|
||||
@ -235,12 +270,12 @@ func VerifySignature(
|
||||
|
||||
feePayerPubkey, err := secp256k1.RecoverPubkey(sigHash, feePayerSig)
|
||||
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)
|
||||
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 := ðsecp256k1.PubKey{
|
||||
@ -248,23 +283,23 @@ func VerifySignature(
|
||||
}
|
||||
|
||||
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())
|
||||
|
||||
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]
|
||||
// WARNING! Under NO CIRCUMSTANCES try to use pubKey.VerifySignature there
|
||||
if !secp256k1.VerifySignature(pubKey.Bytes(), sigHash, feePayerSig[:len(feePayerSig)-1]) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
|
||||
return errorsmod.Wrap(errortypes.ErrorInvalidSigner, "unable to verify signer signature of EIP712 typed data")
|
||||
}
|
||||
|
||||
return nil
|
||||
default:
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
|
||||
return errorsmod.Wrapf(errortypes.ErrTooManySignatures, "unexpected SignatureData %T", sigData)
|
||||
}
|
||||
}
|
||||
|
450
app/ante/eth.go
450
app/ante/eth.go
@ -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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
errortypes "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
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"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
|
||||
@ -21,61 +34,6 @@ import (
|
||||
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
|
||||
type EthAccountVerificationDecorator struct {
|
||||
ak evmtypes.AccountKeeper
|
||||
@ -109,35 +67,35 @@ func (avd EthAccountVerificationDecorator) AnteHandle(
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
||||
return ctx, 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
|
||||
from := msgEthTx.GetFrom()
|
||||
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
|
||||
fromAddr := common.BytesToAddress(from)
|
||||
acct := avd.evmKeeper.GetAccount(ctx, fromAddr) //nolint: all
|
||||
acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
|
||||
|
||||
if acct == nil {
|
||||
acc := avd.ak.NewAccountWithAddress(ctx, from)
|
||||
avd.ak.SetAccount(ctx, acc)
|
||||
acct = statedb.NewEmptyAccount()
|
||||
} else if acct.IsContract() {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType,
|
||||
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
||||
}
|
||||
|
||||
if err := evmkeeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
|
||||
if err := keeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||
return ctx, errorsmod.Wrap(err, "failed to check sender balance")
|
||||
}
|
||||
}
|
||||
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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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)
|
||||
// - transaction or block gas meter runs out of gas
|
||||
// - sets the gas meter limit
|
||||
// - gas limit is greater than the block gas meter limit
|
||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
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())
|
||||
homestead := ethCfg.IsHomestead(blockHeight)
|
||||
istanbul := ethCfg.IsIstanbul(blockHeight)
|
||||
london := ethCfg.IsLondon(blockHeight)
|
||||
evmDenom := params.EvmDenom
|
||||
gasWanted := uint64(0)
|
||||
var events sdk.Events
|
||||
|
||||
// Use the lowest priority of all the messages as the final one.
|
||||
minPriority := int64(math.MaxInt64)
|
||||
baseFee := egcd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, 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)
|
||||
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 {
|
||||
@ -213,45 +183,59 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
gasWanted += txData.GetGas()
|
||||
}
|
||||
|
||||
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
||||
ctx,
|
||||
*msgEthTx,
|
||||
txData,
|
||||
evmDenom,
|
||||
homestead,
|
||||
istanbul,
|
||||
london,
|
||||
)
|
||||
evmDenom := egcd.evmKeeper.GetEVMDenom(ctx)
|
||||
|
||||
fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, homestead, istanbul, ctx.IsCheckTx())
|
||||
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 {
|
||||
minPriority = priority
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: change to typed events
|
||||
ctx.EventManager().EmitEvents(events)
|
||||
|
||||
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
|
||||
blockGasLimit := ethermint.BlockGasLimit(ctx)
|
||||
|
||||
// NOTE: safety check
|
||||
if blockGasLimit > 0 {
|
||||
// generate a copy of the gas pool (i.e block gas meter) to see if we've run out of gas for this block
|
||||
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp
|
||||
gasPool := sdk.NewGasMeter(blockGasLimit)
|
||||
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
|
||||
// return error if the tx gas is greater than the block limit (max gas)
|
||||
|
||||
// NOTE: it's important here to use the gas wanted instead of the gas consumed
|
||||
// from the tx gas pool. The later only has the value so far since the
|
||||
// EthSetupContextDecorator so it will never exceed the block gas limit.
|
||||
if gasWanted > blockGasLimit {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrOutOfGas,
|
||||
"tx gas (%d) exceeds block gas limit (%d)",
|
||||
gasWanted,
|
||||
blockGasLimit,
|
||||
)
|
||||
}
|
||||
|
||||
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
|
||||
gasConsumed := ctx.GasMeter().GasConsumed()
|
||||
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
||||
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
||||
// Set tx GasMeter with a limit of GasWanted (i.e gas limit from the Ethereum tx).
|
||||
// The gas consumed will be then reset to the gas used by the state transition
|
||||
// in the EVM.
|
||||
|
||||
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
|
||||
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() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
baseFee := ctd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
return ctx, errorsmod.Wrapf(
|
||||
err,
|
||||
"failed to create an ethereum core.Message from signer %T", signer,
|
||||
)
|
||||
}
|
||||
|
||||
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
||||
if baseFee == nil {
|
||||
return ctx, errorsmod.Wrap(
|
||||
evmtypes.ErrInvalidBaseFee,
|
||||
"base fee is supported but evm block context value is nil",
|
||||
)
|
||||
}
|
||||
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFee,
|
||||
"max fee per gas less than block base fee (%s < %s)",
|
||||
coreMsg.GasFeeCap(), baseFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
|
||||
cfg := &evmtypes.EVMConfig{
|
||||
ChainConfig: ethCfg,
|
||||
@ -300,35 +300,20 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
CoinBase: common.Address{},
|
||||
BaseFee: baseFee,
|
||||
}
|
||||
|
||||
stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
|
||||
evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB)
|
||||
|
||||
// check that caller has enough balance to cover asset transfer for **topmost** call
|
||||
// NOTE: here the gas consumed is from the context with the infinite gas meter
|
||||
if coreMsg.Value().Sign() > 0 && !evm.Context().CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFunds,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFunds,
|
||||
"failed to transfer %s from address %s using the EVM block context transfer function",
|
||||
coreMsg.Value(),
|
||||
coreMsg.From(),
|
||||
)
|
||||
}
|
||||
|
||||
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
||||
if baseFee == nil {
|
||||
return ctx, sdkerrors.Wrap(
|
||||
evmtypes.ErrInvalidBaseFee,
|
||||
"base fee is supported but evm block context value is nil",
|
||||
)
|
||||
}
|
||||
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee,
|
||||
"max fee per gas less than block base fee (%s < %s)",
|
||||
coreMsg.GasFeeCap(), baseFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
@ -353,19 +338,19 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
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))
|
||||
return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||
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
|
||||
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
|
||||
if acc == nil {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownAddress,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrUnknownAddress,
|
||||
"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
|
||||
// with same sender, they'll be accepted.
|
||||
if txData.GetNonce() != nonce {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidSequence,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInvalidSequence,
|
||||
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
@ -389,216 +374,3 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
|
||||
type EthValidateBasicDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
|
||||
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
|
||||
return EthValidateBasicDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle handles basic validation of tx
|
||||
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// no need to validate basic on recheck tx, call next antehandler
|
||||
if ctx.IsReCheckTx() {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
err := tx.ValidateBasic()
|
||||
// ErrNoSignatures is fine with eth tx
|
||||
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
|
||||
return ctx, sdkerrors.Wrap(err, "tx basic validation failed")
|
||||
}
|
||||
|
||||
// For eth type cosmos tx, some fields should be veified as zero values,
|
||||
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
|
||||
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)
|
||||
}
|
||||
|
@ -9,65 +9,13 @@ import (
|
||||
"github.com/cerc-io/laconicd/app/ante"
|
||||
"github.com/cerc-io/laconicd/server/config"
|
||||
"github.com/cerc-io/laconicd/tests"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cerc-io/laconicd/x/evm/statedb"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
|
||||
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() {
|
||||
dec := ante.NewEthAccountVerificationDecorator(
|
||||
suite.app.AccountKeeper, suite.app.EvmKeeper,
|
||||
@ -233,6 +181,9 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
tx2.From = addr.Hex()
|
||||
tx2Priority := int64(1)
|
||||
|
||||
tx3GasLimit := ethermint.BlockGasLimit(suite.ctx) + uint64(1)
|
||||
tx3 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx3GasLimit, gasPrice, nil, nil, nil, ðtypes.AccessList{{Address: addr, StorageKeys: nil}})
|
||||
|
||||
dynamicFeeTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit,
|
||||
nil, // gasPrice
|
||||
new(big.Int).Add(baseFee, big.NewInt(evmtypes.DefaultPriorityReduction.Int64()*2)), // gasFeeCap
|
||||
@ -269,6 +220,14 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
false, false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"gas limit above block gas limit",
|
||||
tx3,
|
||||
math.MaxUint64,
|
||||
func() {},
|
||||
false, false,
|
||||
0,
|
||||
},
|
||||
{
|
||||
"not enough balance for fees",
|
||||
tx2,
|
||||
@ -320,6 +279,17 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
true, false,
|
||||
dynamicFeeTxPriority,
|
||||
},
|
||||
{
|
||||
"success - gas limit on gasMeter is set on ReCheckTx mode",
|
||||
dynamicFeeTx,
|
||||
0, // for reCheckTX mode, gas limit should be set to 0
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1001000000000000))
|
||||
suite.ctx = suite.ctx.WithIsReCheckTx(true)
|
||||
},
|
||||
true, false,
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,13 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cerc-io/laconicd/x/evm/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
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"
|
||||
)
|
||||
|
||||
@ -64,7 +65,7 @@ func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker {
|
||||
baseFeeInt := sdkmath.NewIntFromBigInt(baseFee)
|
||||
|
||||
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.
|
||||
@ -112,7 +113,7 @@ func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.FeeTx) (sdk.Coi
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ package ante
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
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
|
||||
@ -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) {
|
||||
params := gwd.evmKeeper.GetParams(ctx)
|
||||
ethCfg := params.ChainConfig.EthereumConfig(gwd.evmKeeper.ChainID())
|
||||
chainCfg := gwd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(gwd.evmKeeper.ChainID())
|
||||
|
||||
blockHeight := big.NewInt(ctx.BlockHeight())
|
||||
isLondon := ethCfg.IsLondon(blockHeight)
|
||||
@ -39,12 +39,12 @@ func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
|
||||
}
|
||||
|
||||
gasWanted := feeTx.GetGas()
|
||||
feeMktParams := gwd.feeMarketKeeper.GetParams(ctx)
|
||||
isBaseFeeEnabled := gwd.feeMarketKeeper.GetBaseFeeEnabled(ctx)
|
||||
|
||||
// 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 {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
118
app/ante/fees.go
118
app/ante/fees.go
@ -3,8 +3,9 @@ package ante
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
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"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@ -20,14 +21,50 @@ type MinGasPriceDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
type EthMinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
|
||||
// as the local validator's minimum gasFee (defined in validator config).
|
||||
// If fee is too low, decorator returns error and tx is rejected from mempool.
|
||||
// Note this only applies when ctx.CheckTx = true
|
||||
// If fee is high enough or not CheckTx, then call next AnteHandler
|
||||
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
|
||||
type EthMempoolFeeDecorator struct {
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
// NewMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
|
||||
// Cosmos transactions.
|
||||
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
|
||||
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
// NewEthMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
|
||||
// Ethereum transactions.
|
||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
// NewEthMempoolFeeDecorator creates a new NewEthMempoolFeeDecorator instance used only for
|
||||
// Ethereum transactions.
|
||||
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
|
||||
return EthMempoolFeeDecorator{
|
||||
evmKeeper: ek,
|
||||
}
|
||||
}
|
||||
|
||||
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return ctx, 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
|
||||
@ -37,10 +74,10 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
evmParams := mpd.evmKeeper.GetParams(ctx)
|
||||
evmDenom := mpd.evmKeeper.GetEVMDenom(ctx)
|
||||
minGasPrices := sdk.DecCoins{
|
||||
{
|
||||
Denom: evmParams.EvmDenom,
|
||||
Denom: evmDenom,
|
||||
Amount: minGasPrice,
|
||||
},
|
||||
}
|
||||
@ -62,7 +99,7 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
}
|
||||
|
||||
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.",
|
||||
feeCoins,
|
||||
requiredFees)
|
||||
@ -71,20 +108,8 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
type EthMinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
// AnteHandle ensures that the that the effective fee from the transaction is greater than the
|
||||
// minimum global fee, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument).
|
||||
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
|
||||
@ -93,15 +118,15 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
paramsEvm := empd.evmKeeper.GetParams(ctx)
|
||||
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID())
|
||||
chainCfg := empd.evmKeeper.GetChainConfig(ctx)
|
||||
ethCfg := chainCfg.EthereumConfig(empd.evmKeeper.ChainID())
|
||||
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrUnknownRequest,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrUnknownRequest,
|
||||
"invalid message type %T, expected %T",
|
||||
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)
|
||||
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 {
|
||||
@ -133,8 +158,8 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
fee := sdk.NewDecFromBigInt(feeAmt)
|
||||
|
||||
if fee.LT(requiredFee) {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInsufficientFee,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInsufficientFee,
|
||||
"provided fee < minimum global fee (%d < %d). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", //nolint:lll
|
||||
fee.TruncateInt().Int64(), requiredFee.TruncateInt().Int64(),
|
||||
)
|
||||
@ -143,3 +168,44 @@ func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simul
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func (s AnteTestSuite) TestMinGasPriceDecorator() {
|
||||
return &invalidTx{}
|
||||
},
|
||||
false,
|
||||
"must be a FeeTx",
|
||||
"invalid transaction type",
|
||||
false,
|
||||
},
|
||||
{
|
||||
@ -345,3 +345,7 @@ func (s AnteTestSuite) TestEthMinGasPriceDecorator() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestEthMempoolFeeDecorator() {
|
||||
// TODO: add test
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
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/x/auth/ante"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
@ -20,7 +21,7 @@ type HandlerOptions struct {
|
||||
AccountKeeper evmtypes.AccountKeeper
|
||||
BankKeeper evmtypes.BankKeeper
|
||||
IBCKeeper *ibckeeper.Keeper
|
||||
FeeMarketKeeper evmtypes.FeeMarketKeeper
|
||||
FeeMarketKeeper FeeMarketKeeper
|
||||
EvmKeeper EVMKeeper
|
||||
FeegrantKeeper ante.FeegrantKeeper
|
||||
SignModeHandler authsigning.SignModeHandler
|
||||
@ -31,20 +32,20 @@ type HandlerOptions struct {
|
||||
}
|
||||
|
||||
func (options HandlerOptions) validate() error {
|
||||
if options.AccountKeeper == evmtypes.AccountKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
|
||||
if options.AccountKeeper == nil {
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "account keeper is required for AnteHandler")
|
||||
}
|
||||
if options.BankKeeper == evmtypes.BankKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
|
||||
if options.BankKeeper == nil {
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "bank keeper is required for AnteHandler")
|
||||
}
|
||||
if options.SignModeHandler == authsigning.SignModeHandler(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
||||
if options.SignModeHandler == nil {
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "sign mode handler is required for ante builder")
|
||||
}
|
||||
if options.FeeMarketKeeper == evmtypes.FeeMarketKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
|
||||
if options.FeeMarketKeeper == nil {
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "fee market keeper is required for AnteHandler")
|
||||
}
|
||||
if options.EvmKeeper == EVMKeeper(nil) {
|
||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
|
||||
if options.EvmKeeper == nil {
|
||||
return errorsmod.Wrap(errortypes.ErrLogic, "evm keeper is required for AnteHandler")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -70,9 +71,9 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
RejectMessagesDecorator{}, // reject MsgEthereumTxs
|
||||
ante.NewSetUpContextDecorator(),
|
||||
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
@ -86,27 +87,3 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
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),
|
||||
)
|
||||
}
|
||||
|
@ -28,12 +28,15 @@ type EVMKeeper interface {
|
||||
DynamicFeeEVMKeeper
|
||||
|
||||
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM
|
||||
DeductTxCostsFromUserBalance(
|
||||
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
|
||||
) (fees sdk.Coins, priority int64, err error)
|
||||
DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
|
||||
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
|
||||
ResetTransientGasUsed(ctx sdk.Context)
|
||||
GetTxIndexTransient(ctx sdk.Context) uint64
|
||||
GetChainConfig(ctx sdk.Context) evmtypes.ChainConfig
|
||||
GetEVMDenom(ctx sdk.Context) string
|
||||
GetEnableCreate(ctx sdk.Context) bool
|
||||
GetEnableCall(ctx sdk.Context) bool
|
||||
GetAllowUnprotectedTxs(ctx sdk.Context) bool
|
||||
}
|
||||
|
||||
type protoTxProvider interface {
|
||||
@ -44,4 +47,5 @@ type protoTxProvider interface {
|
||||
type FeeMarketKeeper interface {
|
||||
GetParams(ctx sdk.Context) (params feemarkettypes.Params)
|
||||
AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error)
|
||||
GetBaseFeeEnabled(ctx sdk.Context) bool
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/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
|
||||
@ -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) {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrInvalidType,
|
||||
return ctx, errorsmod.Wrapf(
|
||||
errortypes.ErrInvalidType,
|
||||
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
|
||||
)
|
||||
}
|
||||
|
189
app/ante/setup.go
Normal file
189
app/ante/setup.go
Normal 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
42
app/ante/setup_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
64
app/ante/signverify_test.go
Normal file
64
app/ante/signverify_test.go
Normal 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
65
app/ante/sigverify.go
Normal 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)
|
||||
}
|
@ -15,26 +15,32 @@ import (
|
||||
"github.com/cerc-io/laconicd/types"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
cryptocodec "github.com/cerc-io/laconicd/crypto/codec"
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
authz "github.com/cosmos/cosmos-sdk/x/authz"
|
||||
|
||||
"github.com/cerc-io/laconicd/app"
|
||||
ante "github.com/cerc-io/laconicd/app/ante"
|
||||
@ -46,7 +52,8 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||
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"
|
||||
)
|
||||
@ -92,6 +99,8 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.MergeNetsplitBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.ShanghaiBlock = &maxInt
|
||||
evmGenesis.Params.ChainConfig.CancunBlock = &maxInt
|
||||
}
|
||||
if suite.evmParamsOption != nil {
|
||||
suite.evmParamsOption(&evmGenesis.Params)
|
||||
@ -111,6 +120,7 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||
// We're using TestMsg amino encoding in some tests, so register it here.
|
||||
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
||||
eip712.SetEncodingConfig(encodingConfig)
|
||||
|
||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||
|
||||
@ -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 {
|
||||
// Build MsgSend
|
||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
msgSend := banktypes.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||
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 {
|
||||
// Build MsgSend
|
||||
valEthAddr := tests.GenerateAddress()
|
||||
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
||||
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
msgSend := stakingtypes.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(20)))
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgCreateValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgCreateValidator
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
privEd := ed25519.GenPrivKey()
|
||||
msgCreate, err := types3.NewMsgCreateValidator(
|
||||
msgCreate, err := stakingtypes.NewMsgCreateValidator(
|
||||
valAddr,
|
||||
privEd.PubKey(),
|
||||
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)),
|
||||
// TODO: can this values be empty strings?
|
||||
types3.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
||||
types3.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||
stakingtypes.NewDescription("moniker", "indentity", "website", "security_contract", "details"),
|
||||
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
|
||||
sdk.OneInt(),
|
||||
)
|
||||
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 {
|
||||
proposal, ok := types5.ContentFromProposalType("My proposal", "My description", types5.ProposalTypeText)
|
||||
proposal, ok := govtypes.ContentFromProposalType("My proposal", "My description", govtypes.ProposalTypeText)
|
||||
suite.Require().True(ok)
|
||||
msgSubmit, err := types5.NewMsgSubmitProposal(proposal, deposit, from)
|
||||
msgSubmit, err := govtypes.NewMsgSubmitProposal(proposal, deposit, from)
|
||||
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 {
|
||||
@ -311,18 +337,18 @@ func (suite *AnteTestSuite) CreateTestEIP712GrantAllowance(from sdk.AccAddress,
|
||||
grantedAddr := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, granted.Bytes())
|
||||
msgGrant, err := feegrant.NewMsgGrantAllowance(basic, from, grantedAddr.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
||||
return suite.CreateTestEIP712SingleMessageTxBuilder(from, priv, chainId, gas, gasAmount, msgGrant)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712MsgEditValidator(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
valAddr := sdk.ValAddress(from.Bytes())
|
||||
msgEdit := types3.NewMsgEditValidator(
|
||||
msgEdit := stakingtypes.NewMsgEditValidator(
|
||||
valAddr,
|
||||
types3.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
||||
stakingtypes.NewDescription("moniker", "identity", "website", "security_contract", "details"),
|
||||
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 {
|
||||
@ -335,7 +361,72 @@ func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddres
|
||||
})
|
||||
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.
|
||||
@ -376,8 +467,14 @@ func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequenc
|
||||
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,
|
||||
) 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 {
|
||||
var err error
|
||||
|
||||
@ -398,13 +495,13 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
fee := legacytx.NewStdFee(gas, gasAmount)
|
||||
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
||||
|
||||
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil)
|
||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
|
||||
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, msgs, "", nil)
|
||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msgs[0], data, &eip712.FeeDelegationOptions{
|
||||
FeePayer: from,
|
||||
})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
sigHash, err := eip712.ComputeTypedDataHash(typedData)
|
||||
sigHash, _, err := apitypes.TypedDataAndHash(typedData)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Sign typedData
|
||||
@ -442,12 +539,189 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||
err = builder.SetSignatures(sigsV2)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
err = builder.SetMsgs(msg)
|
||||
err = builder.SetMsgs(msgs...)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
// Generate a set of pub/priv keys to be used in creating multi-keys
|
||||
func (suite *AnteTestSuite) GenerateMultipleKeys(n int) ([]cryptotypes.PrivKey, []cryptotypes.PubKey) {
|
||||
privKeys := make([]cryptotypes.PrivKey, n)
|
||||
pubKeys := make([]cryptotypes.PubKey, n)
|
||||
for i := 0; i < n; i++ {
|
||||
privKey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
privKeys[i] = privKey
|
||||
pubKeys[i] = privKey.PubKey()
|
||||
}
|
||||
return privKeys, pubKeys
|
||||
}
|
||||
|
||||
// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard)
|
||||
func (suite *AnteTestSuite) generateSingleSignature(signMode signing.SignMode, privKey cryptotypes.PrivKey, signDocBytes []byte, signType string) (signature signing.SignatureV2) {
|
||||
var (
|
||||
msg []byte
|
||||
err error
|
||||
)
|
||||
|
||||
msg = signDocBytes
|
||||
|
||||
if signType == "EIP-712" {
|
||||
msg, err = eip712.GetEIP712BytesForMsg(signDocBytes)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
sigBytes, _ := privKey.Sign(msg)
|
||||
sigData := &signing.SingleSignatureData{
|
||||
SignMode: signMode,
|
||||
Signature: sigBytes,
|
||||
}
|
||||
|
||||
return signing.SignatureV2{
|
||||
PubKey: privKey.PubKey(),
|
||||
Data: sigData,
|
||||
}
|
||||
}
|
||||
|
||||
// generateMultikeySignatures signs a set of messages using each private key within a given multi-key
|
||||
func (suite *AnteTestSuite) generateMultikeySignatures(signMode signing.SignMode, privKeys []cryptotypes.PrivKey, signDocBytes []byte, signType string) (signatures []signing.SignatureV2) {
|
||||
n := len(privKeys)
|
||||
signatures = make([]signing.SignatureV2, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
privKey := privKeys[i]
|
||||
currentType := signType
|
||||
|
||||
// If mixed type, alternate signing type on each iteration
|
||||
if signType == "mixed" {
|
||||
if i%2 == 0 {
|
||||
currentType = "EIP-712"
|
||||
} else {
|
||||
currentType = "Standard"
|
||||
}
|
||||
}
|
||||
|
||||
signatures[i] = suite.generateSingleSignature(
|
||||
signMode,
|
||||
privKey,
|
||||
signDocBytes,
|
||||
currentType,
|
||||
)
|
||||
}
|
||||
|
||||
return signatures
|
||||
}
|
||||
|
||||
// RegisterAccount creates an account with the keeper and populates the initial balance
|
||||
func (suite *AnteTestSuite) RegisterAccount(pubKey cryptotypes.PubKey, balance *big.Int) {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, sdk.AccAddress(pubKey.Address()))
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, common.BytesToAddress(pubKey.Address()), balance)
|
||||
}
|
||||
|
||||
// createSignerBytes generates sign doc bytes using the given parameters
|
||||
func (suite *AnteTestSuite) createSignerBytes(chainId string, signMode signing.SignMode, pubKey cryptotypes.PubKey, txBuilder client.TxBuilder) []byte {
|
||||
acc, err := sdkante.GetSignerAcc(suite.ctx, suite.app.AccountKeeper, sdk.AccAddress(pubKey.Address()))
|
||||
suite.Require().NoError(err)
|
||||
signerInfo := authsigning.SignerData{
|
||||
Address: sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), acc.GetAddress().Bytes()),
|
||||
ChainID: chainId,
|
||||
AccountNumber: acc.GetAccountNumber(),
|
||||
Sequence: acc.GetSequence(),
|
||||
PubKey: pubKey,
|
||||
}
|
||||
|
||||
signerBytes, err := suite.clientCtx.TxConfig.SignModeHandler().GetSignBytes(
|
||||
signMode,
|
||||
signerInfo,
|
||||
txBuilder.GetTx(),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return signerBytes
|
||||
}
|
||||
|
||||
// createBaseTxBuilder creates a TxBuilder to be used for Single- or Multi-signing
|
||||
func (suite *AnteTestSuite) createBaseTxBuilder(msg sdk.Msg, gas uint64) client.TxBuilder {
|
||||
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
txBuilder.SetGasLimit(gas)
|
||||
txBuilder.SetFeeAmount(sdk.NewCoins(
|
||||
sdk.NewCoin("aphoton", sdk.NewInt(10000)),
|
||||
))
|
||||
|
||||
err := txBuilder.SetMsgs(msg)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txBuilder.SetMemo("")
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
// CreateTestSignedMultisigTx creates and sign a multi-signed tx for the given message. `signType` indicates whether to use standard signing ("Standard"),
|
||||
// EIP-712 signing ("EIP-712"), or a mix of the two ("mixed").
|
||||
func (suite *AnteTestSuite) CreateTestSignedMultisigTx(privKeys []cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainId string, gas uint64, signType string) client.TxBuilder {
|
||||
pubKeys := make([]cryptotypes.PubKey, len(privKeys))
|
||||
for i, privKey := range privKeys {
|
||||
pubKeys[i] = privKey.PubKey()
|
||||
}
|
||||
|
||||
// Re-derive multikey
|
||||
numKeys := len(privKeys)
|
||||
multiKey := kmultisig.NewLegacyAminoPubKey(numKeys, pubKeys)
|
||||
|
||||
suite.RegisterAccount(multiKey, big.NewInt(10000000000))
|
||||
|
||||
txBuilder := suite.createBaseTxBuilder(msg, gas)
|
||||
|
||||
// Prepare signature field
|
||||
sig := multisig.NewMultisig(len(pubKeys))
|
||||
txBuilder.SetSignatures(signing.SignatureV2{
|
||||
PubKey: multiKey,
|
||||
Data: sig,
|
||||
})
|
||||
|
||||
signerBytes := suite.createSignerBytes(chainId, signMode, multiKey, txBuilder)
|
||||
|
||||
// Sign for each key and update signature field
|
||||
sigs := suite.generateMultikeySignatures(signMode, privKeys, signerBytes, signType)
|
||||
for _, pkSig := range sigs {
|
||||
err := multisig.AddSignatureV2(sig, pkSig, pubKeys)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
txBuilder.SetSignatures(signing.SignatureV2{
|
||||
PubKey: multiKey,
|
||||
Data: sig,
|
||||
})
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestSingleSignedTx(privKey cryptotypes.PrivKey, signMode signing.SignMode, msg sdk.Msg, chainId string, gas uint64, signType string) client.TxBuilder {
|
||||
pubKey := privKey.PubKey()
|
||||
|
||||
suite.RegisterAccount(pubKey, big.NewInt(10000000000))
|
||||
|
||||
txBuilder := suite.createBaseTxBuilder(msg, gas)
|
||||
|
||||
// Prepare signature field
|
||||
sig := signing.SingleSignatureData{}
|
||||
txBuilder.SetSignatures(signing.SignatureV2{
|
||||
PubKey: pubKey,
|
||||
Data: &sig,
|
||||
})
|
||||
|
||||
signerBytes := suite.createSignerBytes(chainId, signMode, pubKey, txBuilder)
|
||||
|
||||
sigData := suite.generateSingleSignature(signMode, privKey, signerBytes, signType)
|
||||
txBuilder.SetSignatures(sigData)
|
||||
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func NextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
45
app/app.go
45
app/app.go
@ -2,6 +2,7 @@ package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/grpc/node"
|
||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
@ -26,6 +28,7 @@ import (
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
||||
"github.com/cosmos/cosmos-sdk/store/streaming"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"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/app/ante"
|
||||
"github.com/cerc-io/laconicd/ethereum/eip712"
|
||||
srvflags "github.com/cerc-io/laconicd/server/flags"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
"github.com/cerc-io/laconicd/x/evm"
|
||||
@ -184,7 +188,7 @@ var (
|
||||
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
||||
govtypes.ModuleName: {authtypes.Burner},
|
||||
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
||||
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
|
||||
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, //nolint:lll // used for secure addition and subtraction of balance using module account
|
||||
auctiontypes.ModuleName: nil,
|
||||
auctiontypes.AuctionBurnModuleAccountName: nil,
|
||||
registrytypes.ModuleName: nil,
|
||||
@ -199,8 +203,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
var _ simapp.App = (*EthermintApp)(nil)
|
||||
|
||||
// var _ server.Application (*EthermintApp)(nil)
|
||||
|
||||
// EthermintApp implements an extended ABCI application. It is an application
|
||||
@ -256,9 +258,6 @@ type EthermintApp struct {
|
||||
// the module manager
|
||||
mm *module.Manager
|
||||
|
||||
// simulation manager
|
||||
sm *module.SimulationManager
|
||||
|
||||
// the configurator
|
||||
configurator module.Configurator
|
||||
}
|
||||
@ -280,6 +279,8 @@ func NewEthermintApp(
|
||||
cdc := encodingConfig.Amino
|
||||
interfaceRegistry := encodingConfig.InterfaceRegistry
|
||||
|
||||
eip712.SetEncodingConfig(encodingConfig)
|
||||
|
||||
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
|
||||
bApp := baseapp.NewBaseApp(
|
||||
appName,
|
||||
@ -313,6 +314,12 @@ func NewEthermintApp(
|
||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
||||
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{
|
||||
BaseApp: bApp,
|
||||
cdc: cdc,
|
||||
@ -658,17 +665,6 @@ func NewEthermintApp(
|
||||
// add test gRPC service for testing gRPC queries in isolation
|
||||
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
||||
|
||||
// create the simulation manager and define the order of the modules for deterministic simulations
|
||||
//
|
||||
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
||||
// transactions
|
||||
overrideModules := map[string]module.AppModuleSimulation{
|
||||
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
||||
}
|
||||
app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules)
|
||||
|
||||
app.sm.RegisterStoreDecoders()
|
||||
|
||||
// initialize stores
|
||||
app.MountKVStores(keys)
|
||||
app.MountTransientStores(tkeys)
|
||||
@ -718,6 +714,8 @@ func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted u
|
||||
EvmKeeper: app.EvmKeeper,
|
||||
FeeMarketKeeper: app.FeeMarketKeeper,
|
||||
MaxTxGasWanted: maxGasWanted,
|
||||
ExtensionOptionChecker: ethermint.HasDynamicFeeExtensionOption,
|
||||
// TxFeeChecker: ante.NewDynamicFeeChecker(app.EvmKeeper),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -838,11 +836,6 @@ func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
|
||||
return subspace
|
||||
}
|
||||
|
||||
// SimulationManager implements the SimulationApp interface
|
||||
func (app *EthermintApp) SimulationManager() *module.SimulationManager {
|
||||
return app.sm
|
||||
}
|
||||
|
||||
// RegisterAPIRoutes registers all application module routes with the provided
|
||||
// API server.
|
||||
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||
@ -851,6 +844,8 @@ func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.
|
||||
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
// Register new tendermint queries routes from grpc-gateway.
|
||||
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
// Register node gRPC service for grpc-gateway.
|
||||
node.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||
|
||||
// Register grpc-gateway routes for all modules.
|
||||
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
|
||||
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
|
||||
statikFS, err := fs.New()
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
127
app/utils.go
127
app/utils.go
@ -5,27 +5,21 @@ import (
|
||||
"math/rand" // #nosec G702
|
||||
"time"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
@ -83,7 +77,7 @@ func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.Genesis
|
||||
// Initialize the chain
|
||||
app.InitChain(
|
||||
abci.RequestInitChain{
|
||||
ChainId: "ethermint_9000-1",
|
||||
ChainId: "laconic_9000-1",
|
||||
Validators: []abci.ValidatorUpdate{},
|
||||
ConsensusParams: DefaultConsensusParams,
|
||||
AppStateBytes: stateBytes,
|
||||
@ -94,96 +88,6 @@ func SetupWithDB(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.Genesis
|
||||
return app
|
||||
}
|
||||
|
||||
// RandomGenesisAccounts is used by the auth module to create random genesis accounts in simulation when a genesis.json is not specified.
|
||||
// In contrast, the default auth module's RandomGenesisAccounts implementation creates only base accounts and vestings accounts.
|
||||
func RandomGenesisAccounts(simState *module.SimulationState) authtypes.GenesisAccounts {
|
||||
emptyCodeHash := crypto.Keccak256(nil)
|
||||
genesisAccs := make(authtypes.GenesisAccounts, len(simState.Accounts))
|
||||
for i, acc := range simState.Accounts {
|
||||
bacc := authtypes.NewBaseAccountWithAddress(acc.Address)
|
||||
|
||||
ethacc := ðermint.EthAccount{
|
||||
BaseAccount: bacc,
|
||||
CodeHash: common.BytesToHash(emptyCodeHash).String(),
|
||||
}
|
||||
genesisAccs[i] = ethacc
|
||||
}
|
||||
|
||||
return genesisAccs
|
||||
}
|
||||
|
||||
// RandomAccounts creates random accounts with an ethsecp256k1 private key
|
||||
// TODO: replace secp256k1.GenPrivKeyFromSecret() with similar function in go-ethereum
|
||||
func RandomAccounts(r *rand.Rand, n int) []simtypes.Account {
|
||||
accs := make([]simtypes.Account, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// don't need that much entropy for simulation
|
||||
privkeySeed := make([]byte, 15)
|
||||
_, _ = r.Read(privkeySeed)
|
||||
|
||||
prv := secp256k1.GenPrivKeyFromSecret(privkeySeed)
|
||||
ethPrv := ðsecp256k1.PrivKey{}
|
||||
_ = ethPrv.UnmarshalAmino(prv.Bytes()) // UnmarshalAmino simply copies the bytes and assigns them to ethPrv.Key
|
||||
accs[i].PrivKey = ethPrv
|
||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||
|
||||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
|
||||
}
|
||||
|
||||
return accs
|
||||
}
|
||||
|
||||
// StateFn returns the initial application state using a genesis or the simulation parameters.
|
||||
// It is a wrapper of simapp.AppStateFn to replace evm param EvmDenom with staking param BondDenom.
|
||||
func StateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
|
||||
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
|
||||
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
|
||||
appStateFn := simapp.AppStateFn(cdc, simManager)
|
||||
appState, simAccs, chainID, genesisTimestamp = appStateFn(r, accs, config)
|
||||
|
||||
rawState := make(map[string]json.RawMessage)
|
||||
err := json.Unmarshal(appState, &rawState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stakingStateBz, ok := rawState[stakingtypes.ModuleName]
|
||||
if !ok {
|
||||
panic("staking genesis state is missing")
|
||||
}
|
||||
|
||||
stakingState := new(stakingtypes.GenesisState)
|
||||
cdc.MustUnmarshalJSON(stakingStateBz, stakingState)
|
||||
|
||||
// we should get the BondDenom and make it the evmdenom.
|
||||
// thus simulation accounts could have positive amount of gas token.
|
||||
bondDenom := stakingState.Params.BondDenom
|
||||
|
||||
evmStateBz, ok := rawState[evmtypes.ModuleName]
|
||||
if !ok {
|
||||
panic("evm genesis state is missing")
|
||||
}
|
||||
|
||||
evmState := new(evmtypes.GenesisState)
|
||||
cdc.MustUnmarshalJSON(evmStateBz, evmState)
|
||||
|
||||
// we should replace the EvmDenom with BondDenom
|
||||
evmState.Params.EvmDenom = bondDenom
|
||||
|
||||
// change appState back
|
||||
rawState[evmtypes.ModuleName] = cdc.MustMarshalJSON(evmState)
|
||||
|
||||
// replace appstate
|
||||
appState, err = json.Marshal(rawState)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return appState, simAccs, chainID, genesisTimestamp
|
||||
}
|
||||
}
|
||||
|
||||
// NewTestGenesisState generate genesis state with single validator
|
||||
func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
|
||||
privVal := mock.NewPV()
|
||||
@ -207,6 +111,29 @@ func NewTestGenesisState(codec codec.Codec) simapp.GenesisState {
|
||||
return genesisStateWithValSet(codec, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
|
||||
}
|
||||
|
||||
// RandomAccounts creates random accounts with an ethsecp256k1 private key
|
||||
// TODO: replace secp256k1.GenPrivKeyFromSecret() with similar function in go-ethereum
|
||||
func RandomAccounts(r *rand.Rand, n int) []simtypes.Account {
|
||||
accs := make([]simtypes.Account, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// don't need that much entropy for simulation
|
||||
privkeySeed := make([]byte, 15)
|
||||
_, _ = r.Read(privkeySeed)
|
||||
|
||||
prv := secp256k1.GenPrivKeyFromSecret(privkeySeed)
|
||||
ethPrv := ðsecp256k1.PrivKey{}
|
||||
_ = ethPrv.UnmarshalAmino(prv.Bytes()) // UnmarshalAmino simply copies the bytes and assigns them to ethPrv.Key
|
||||
accs[i].PrivKey = ethPrv
|
||||
accs[i].PubKey = accs[i].PrivKey.PubKey()
|
||||
accs[i].Address = sdk.AccAddress(accs[i].PubKey.Address())
|
||||
|
||||
accs[i].ConsKey = ed25519.GenPrivKeyFromSecret(privkeySeed)
|
||||
}
|
||||
|
||||
return accs
|
||||
}
|
||||
|
||||
func genesisStateWithValSet(codec codec.Codec, genesisState simapp.GenesisState,
|
||||
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount,
|
||||
balances ...banktypes.Balance,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
version: v1
|
||||
directories:
|
||||
- proto
|
||||
- third_party/proto
|
||||
|
@ -13,57 +13,6 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
4
client/docs/statik/statik.go
vendored
4
client/docs/statik/statik.go
vendored
File diff suppressed because one or more lines are too long
272
client/docs/swagger-ui/swagger.yaml
vendored
272
client/docs/swagger-ui/swagger.yaml
vendored
@ -154,10 +154,13 @@ paths:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
<<<<<<< HEAD
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
...
|
||||
foo := &pb.Foo{}
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
type: string
|
||||
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:
|
||||
- Query
|
||||
/ethermint/evm/v1/eth_call:
|
||||
@ -1524,10 +1561,13 @@ paths:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
type: string
|
||||
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:
|
||||
- Query
|
||||
/ethermint/evm/v1/params:
|
||||
@ -1713,11 +1765,24 @@ paths:
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 =
|
||||
already activated)
|
||||
<<<<<<< HEAD
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 =
|
||||
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: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters
|
||||
using *sdk.Int values
|
||||
@ -1727,7 +1792,11 @@ paths:
|
||||
type: boolean
|
||||
description: >-
|
||||
Allow unprotected transactions defines if replay-protected
|
||||
<<<<<<< HEAD
|
||||
(i.e non EIP155
|
||||
=======
|
||||
(i.e non EIP155
|
||||
>>>>>>> v0.20.0
|
||||
|
||||
signed) transactions can be executed on the state machine.
|
||||
title: Params defines the EVM module parameters
|
||||
@ -1861,10 +1930,13 @@ paths:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
required: false
|
||||
type: string
|
||||
<<<<<<< HEAD
|
||||
- name: trace_config.overrides.merge_fork_block
|
||||
description: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
|
||||
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
|
||||
required: false
|
||||
type: string
|
||||
@ -2498,6 +2588,11 @@ paths:
|
||||
in: query
|
||||
required: false
|
||||
type: boolean
|
||||
- name: trace_config.tracer_json_config
|
||||
description: tracer config.
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: block_number
|
||||
description: block number.
|
||||
in: query
|
||||
@ -2515,6 +2610,18 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
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:
|
||||
- Query
|
||||
/ethermint/evm/v1/trace_tx:
|
||||
@ -2659,10 +2766,13 @@ paths:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
format: byte
|
||||
- name: msg.size
|
||||
description: encoded storage size of the transaction.
|
||||
description: 'DEPRECATED: encoded storage size of the transaction.'
|
||||
in: query
|
||||
required: false
|
||||
type: number
|
||||
@ -2927,10 +3037,22 @@ paths:
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
<<<<<<< HEAD
|
||||
- name: trace_config.overrides.merge_fork_block
|
||||
description: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in
|
||||
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
|
||||
required: false
|
||||
type: string
|
||||
@ -2944,6 +3066,11 @@ paths:
|
||||
in: query
|
||||
required: false
|
||||
type: boolean
|
||||
- name: trace_config.tracer_json_config
|
||||
description: tracer config.
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: block_number
|
||||
description: block number of requested transaction.
|
||||
in: query
|
||||
@ -2961,6 +3088,18 @@ paths:
|
||||
required: false
|
||||
type: string
|
||||
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:
|
||||
- Query
|
||||
/ethermint/evm/v1/validator_account/{cons_address}:
|
||||
@ -3120,10 +3259,13 @@ paths:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
tags:
|
||||
- Query
|
||||
<<<<<<< HEAD
|
||||
/cosmos/auth/v1beta1/accounts:
|
||||
get:
|
||||
summary: Accounts returns all the existing accounts
|
||||
@ -14052,6 +14195,8 @@ paths:
|
||||
type: boolean
|
||||
tags:
|
||||
- Query
|
||||
=======
|
||||
>>>>>>> v0.20.0
|
||||
definitions:
|
||||
ethermint.evm.v1.ChainConfig:
|
||||
type: object
|
||||
@ -14111,11 +14256,22 @@ definitions:
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
<<<<<<< HEAD
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = 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: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
|
||||
values
|
||||
@ -14287,10 +14443,13 @@ definitions:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
foo := &pb.Foo{}
|
||||
if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
if err := any.UnmarshalTo(foo); err != nil {
|
||||
...
|
||||
}
|
||||
|
||||
@ -14344,7 +14503,7 @@ definitions:
|
||||
size:
|
||||
type: number
|
||||
format: double
|
||||
title: encoded storage size of the transaction
|
||||
title: 'DEPRECATED: encoded storage size of the transaction'
|
||||
hash:
|
||||
type: string
|
||||
title: transaction hash in hex format
|
||||
@ -14515,11 +14674,22 @@ definitions:
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
<<<<<<< HEAD
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = 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: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
|
||||
values
|
||||
@ -14529,7 +14699,11 @@ definitions:
|
||||
type: boolean
|
||||
description: >-
|
||||
Allow unprotected transactions defines if replay-protected (i.e non
|
||||
<<<<<<< HEAD
|
||||
EIP155
|
||||
=======
|
||||
EIP155
|
||||
>>>>>>> v0.20.0
|
||||
|
||||
signed) transactions can be executed on the state machine.
|
||||
title: Params defines the EVM module parameters
|
||||
@ -14684,11 +14858,22 @@ definitions:
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
<<<<<<< HEAD
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = 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: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using
|
||||
*sdk.Int values
|
||||
@ -14698,7 +14883,11 @@ definitions:
|
||||
type: boolean
|
||||
description: >-
|
||||
Allow unprotected transactions defines if replay-protected (i.e
|
||||
<<<<<<< HEAD
|
||||
non EIP155
|
||||
=======
|
||||
non EIP155
|
||||
>>>>>>> v0.20.0
|
||||
|
||||
signed) transactions can be executed on the state machine.
|
||||
title: Params defines the EVM module parameters
|
||||
@ -14839,11 +15028,22 @@ definitions:
|
||||
title: >-
|
||||
Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already
|
||||
activated)
|
||||
<<<<<<< HEAD
|
||||
merge_fork_block:
|
||||
type: string
|
||||
title: >-
|
||||
EIP-3675 (TheMerge) switch block (nil = no fork, 0 = 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: >-
|
||||
ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int
|
||||
values
|
||||
@ -14855,6 +15055,9 @@ definitions:
|
||||
enable_return_data:
|
||||
type: boolean
|
||||
title: enable return data capture
|
||||
tracer_json_config:
|
||||
type: string
|
||||
title: tracer config
|
||||
description: TraceConfig holds extra parameters to trace functions.
|
||||
google.protobuf.Any:
|
||||
type: object
|
||||
@ -14958,10 +15161,13 @@ definitions:
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
any, err := anypb.New(foo)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
...
|
||||
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",
|
||||
"value": "1.212s"
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
cosmos.auth.v1beta1.Params:
|
||||
type: object
|
||||
properties:
|
||||
@ -21145,3 +21355,5 @@ definitions:
|
||||
application's
|
||||
|
||||
state transition machine.
|
||||
=======
|
||||
>>>>>>> v0.20.0
|
||||
|
@ -50,18 +50,32 @@ output
|
||||
- armor encrypted private key (saved to file)
|
||||
*/
|
||||
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]
|
||||
|
||||
interactive, _ := cmd.Flags().GetBool(flagInteractive)
|
||||
noBackup, _ := cmd.Flags().GetBool(flagNoBackup)
|
||||
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
|
||||
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
|
||||
|
||||
showMnemonic := !noBackup
|
||||
kb := ctx.Keyring
|
||||
outputFormat := ctx.OutputFormat
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
|
||||
algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
|
||||
keyringAlgos, ledgerAlgos := kb.SupportedAlgorithms()
|
||||
|
||||
// check if the provided signing algorithm is supported by the keyring or
|
||||
// ledger
|
||||
if useLedger {
|
||||
algo, err = keyring.NewSigningAlgoFromString(algoStr, ledgerAlgos)
|
||||
} else {
|
||||
algo, err = keyring.NewSigningAlgoFromString(algoStr, keyringAlgos)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -144,7 +158,6 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
||||
account, _ := cmd.Flags().GetUint32(flagAccount)
|
||||
index, _ := cmd.Flags().GetUint32(flagIndex)
|
||||
hdPath, _ := cmd.Flags().GetString(flagHDPath)
|
||||
useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger)
|
||||
|
||||
if len(hdPath) == 0 {
|
||||
hdPath = hd.CreateHDPath(coinType, account, index).String()
|
||||
@ -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 useLedger {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ import (
|
||||
"github.com/cerc-io/laconicd/version"
|
||||
)
|
||||
|
||||
const (
|
||||
flagLong = "long"
|
||||
)
|
||||
const flagLong = "long"
|
||||
|
||||
func init() {
|
||||
infoCmd.Flags().Bool(flagLong, false, "Print full information")
|
||||
|
@ -32,7 +32,7 @@ const (
|
||||
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
|
||||
func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
|
||||
Use: "add-genesis-account ADDRESS_OR_KEY_NAME COIN...",
|
||||
Short: "Add a genesis account to genesis.json",
|
||||
Long: `Add a genesis account to genesis.json. The provided account must specify
|
||||
the account address or key name and a list of initial coins. If a key name is given,
|
||||
|
@ -37,13 +37,14 @@ import (
|
||||
"github.com/cerc-io/laconicd/client/debug"
|
||||
"github.com/cerc-io/laconicd/crypto/hd"
|
||||
"github.com/cerc-io/laconicd/encoding"
|
||||
"github.com/cerc-io/laconicd/ethereum/eip712"
|
||||
"github.com/cerc-io/laconicd/server"
|
||||
servercfg "github.com/cerc-io/laconicd/server/config"
|
||||
srvflags "github.com/cerc-io/laconicd/server/flags"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
)
|
||||
|
||||
const EnvPrefix = "ETHERMINT"
|
||||
const EnvPrefix = "LACONIC"
|
||||
|
||||
// NewRootCmd creates a new root command for simd. It is called once in the
|
||||
// main function.
|
||||
@ -61,9 +62,11 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
||||
WithKeyringOptions(hd.EthSecp256k1Option()).
|
||||
WithViper(EnvPrefix)
|
||||
|
||||
eip712.SetEncodingConfig(encodingConfig)
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "laconicd",
|
||||
Short: "Ethermint Daemon",
|
||||
Short: "Laconic Daemon",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
|
||||
// set the default command outputs
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
@ -182,6 +185,7 @@ func txCommand() *cobra.Command {
|
||||
authcmd.GetBroadcastCommand(),
|
||||
authcmd.GetEncodeCommand(),
|
||||
authcmd.GetDecodeCommand(),
|
||||
authcmd.GetAuxToFeeCommand(),
|
||||
)
|
||||
|
||||
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.SetIndexEvents(cast.ToStringSlice(appOpts.Get(sdkserver.FlagIndexEvents))),
|
||||
baseapp.SetSnapshot(snapshotStore, snapshotOptions),
|
||||
baseapp.SetIAVLCacheSize(cast.ToInt(appOpts.Get(sdkserver.FlagIAVLCacheSize))),
|
||||
baseapp.SetIAVLDisableFastNode(cast.ToBool(appOpts.Get(sdkserver.FlagDisableIAVLFastNode))),
|
||||
)
|
||||
|
||||
return ethermintApp
|
||||
|
@ -6,11 +6,12 @@ import (
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"github.com/cerc-io/laconicd/ethereum/eip712"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
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"
|
||||
|
||||
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||
)
|
||||
|
||||
@ -182,7 +183,7 @@ func (pubKey PubKey) MarshalAmino() ([]byte, error) {
|
||||
// UnmarshalAmino overrides Amino binary marshaling.
|
||||
func (pubKey *PubKey) UnmarshalAmino(bz []byte) error {
|
||||
if len(bz) != PubKeySize {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(bz))
|
||||
return errorsmod.Wrapf(errortypes.ErrInvalidPubKey, "invalid pubkey size, expected %d, got %d", PubKeySize, len(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
|
||||
// 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.
|
||||
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 {
|
||||
// remove recovery ID (V) if contained in the signature
|
||||
sig = sig[:len(sig)-1]
|
||||
|
4
crypto/ethsecp256k1/keys.pb.go
generated
4
crypto/ethsecp256k1/keys.pb.go
generated
@ -5,7 +5,7 @@ package ethsecp256k1
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
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
|
||||
// key format.
|
||||
type PubKey struct {
|
||||
// key is the public key in byte form
|
||||
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
|
||||
// Tendermint's PrivateKey interface.
|
||||
type PrivKey struct {
|
||||
// key is the private key in byte form
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -10,7 +11,6 @@ import (
|
||||
|
||||
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
amino "github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
@ -20,10 +20,10 @@ import (
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
)
|
||||
|
||||
var TestCodec codec.Codec
|
||||
var TestCodec amino.Codec
|
||||
|
||||
func init() {
|
||||
cdc := codec.NewLegacyAmino()
|
||||
cdc := amino.NewLegacyAmino()
|
||||
cryptocodec.RegisterCrypto(cdc)
|
||||
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
@ -31,12 +31,18 @@ func init() {
|
||||
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) {
|
||||
dir := t.TempDir()
|
||||
mockIn := strings.NewReader("")
|
||||
|
||||
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, TestCodec, EthSecp256k1Option())
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -68,7 +74,9 @@ func TestKeyring(t *testing.T) {
|
||||
privkey := EthSecp256k1.Generate()(bz)
|
||||
addr := common.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
|
||||
os.Setenv(hdWalletFixEnv, "true")
|
||||
wallet, err := hdwallet.NewFromMnemonic(mnemonic)
|
||||
os.Setenv(hdWalletFixEnv, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
path := hdwallet.MustParseDerivationPath(hdPath)
|
||||
|
@ -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 |
|
||||
| `enable_memory` | [bool](#bool) | | enable memory 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. |
|
||||
| `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_hash` | [string](#string) | | block hex hash |
|
||||
| `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_hash` | [string](#string) | | block hex hash 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 |
|
||||
|
||||
|
||||
|
||||
|
@ -14,35 +14,17 @@ import (
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/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"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"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
|
||||
// into an EIP712-compatible TypedData request.
|
||||
func WrapTxToTypedData(
|
||||
@ -55,7 +37,20 @@ func WrapTxToTypedData(
|
||||
txData := make(map[string]interface{})
|
||||
|
||||
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 {
|
||||
setRecordMsg := msg.(*registry.MsgSetRecord)
|
||||
var attr []interface{}
|
||||
for _, b := range setRecordMsg.Payload.Record.Attributes.Value {
|
||||
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{}{ //nolint:lll
|
||||
"type_url": setRecordMsg.Payload.Record.Attributes.TypeUrl,
|
||||
"value": attr,
|
||||
}
|
||||
}
|
||||
|
||||
if txData["msgs"].([]interface{})[0].(map[string]interface{})["value"].(map[string]interface{})["payload"] != nil {
|
||||
@ -105,7 +100,7 @@ func WrapTxToTypedData(
|
||||
if feeDelegation != nil {
|
||||
feeInfo, ok := txData["fee"].(map[string]interface{})
|
||||
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()
|
||||
@ -238,7 +233,11 @@ func traverseFields(
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
var field reflect.Value
|
||||
var (
|
||||
field reflect.Value
|
||||
err error
|
||||
)
|
||||
|
||||
if v.IsValid() {
|
||||
field = v.Field(i)
|
||||
}
|
||||
@ -247,23 +246,15 @@ func traverseFields(
|
||||
fieldName := jsonNameFromTag(t.Field(i).Tag)
|
||||
|
||||
if fieldType == cosmosAnyType {
|
||||
any, ok := field.Interface().(*codectypes.Any)
|
||||
if !ok {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "%T", field.Interface())
|
||||
// Unpack field, value as Any
|
||||
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
anyWrapper := &cosmosAnyWrapper{
|
||||
Type: any.TypeUrl,
|
||||
}
|
||||
|
||||
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 field is an empty value, do not include in types, since it will not be present in the object
|
||||
if field.IsZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
// If its a nil pointer, do not include in types
|
||||
@ -305,6 +296,12 @@ func traverseFields(
|
||||
fieldType = fieldType.Elem()
|
||||
field = field.Index(0)
|
||||
isCollection = true
|
||||
|
||||
if fieldType == cosmosAnyType {
|
||||
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
@ -395,6 +392,27 @@ func jsonNameFromTag(tag reflect.StructTag) string {
|
||||
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
|
||||
//
|
||||
// this is needed for Geth's own signing code which doesn't
|
||||
@ -497,7 +515,7 @@ func typToEth(typ reflect.Type) string {
|
||||
func doRecover(err *error) {
|
||||
if r := recover(); r != nil {
|
||||
if e, ok := r.(error); ok {
|
||||
e = sdkerrors.Wrap(e, "panicked with error")
|
||||
e = errorsmod.Wrap(e, "panicked with error")
|
||||
*err = e
|
||||
return
|
||||
}
|
||||
|
432
ethereum/eip712/eip712_test.go
Normal file
432
ethereum/eip712/eip712_test.go
Normal 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 := ðsecp256k1.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
299
ethereum/eip712/encoding.go
Normal 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
|
||||
}
|
64
go.mod
64
go.mod
@ -1,20 +1,24 @@
|
||||
module github.com/cerc-io/laconicd
|
||||
|
||||
go 1.18
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
cosmossdk.io/math v1.0.0-beta.3
|
||||
github.com/99designs/gqlgen v0.17.20
|
||||
cosmossdk.io/errors v1.0.0-beta.7
|
||||
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/btcsuite/btcd v0.22.1
|
||||
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/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/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/go-chi/chi/v5 v5.0.7
|
||||
github.com/gogo/protobuf v1.3.3
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gorilla/mux v1.8.0
|
||||
@ -26,27 +30,26 @@ require (
|
||||
github.com/ipfs/go-ipld-cbor v0.0.6
|
||||
github.com/ipld/go-ipld-prime v0.18.0
|
||||
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
|
||||
github.com/multiformats/go-multihash v0.2.1
|
||||
github.com/onsi/ginkgo/v2 v2.2.0
|
||||
github.com/onsi/gomega v1.20.2
|
||||
github.com/multiformats/go-multihash v0.2.0
|
||||
github.com/onsi/ginkgo/v2 v2.5.1
|
||||
github.com/onsi/gomega v1.24.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rakyll/statik v0.1.7
|
||||
github.com/regen-network/cosmos-proto v0.3.1
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/spf13/cast v1.5.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.14.0
|
||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
||||
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/tyler-smith/go-bip39 v1.1.0
|
||||
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
|
||||
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/protobuf v1.28.1
|
||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
@ -57,7 +60,6 @@ require (
|
||||
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||
cloud.google.com/go/iam v0.8.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
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||
@ -69,7 +71,7 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.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/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
@ -77,13 +79,11 @@ require (
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||
github.com/coinbase/rosetta-sdk-go v0.7.9 // indirect
|
||||
github.com/confio/ics23/go v0.7.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.4 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7 // indirect
|
||||
github.com/confio/ics23/go v0.9.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.3 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
||||
github.com/cosmos/ledger-go v0.9.2 // indirect
|
||||
github.com/cosmos/iavl v0.19.4 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
|
||||
github.com/creachadair/taskgroup v0.3.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
@ -97,11 +97,12 @@ require (
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.0.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
@ -139,7 +140,7 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
||||
github.com/klauspost/compress v1.15.9 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/lib/pq v1.10.6 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
@ -170,9 +171,10 @@ require (
|
||||
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||
github.com/prometheus/client_model v0.2.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/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/rs/zerolog v1.27.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
@ -191,7 +193,8 @@ require (
|
||||
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.8 // 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.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
@ -211,10 +214,13 @@ require (
|
||||
)
|
||||
|
||||
replace (
|
||||
// use cosmos keyring
|
||||
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.
|
||||
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
|
||||
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
|
||||
)
|
||||
|
137
go.sum
137
go.sum
@ -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=
|
||||
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/math v1.0.0-beta.3 h1:TbZxSopz2LqjJ7aXYfn7nJSb8vNaBklW6BLpcei1qwM=
|
||||
cosmossdk.io/math v1.0.0-beta.3/go.mod h1:3LYasri3Zna4XpbrTNdKsWmD5fHHkaNAod/mNT9XdE4=
|
||||
cosmossdk.io/math v1.0.0-beta.4 h1:JtKedVLGzA0vv84xjYmZ75RKG35Kf2WwcFu8IjRkIIw=
|
||||
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=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||
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/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.20/go.mod h1:Mja2HI23kWT1VRH09hvWshFgOzKswpO20o4ScpJIES4=
|
||||
github.com/99designs/gqlgen v0.17.22 h1:TOcrF8t0T3I0za9JD3CB6ehq7dDEMjR9Onikf8Lc/04=
|
||||
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.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
|
||||
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/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/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/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
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/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/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.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
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/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.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
|
||||
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.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
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/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-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
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/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/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.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=
|
||||
@ -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/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/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44=
|
||||
github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7 h1:yqYUOHF2jopwZh4dVQp3xgqwftE5/2hkrwIV6vkUbO0=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-alpha7/go.mod h1:dosO4pSAbJF8zWCzCoTWP7nNsjcvSUBQmniFxDg5daw=
|
||||
github.com/cosmos/cosmos-sdk v0.46.3 h1:2jdJYcSwh4AtFJKGoNGvmEy2mKDWtGaVZphGpvedljQ=
|
||||
github.com/cosmos/cosmos-sdk v0.46.3/go.mod h1:AynIAjXwtS3T/ApdhNCz/7/KGMbZSUBbKRTcbukb2ic=
|
||||
github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk=
|
||||
github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.1 h1:iDL5qh++NoXxG8hSy93FdYJut4XfgbShIocllGaXx/0=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.1/go.mod h1:8k2GNZghi5sDRFw/scPL8gMSowT1vDA+5ouxL8GjaUE=
|
||||
github.com/cosmos/cosmos-sdk v0.46.7 h1:dkGy9y2ewgqvawrUOuWb2oz3MdotVduokyreXC4bS0s=
|
||||
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 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
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/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
|
||||
github.com/cosmos/iavl v0.19.3 h1:cESO0OwTTxQm5rmyESKW+zESheDUYI7CcZDWWDwnuxg=
|
||||
github.com/cosmos/iavl v0.19.3/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.0.1/go.mod h1:LX0DHLW3dfi/1e4BJzi8MGLWmQ4DSraPEgVjyo3VzAo=
|
||||
github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok=
|
||||
github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw=
|
||||
github.com/cosmos/ibc-go/v5 v5.2.0 h1:LxwttRQqdUJpQ3/Gc3XPg5lkRo3pcbzx65dxFIY6ONE=
|
||||
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/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
|
||||
github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
|
||||
github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI=
|
||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
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.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/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
||||
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/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-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-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||
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/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.19 h1:EOR5JbL4MD5yeOqv8W2iC1s4NximrTjqFccUz8lyBRA=
|
||||
github.com/ethereum/go-ethereum v1.10.19/go.mod h1:IJBNMtzKcNHPtllYihy6BL2IgK1u+32JriaTbdt4v+w=
|
||||
github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s=
|
||||
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/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||
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/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.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
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/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
||||
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
|
||||
@ -367,6 +367,8 @@ github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjX
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -384,6 +386,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.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||
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.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
@ -477,7 +481,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.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.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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
@ -687,8 +690,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.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.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||
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/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||
@ -784,7 +787,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/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.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.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
@ -816,8 +818,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-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.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
|
||||
github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
|
||||
github.com/multiformats/go-multihash v0.2.0 h1:oytJb9ZA1OUW0r0f9ea18GiaPOo4SXyc7p2movyUuo4=
|
||||
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/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@ -848,17 +850,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.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
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.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
|
||||
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.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.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY=
|
||||
github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
|
||||
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/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/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=
|
||||
@ -939,8 +941,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.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.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
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/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
|
||||
@ -958,15 +961,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 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.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.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||
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/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
|
||||
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/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/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=
|
||||
@ -1005,8 +1010,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/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
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.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
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.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
@ -1015,8 +1020,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/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
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.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
||||
github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
|
||||
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-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=
|
||||
@ -1051,8 +1056,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/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
|
||||
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
|
||||
github.com/tendermint/tendermint v0.34.22 h1:XMhtC8s8QqJO4l/dn+TkQvevTRSow3Vixjclr41o+2Q=
|
||||
github.com/tendermint/tendermint v0.34.22/go.mod h1:YpP5vBEAKUT4g6oyfjKgFeZmdB/GjkJAxfF+cgmJg6Y=
|
||||
github.com/tendermint/tendermint v0.34.24 h1:879MKKJWYYPJEMMKME+DWUTY4V9f/FBpnZDI82ky+4k=
|
||||
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/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I=
|
||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@ -1083,9 +1088,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/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
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/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.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/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
@ -1101,6 +1108,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/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/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/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@ -1110,9 +1118,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.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
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-0.20220302062450-5552068d2266 h1:O9XLFXGkVswDFmH9LaYpqu+r/AAFWqr0DL6V00KEVFg=
|
||||
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
|
||||
github.com/zondax/hid v0.9.1/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.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
@ -1206,6 +1215,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.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 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1263,8 +1273,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-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.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
|
||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -1375,11 +1385,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-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-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-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-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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
@ -1396,6 +1406,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.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.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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -1404,7 +1415,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-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-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-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -1466,6 +1477,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.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.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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -1553,8 +1565,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-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-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg=
|
||||
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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
@ -1593,10 +1605,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.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.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.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
|
||||
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/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=
|
||||
@ -1617,7 +1628,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/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/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||
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/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
@ -1648,8 +1658,7 @@ lukechampine.com/blake3 v1.1.6 h1:H3cROdztr7RCfoaTpGZFQsrqvweFLrqS73j7L7cmR5c=
|
||||
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/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g=
|
||||
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
||||
pgregory.net/rapid v0.5.3 h1:163N50IHFqr1phZens4FQOdPgfJscR7a562mjQqeo4M=
|
||||
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/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
|
16
gometalinter.json
Normal file
16
gometalinter.json
Normal 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
|
||||
}
|
269
gomod2nix.toml
269
gomod2nix.toml
@ -2,26 +2,32 @@ schema = 3
|
||||
|
||||
[mod]
|
||||
[mod."cloud.google.com/go"]
|
||||
version = "v0.102.1"
|
||||
hash = "sha256-rv3MHFvIrN6AcrmWcWGSQwgaZLbjJMmJFi3bsfHoiO4="
|
||||
version = "v0.105.0"
|
||||
hash = "sha256-2nYtHjuN9ghGcM6aPlOxyNNarHebHtj0Xec48sWwdaI="
|
||||
[mod."cloud.google.com/go/compute"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-g+n7L36LC+NP4KaiEu9fCMn6S9fkxjp4PCLOp/oXV38="
|
||||
version = "v1.12.1"
|
||||
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"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-sPtj6QPPC/QrkDXJW4Y7rMIHk5l1y9XV/DgM47eEtvg="
|
||||
version = "v0.7.0"
|
||||
hash = "sha256-2UTJ/BbZ+YMGJhyo3HRPUYVDXW6+B5znFdqiutboYtA="
|
||||
[mod."cloud.google.com/go/storage"]
|
||||
version = "v1.22.1"
|
||||
hash = "sha256-YZt05wru0kacyi6moTgvocavActKpXx7FlLh+o0HGDs="
|
||||
version = "v1.27.0"
|
||||
hash = "sha256-V4B6A1Ms8cemB5Cs6nAtUe1N1ldaI9oqTdzGU2FUhrc="
|
||||
[mod."cosmossdk.io/errors"]
|
||||
version = "v1.0.0-beta.7"
|
||||
hash = "sha256-XblGvIx6Wvvq6wggXjp+KbeJGXoe7AZH7hXEdauCezU="
|
||||
[mod."cosmossdk.io/math"]
|
||||
version = "v1.0.0-beta.3"
|
||||
hash = "sha256-lTQ27ZlL+kWlc+S//sJmyiOwaf9qS+YLv61I4OXi9XE="
|
||||
version = "v1.0.0-beta.4"
|
||||
hash = "sha256-UYdq/46EubyjxkldGike8FlwJLWGCB576VB7th285ao="
|
||||
[mod."filippo.io/edwards25519"]
|
||||
version = "v1.0.0-rc.1"
|
||||
hash = "sha256-3DboBqby2ejRU33FG96Z8JF5AJ8HP2rC/v++VyoQ2LQ="
|
||||
[mod."github.com/99designs/gqlgen"]
|
||||
version = "v0.17.22"
|
||||
hash = "sha256-Cu3nAqFbsV7DH+4UZvX83ScxJtPlvOyD7ptUPXnwGng="
|
||||
[mod."github.com/99designs/keyring"]
|
||||
version = "v1.1.7-0.20210622111912-ef00f8ac3d76"
|
||||
hash = "sha256-oCalyOZWegRgKHZ1GvYHNkrMKh51j8cOE/K4yBPM5Oc="
|
||||
@ -38,6 +44,9 @@ schema = 3
|
||||
[mod."github.com/Workiva/go-datastructures"]
|
||||
version = "v1.0.53"
|
||||
hash = "sha256-W6qOvqu8sokMlZrpOF1SWG138H0/BotywKNLlDF8Zug="
|
||||
[mod."github.com/agnivade/levenshtein"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-tgv2s8XIcWjscv1pP87TOIUV4vADT2px1Lo/MQCTBjM="
|
||||
[mod."github.com/armon/go-metrics"]
|
||||
version = "v0.4.1"
|
||||
hash = "sha256-usxTUHA0QQMdM6sHi2z51nmnEKMbA0qUilxJFpWHlYE="
|
||||
@ -57,8 +66,8 @@ schema = 3
|
||||
version = "v0.22.1"
|
||||
hash = "sha256-hBU+roIELcmbW2Gz7eGZzL9qNA1bakq5wNxqCgs4TKc="
|
||||
[mod."github.com/btcsuite/btcd/btcec/v2"]
|
||||
version = "v2.2.0"
|
||||
hash = "sha256-cwoIqi0SiAaGEBtuQKip9OVirKIeJw5fUoWo7x/xfOc="
|
||||
version = "v2.3.2"
|
||||
hash = "sha256-natWs+yIAuD1UI07iZtjPilroQLfXizFn3lNOiOT83U="
|
||||
[mod."github.com/btcsuite/btcd/chaincfg/chainhash"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-vix0j/KGNvoKjhlKgVeSLY6un2FHeIEoZWMC4z3yvZ4="
|
||||
@ -84,35 +93,36 @@ schema = 3
|
||||
version = "v0.7.9"
|
||||
hash = "sha256-ZWIXIXcHGjeCNgMrpXymry8/8esDDauGFfF/+gEoO1Y="
|
||||
[mod."github.com/confio/ics23/go"]
|
||||
version = "v0.7.0"
|
||||
hash = "sha256-FjUQfDKtX+/13+UjJzbYPAkgM4GPZ0vk+dKz7/iRetw="
|
||||
version = "v0.8.0"
|
||||
hash = "sha256-mFKxFHp7RaE1L5NdtH9H9px2Cy6I5uOZVnFOgE8Nrew="
|
||||
replaced = "github.com/cosmos/cosmos-sdk/ics23/go"
|
||||
[mod."github.com/cosmos/btcutil"]
|
||||
version = "v1.0.4"
|
||||
hash = "sha256-JvcBXBdjdmnaW/nyf/tw/uaOAGn1b78yxrtl2/Rs3kA="
|
||||
version = "v1.0.5"
|
||||
hash = "sha256-t572Sr5iiHcuMKLMWa2i+LBAt192oa+G1oA371tG/eI="
|
||||
[mod."github.com/cosmos/cosmos-proto"]
|
||||
version = "v1.0.0-alpha7"
|
||||
hash = "sha256-2wCH+toTF2A6MfFjOa13muEH5oBCcxAhZEqirNOrBA0="
|
||||
version = "v1.0.0-beta.1"
|
||||
hash = "sha256-oATkuj+fM5eBn+ywO+w/tL0AFSIEkx0J3Yz+VhVe0QA="
|
||||
[mod."github.com/cosmos/cosmos-sdk"]
|
||||
version = "v0.46.2-0.20220920160224-9454b97ccb77"
|
||||
hash = "sha256-zwOsdcoPbEzn+q/UmW6/CauW65V6a4z/7k8DXPCvKb0="
|
||||
version = "v0.46.7"
|
||||
hash = "sha256-54DCF8lrnA1oUmBJlbUlWXOP5UbenRInUROn5P5I9qI="
|
||||
[mod."github.com/cosmos/go-bip39"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
|
||||
[mod."github.com/cosmos/gogoproto"]
|
||||
version = "v1.4.3"
|
||||
hash = "sha256-Y/NL76ay/oAl8mS3skkK5ula0/xudqbwW1o22lZjKRg="
|
||||
[mod."github.com/cosmos/gorocksdb"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-209TcVuXc5s/TcOvNlaQ1HEJAUDTEK3nxPhs+d8TEcY="
|
||||
[mod."github.com/cosmos/iavl"]
|
||||
version = "v0.19.2-0.20220916140702-9b6be3095313"
|
||||
hash = "sha256-49xr/7/4L1wZ45eW5lE7C4SlcbGf4gBY+662SfJiWPQ="
|
||||
version = "v0.19.4"
|
||||
hash = "sha256-EmpRZ48pjPFq/fIHneut9Vyo5QJATfb3ZO7KzWnqs9g="
|
||||
[mod."github.com/cosmos/ibc-go/v5"]
|
||||
version = "v5.0.0"
|
||||
hash = "sha256-sDZdmuGohaaBF7bxrjo9PWJnmoF+VOkjySYhsFixPz4="
|
||||
version = "v5.2.0"
|
||||
hash = "sha256-Gfqhdz9ZKEgb7LCkHiXCwYZYUYluQ+vMew/GkssfVj8="
|
||||
[mod."github.com/cosmos/ledger-cosmos-go"]
|
||||
version = "v0.11.1"
|
||||
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA="
|
||||
[mod."github.com/cosmos/ledger-go"]
|
||||
version = "v0.9.2"
|
||||
hash = "sha256-0YI+0A6wFBjiebBwzWOQjkgXkTakCrf7Gjg2xEaQdoM="
|
||||
version = "v0.12.1"
|
||||
hash = "sha256-9+nr+/r4MyiogddS0JcXOuriPqXP4nxln8ts+mYQRcg="
|
||||
[mod."github.com/creachadair/taskgroup"]
|
||||
version = "v0.3.2"
|
||||
hash = "sha256-Y261IO/d9xjV0UScqHvo31broxvnKn4IQQC9Mu6jNkE="
|
||||
@ -156,17 +166,20 @@ schema = 3
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-k1DYvCqO3BKNcGEve/nMW0RxzMkK2tGfXbUbycqcVSo="
|
||||
[mod."github.com/ethereum/go-ethereum"]
|
||||
version = "v1.10.19"
|
||||
hash = "sha256-7FPnTGcCb8Xd1QVR+6PmGTaHdTY1mm/8osFTW1JLuG8="
|
||||
version = "v1.10.26"
|
||||
hash = "sha256-gkMEwJ4rOgn12amD4QpZ4th/10uyTTeoFmpseuKDQPs="
|
||||
[mod."github.com/felixge/httpsnoop"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-TNXnnC/ZGNY9lInAcES1cBGqIdEljKuh5LH/khVFjVk="
|
||||
[mod."github.com/fsnotify/fsnotify"]
|
||||
version = "v1.5.4"
|
||||
hash = "sha256-iPuInpDAJvDeSTr6to713J/fTOWdQIWlLXWAuWIs2Bw="
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-DQesOCweQPEwmAn6s7DCP/Dwy8IypC+osbpfsvpkdP0="
|
||||
[mod."github.com/gballet/go-libpcsclite"]
|
||||
version = "v0.0.0-20190607065134-2772fd86a8ff"
|
||||
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"]
|
||||
version = "v0.12.0"
|
||||
hash = "sha256-5RkXo6s0oye8etgD5qy+AvkkkNsQ6jc0kWJj6flA4GM="
|
||||
@ -176,6 +189,9 @@ schema = 3
|
||||
[mod."github.com/go-logfmt/logfmt"]
|
||||
version = "v0.5.1"
|
||||
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"]
|
||||
version = "v1.2.6"
|
||||
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
|
||||
@ -211,8 +227,8 @@ schema = 3
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-1PIeFGgUL4BK/StL/D12pg9bEQ5HfMT/fMLdus4pZTs="
|
||||
[mod."github.com/google/go-cmp"]
|
||||
version = "v0.5.8"
|
||||
hash = "sha256-8zkIo+Sr1NXMnj3PNmvjX2sZKnAKWXOFvmnX7D9bwxQ="
|
||||
version = "v0.5.9"
|
||||
hash = "sha256-lQc4O00R3QSMGs9LP8Sy7A9kj0cqV5rrUdpnGeipIyg="
|
||||
[mod."github.com/google/orderedcode"]
|
||||
version = "v0.0.1"
|
||||
hash = "sha256-KrExYovtUQrHGI1mPQf57jGw8soz7eWOC2xqEaV0uGk="
|
||||
@ -220,14 +236,11 @@ schema = 3
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
|
||||
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-fxaElfiGGh1mLmltkFpVFdiuaagrLZLTW9btVpK13wg="
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-5gxsS5kDLqNFBkQ4eK6GS/sNn+aFknm6jjfteO+6jl4="
|
||||
[mod."github.com/googleapis/gax-go/v2"]
|
||||
version = "v2.4.0"
|
||||
hash = "sha256-zzat4+3iF2XBTQ6RZAUgsCbfK0HgO0nYhM4utA5dqz0="
|
||||
[mod."github.com/googleapis/go-type-adapters"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-u3ajruRV/EN2E1WKet/zoe3zmRrAy4C5F2Dx8bpQwoc="
|
||||
version = "v2.6.0"
|
||||
hash = "sha256-sSsncbJmv0n5jB3G7tHY1Zr2ucCusIeTrXZH4A8QqYI="
|
||||
[mod."github.com/gorilla/handlers"]
|
||||
version = "v1.5.1"
|
||||
hash = "sha256-GnBAARgOx1E+hDMQ63SI17hdhGtLQxb31lZOmn5j/pU="
|
||||
@ -289,8 +302,26 @@ schema = 3
|
||||
version = "v0.15.0"
|
||||
hash = "sha256-9oqKb5Y3hjleOFE2BczbEzLH6q2Jg7kUTP/M8Yk4Ne4="
|
||||
[mod."github.com/inconshreveable/mousetrap"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-ogTuLrV40FwS4ueo4hh6hi1wPywOI+LyIqfNjsibwNY="
|
||||
version = "v1.0.1"
|
||||
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"]
|
||||
version = "v1.0.2"
|
||||
hash = "sha256-L1D4Yoxnzihs795GZ+Q3AZsFP5c4iqyjTeyrudzPXtw="
|
||||
@ -304,8 +335,11 @@ schema = 3
|
||||
version = "v0.0.0-20190712205309-48d3d31d256d"
|
||||
hash = "sha256-bn04wkDnhQ0tb/YzmPf7MNJlApOl+z6+EAbUqH7Ti5Q="
|
||||
[mod."github.com/klauspost/compress"]
|
||||
version = "v1.15.9"
|
||||
hash = "sha256-ctPxlVq0c/SoNPVsP66RjxUjTHys3diW2Apxjyc9WdE="
|
||||
version = "v1.15.11"
|
||||
hash = "sha256-9MXm0TObg6DyqnYMIw3IChrorHc2ILf5djZYoM0e1J0="
|
||||
[mod."github.com/klauspost/cpuid/v2"]
|
||||
version = "v2.0.9"
|
||||
hash = "sha256-0rHlHzEVaDdkVbRJDhnAJjfJUmAHOYjXN5u7VoCi5uk="
|
||||
[mod."github.com/lib/pq"]
|
||||
version = "v1.10.6"
|
||||
hash = "sha256-8EhFwY/9YH5L/fd6l2beOnC3VvpegRAmCCsnDVJBqBM="
|
||||
@ -319,8 +353,8 @@ schema = 3
|
||||
version = "v0.9.0"
|
||||
hash = "sha256-Fe2OPoyRExZejwtUBivKhfJAJW7o9b1eyYpgDlWQ1No="
|
||||
[mod."github.com/mattn/go-colorable"]
|
||||
version = "v0.1.12"
|
||||
hash = "sha256-Y1vCt0ShrCz4wSmwsppCfeLPLKrWusc2zM2lUFwDMyI="
|
||||
version = "v0.1.13"
|
||||
hash = "sha256-qb3Qbo0CELGRIzvw7NVM1g/aayaz4Tguppk9MD2/OI8="
|
||||
[mod."github.com/mattn/go-isatty"]
|
||||
version = "v0.0.16"
|
||||
hash = "sha256-YMaPZvShDfA98vqw1+zWWl7M1IT4nHPGBrAt7kHo8Iw="
|
||||
@ -334,11 +368,14 @@ schema = 3
|
||||
version = "v0.1.1"
|
||||
hash = "sha256-SoKy4Mwkbm0J2yQLDcIcBbo/J6auTNdlZslTvJrSknM="
|
||||
[mod."github.com/mimoo/StrobeGo"]
|
||||
version = "v0.0.0-20181016162300-f8f6d4d2b643"
|
||||
hash = "sha256-ih5WfC48IniPuAHUpC6upOabZA1/DssTAcxhZe6A/dE="
|
||||
version = "v0.0.0-20210601165009-122bf33a46e0"
|
||||
hash = "sha256-rmw70RHsbeOnema++aFCPdswADMVKtb7KGF3msOI7ak="
|
||||
[mod."github.com/minio/highwayhash"]
|
||||
version = "v1.0.2"
|
||||
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"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-oduBKXHAQG8X6aqLEpqZHs5DOKe84u6WkBwi4W6cv3k="
|
||||
@ -348,18 +385,36 @@ schema = 3
|
||||
[mod."github.com/mitchellh/mapstructure"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-ztVhGQXs67MF8UadVvG72G3ly0ypQW0IRDdOOkjYwoE="
|
||||
[mod."github.com/mr-tron/base58"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-8FzMu3kHUbBX10pUdtGf59Ag7BNupx8ZHeUaodR1/Vk="
|
||||
[mod."github.com/mtibben/percent"]
|
||||
version = "v0.2.1"
|
||||
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"]
|
||||
version = "v0.0.5"
|
||||
hash = "sha256-/5i70IkH/qSW5KjGzv8aQNKh9tHoz98tqtL0K2DMFn4="
|
||||
[mod."github.com/onsi/ginkgo/v2"]
|
||||
version = "v2.2.0"
|
||||
hash = "sha256-+VzAN6pB5DwEqT/KHdhgfPnWBtyIIcHi1J4HQkqCvvU="
|
||||
version = "v2.5.1"
|
||||
hash = "sha256-VB29+H9k7l6il63oXJvsjamSUhsw/e99iI/BeTCderA="
|
||||
[mod."github.com/onsi/gomega"]
|
||||
version = "v1.20.2"
|
||||
hash = "sha256-3SGyvhWVlR3tYojnRSDr2SRToontAtw4hbZX+agn/Hs="
|
||||
version = "v1.24.1"
|
||||
hash = "sha256-REfxQTDRcO23GnmJfOW8/MmPJf9oE2grVvvGiC1eSbo="
|
||||
[mod."github.com/pelletier/go-toml"]
|
||||
version = "v1.9.5"
|
||||
hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc="
|
||||
@ -375,6 +430,9 @@ schema = 3
|
||||
[mod."github.com/pmezard/go-difflib"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA="
|
||||
[mod."github.com/polydawn/refmt"]
|
||||
version = "v0.0.0-20201211092308-30ac6d18308e"
|
||||
hash = "sha256-oicfIWyK51U0LaNW0qgg5enH866TM6vsJExw98whjio="
|
||||
[mod."github.com/prometheus/client_golang"]
|
||||
version = "v1.12.2"
|
||||
hash = "sha256-d8xHyML/FImuPmFOy7UGW/y85NPLzJYL6IFhR3s7XzE="
|
||||
@ -385,8 +443,8 @@ schema = 3
|
||||
version = "v0.34.0"
|
||||
hash = "sha256-M+v+7DntUBmiQNzfNmG3aLLufbl0XBQOubtYoNTzJDA="
|
||||
[mod."github.com/prometheus/procfs"]
|
||||
version = "v0.7.3"
|
||||
hash = "sha256-ik0WpnpSjMwifPYfQTfu/eb5ilNj+eLJF0d5Dftp8A8="
|
||||
version = "v0.8.0"
|
||||
hash = "sha256-hgrilokQsXCOCCvwgOSfuErxoFAQpXM/+zNJKcMVHyM="
|
||||
[mod."github.com/prometheus/tsdb"]
|
||||
version = "v0.7.1"
|
||||
hash = "sha256-BPz7YJbfMZgeR+u9YaeWeipVzHIS73EdgXD7VSJSLbA="
|
||||
@ -394,8 +452,8 @@ schema = 3
|
||||
version = "v0.1.7"
|
||||
hash = "sha256-/bfnXHBmN8vviPL7D85IzcEVXCaWyjbPPNyauzEcQ8Q="
|
||||
[mod."github.com/rcrowley/go-metrics"]
|
||||
version = "v0.0.0-20200313005456-10cdbea86bc0"
|
||||
hash = "sha256-xHqWWd4/RyAxqb80zjnrqHnHtWPfVTyByE+vDfbT52E="
|
||||
version = "v0.0.0-20201227073835-cf1acfcdf475"
|
||||
hash = "sha256-10ytHQ1SpMKYTiKuOPdEMuOVa8HVvv9ryYSIF9BHEBI="
|
||||
[mod."github.com/regen-network/cosmos-proto"]
|
||||
version = "v0.3.1"
|
||||
hash = "sha256-Bchbq/Hg72EA7Hevs8+PNuENuQaZAzk3qeVjMqFMUxc="
|
||||
@ -409,20 +467,23 @@ schema = 3
|
||||
version = "v1.27.0"
|
||||
hash = "sha256-BxQtP2TROeSSpj9l1irocuSfxn55UL4ugzB/og7r8eE="
|
||||
[mod."github.com/sasha-s/go-deadlock"]
|
||||
version = "v0.2.1-0.20190427202633-1595213edefa"
|
||||
hash = "sha256-BBOohTR+ktgJHAoYWh39/ui8MczcJECloc7tvxVBE50="
|
||||
version = "v0.3.1"
|
||||
hash = "sha256-2CBEi9/iN/OMt7wEIG+hRjgDH6CRWIgibGGGy1dQ78I="
|
||||
[mod."github.com/shirou/gopsutil"]
|
||||
version = "v3.21.4-0.20210419000835-c7a38de76ee5+incompatible"
|
||||
hash = "sha256-oqIqyFquWabIE6DID6uTEc8oFEmM1rVu2ATn3toiCEg="
|
||||
[mod."github.com/spaolacci/murmur3"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-RWD4PPrlAsZZ8Xy356MBxpj+/NZI7w2XOU14Ob7/Y9M="
|
||||
[mod."github.com/spf13/afero"]
|
||||
version = "v1.8.2"
|
||||
hash = "sha256-ERuG4GK1LOn72DRbT9URpo1QoVIm2A3mPtlf+xSPgx8="
|
||||
version = "v1.9.2"
|
||||
hash = "sha256-R1mir7Fu95QK+YL99U14RGbLJzxqWRH5rSFpssgJvzA="
|
||||
[mod."github.com/spf13/cast"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-Pdp+wC5FWqyJKzyYHb7JCcV9BoJk/sxQw6nLyuLJvuQ="
|
||||
[mod."github.com/spf13/cobra"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-rcyHWrxshA5DVpxrSba5X4NjppqOGrJ64QkUKKnfW2E="
|
||||
version = "v1.6.1"
|
||||
hash = "sha256-80B5HcYdFisz6QLYkTyka7f9Dr6AfcVyPwp3QChoXwU="
|
||||
[mod."github.com/spf13/jwalterweatherman"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-62BQtqTLF/eVrTOr7pUXE7AiHRjOVC8jQs3/Ehmflfs="
|
||||
@ -430,17 +491,17 @@ schema = 3
|
||||
version = "v1.0.5"
|
||||
hash = "sha256-w9LLYzxxP74WHT4ouBspH/iQZXjuAh2WQCHsuvyEjAw="
|
||||
[mod."github.com/spf13/viper"]
|
||||
version = "v1.13.0"
|
||||
hash = "sha256-yHviS3lMo1hB6jwyiU3zpyGtxP6v9AsyZUKiLeCVz+k="
|
||||
version = "v1.14.0"
|
||||
hash = "sha256-qn3VzD339HZIub5QP4aWVciSufAfVb9llbmQZ8pfDEs="
|
||||
[mod."github.com/status-im/keycard-go"]
|
||||
version = "v0.0.0-20200402102358-957c09536969"
|
||||
hash = "sha256-yddXXuu6mEFEO2/K6c1tWymeBKzOcvLQnNsFGRjtfXk="
|
||||
[mod."github.com/stretchr/objx"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-W6ycaeD/okr4udpCAGDsByr3OmiR0fuBzJUXHaHEFC0="
|
||||
version = "v0.5.0"
|
||||
hash = "sha256-nY4mvP0f0Ry1IKMKQAYNuioA5h4red4mmQqeGZw6EF0="
|
||||
[mod."github.com/stretchr/testify"]
|
||||
version = "v1.8.0"
|
||||
hash = "sha256-LDxBAebK+A06y4vbH7cd1sVBOameIY81Xm8/9OPZh7o="
|
||||
version = "v1.8.1"
|
||||
hash = "sha256-3e0vOJLgCMAan+GfaGN8RGZdarh5iCavM6flf6YMNPk="
|
||||
[mod."github.com/subosito/gotenv"]
|
||||
version = "v1.4.1"
|
||||
hash = "sha256-aHAUs8Gh+BREUulljWr7vBZQg1BLu/M/8UfNK8CWSn8="
|
||||
@ -457,8 +518,8 @@ schema = 3
|
||||
version = "v0.16.0"
|
||||
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
|
||||
[mod."github.com/tendermint/tendermint"]
|
||||
version = "v0.34.21"
|
||||
hash = "sha256-C1KW6Wd4TwsFC09IHt8Jo3dozEk/Q2ZVdTapM8btEJ0="
|
||||
version = "v0.34.24"
|
||||
hash = "sha256-3HFTv4XgN535RDaJ5OwUS+fnJHgkmLTwU7CNU2ilxEQ="
|
||||
[mod."github.com/tendermint/tm-db"]
|
||||
version = "v0.6.7"
|
||||
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
|
||||
@ -474,9 +535,18 @@ schema = 3
|
||||
[mod."github.com/ulikunitz/xz"]
|
||||
version = "v0.5.8"
|
||||
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"]
|
||||
version = "v0.9.1-0.20220302062450-5552068d2266"
|
||||
hash = "sha256-IZea8SHuLQxlltm1avieRVI054TWZg2jEoplodvNtwk="
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-hSVmN/f/lQHFhF60o6ej78ELC0MMoqQgqIX2hHjdTXg="
|
||||
[mod."github.com/zondax/ledger-go"]
|
||||
version = "v0.14.0"
|
||||
hash = "sha256-RozTPSNs4RerZ4DQMBcGmvREjoRtH1G69xjhccYjIOk="
|
||||
[mod."go.etcd.io/bbolt"]
|
||||
version = "v1.3.6"
|
||||
hash = "sha256-DenVAmyN22xUiivk6fdJp4C9ZnUJXCMDUf8E0goRRV4="
|
||||
@ -484,47 +554,47 @@ schema = 3
|
||||
version = "v0.23.0"
|
||||
hash = "sha256-R3O9GyNtv6j0ic7s+2xkLLaLzbJEop0Otj1nJDFBjsg="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.0.0-20220622213112-05595931fe9d"
|
||||
hash = "sha256-2c4wvwiQ0DJSJsApfmNoxCxx1siRCiJvW9hhrGlcvds="
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-Un9wPqz8u/xpV98T4IqE6RMXIPhGCIm2prsNkHP3cjg="
|
||||
[mod."golang.org/x/exp"]
|
||||
version = "v0.0.0-20220722155223-a9213eeb770e"
|
||||
hash = "sha256-kNgzydWRpjm0sZl4uXEs3LX5L0xjJtJRAFf/CTlYUN4="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.0.0-20220726230323-06994584191e"
|
||||
hash = "sha256-VFJB2BjvFZnp0zoJLX4iinV/P6Cn7XUlsKwBGCdVjlU="
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-7IwGZh/xg4mQz88cJio2Ov5d3jGRXKj1itlAja/EAbQ="
|
||||
[mod."golang.org/x/oauth2"]
|
||||
version = "v0.0.0-20220622183110-fd043fe589d2"
|
||||
hash = "sha256-VLffpTpx3DlUzXB8mKiJfFzm4ZmgnLSUuLB5Ir0WQUg="
|
||||
version = "v0.0.0-20221014153046-6fdb5e3db783"
|
||||
hash = "sha256-IoygidVNqyAZmN+3macDeIefK8hhJToygpcqlwehdYQ="
|
||||
[mod."golang.org/x/sync"]
|
||||
version = "v0.0.0-20220722155255-886fb9371eb4"
|
||||
hash = "sha256-ZZyIlxh+nqsOiWHstW7eHXN7RhHnbSL2eDIzcve07Q0="
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-Hygjq9euZ0qz6TvHYQwOZEjNiTbTh1nSLRAWZ6KFGR8="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.0.0-20220811171246-fbc7d0a398ab"
|
||||
hash = "sha256-acnc9aKY/SyebObLasV+gowfB0S+6ehz3hnUgAmQmSU="
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-TIHhfYbZ99sCU1ZMikxwomXH5AEtD/lA1VMMW+UAhbU="
|
||||
[mod."golang.org/x/term"]
|
||||
version = "v0.0.0-20220722155259-a9ba230a4035"
|
||||
hash = "sha256-9uM1OONzbsa6bz2iKk767hAaCuafi58bdTF7at03fWY="
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-NKv2o8wz8DB/2W2h/muGEIHb+S06mBXZxhG254RpQ5s="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.3.7"
|
||||
hash = "sha256-XH2pUzzQx95O0rak00grQvfACfL+EmZiV7ZzJBkX+XY="
|
||||
version = "v0.5.0"
|
||||
hash = "sha256-ztH+xQyM/clOcQl+y/UEPcfNKbc3xApMbEPDDZ9up0o="
|
||||
[mod."golang.org/x/xerrors"]
|
||||
version = "v0.0.0-20220609144429-65e65417b02f"
|
||||
hash = "sha256-tl8pv3oddbz2+KoIp7PFDKsxjQF8ocjPF8XPsY3sw38="
|
||||
version = "v0.0.0-20220907171357-04be3eba64a2"
|
||||
hash = "sha256-6+zueutgefIYmgXinOflz8qGDDDj0Zhv+2OkGhBTKno="
|
||||
[mod."google.golang.org/api"]
|
||||
version = "v0.93.0"
|
||||
hash = "sha256-W17B79osAhObMbrCHlgywEPg9yIPx0ZISDhp9JwFE5A="
|
||||
version = "v0.102.0"
|
||||
hash = "sha256-q8t08Wu0qzOQOmhY4GSoUrhqLTW/TeXiKhio+5ONfe4="
|
||||
[mod."google.golang.org/appengine"]
|
||||
version = "v1.6.7"
|
||||
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
|
||||
[mod."google.golang.org/genproto"]
|
||||
version = "v0.0.0-20220815135757-37a418bb8959"
|
||||
hash = "sha256-uS60VVZDdn6kNV24bmOmSTuwz4lBqVM+9XK176GGL2s="
|
||||
version = "v0.0.0-20221116193143-41c2ba794472"
|
||||
hash = "sha256-uQuxuOvWRsdMii5M5QresisVd1E+Ss8s2WfR2n7QSXk="
|
||||
[mod."google.golang.org/grpc"]
|
||||
version = "v1.49.0"
|
||||
hash = "sha256-x4+/XjxI2HY8fZYMiEV7Kv+2SrnlmaTJX3tBl+dPUoI="
|
||||
version = "v1.51.0"
|
||||
hash = "sha256-RzH5DU13D/ulxxOouIKpdNt8eHdff7mrEnB+JUupbLU="
|
||||
[mod."google.golang.org/protobuf"]
|
||||
version = "v1.28.1"
|
||||
hash = "sha256-sTJYgvlv5is7vHNxcuigF2lNASp0QonhUgnrguhfHSU="
|
||||
version = "v1.28.2-0.20220831092852-f930b1dc76e8"
|
||||
hash = "sha256-li5hXlXwTJ5LIZ8bVki1AZ6UFI2gXHl33JwdX1dOrtM="
|
||||
[mod."gopkg.in/ini.v1"]
|
||||
version = "v1.67.0"
|
||||
hash = "sha256-V10ahGNGT+NLRdKUyRg1dos5RxLBXBk1xutcnquc/+4="
|
||||
@ -537,6 +607,9 @@ schema = 3
|
||||
[mod."gopkg.in/yaml.v3"]
|
||||
version = "v3.0.1"
|
||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||
[mod."lukechampine.com/blake3"]
|
||||
version = "v1.1.6"
|
||||
hash = "sha256-pKVTpuCcqGSn8s11Jq33yrXewQLvycuAoxKJEdbZ7rA="
|
||||
[mod."nhooyr.io/websocket"]
|
||||
version = "v1.8.6"
|
||||
hash = "sha256-DyaiCc/1iELrl6JSpz6WYMtFwUiSCOSoNF8IhSyP1ag="
|
||||
|
165
gql/graphiql.go
Normal file
165
gql/graphiql.go
Normal file
@ -0,0 +1,165 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GraphiQL is an in-browser IDE for exploring GraphiQL APIs.
|
||||
// This handler returns GraphiQL when requested.
|
||||
//
|
||||
// For more information, see https://github.com/graphql/graphiql.
|
||||
|
||||
func PlaygroundHandler(apiURL string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "only GET requests are supported", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
err := page.Execute(w, map[string]interface{}{
|
||||
"apiURL": apiURL,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/graphql/graphiql/blob/main/examples/graphiql-cdn/index.html
|
||||
var page = template.Must(template.New("graphiql").Parse(`
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>GraphiQL</title>
|
||||
<style>
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#graphiql {
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--
|
||||
This GraphiQL example depends on Promise and fetch, which are available in
|
||||
modern browsers, but can be "polyfilled" for older browsers.
|
||||
GraphiQL itself depends on React DOM.
|
||||
If you do not want to rely on a CDN, you can host these files locally or
|
||||
include them directly in your favored resource bundler.
|
||||
-->
|
||||
<script
|
||||
src="https://unpkg.com/react@17/umd/react.development.js"
|
||||
integrity="sha512-Vf2xGDzpqUOEIKO+X2rgTLWPY+65++WPwCHkX2nFMu9IcstumPsf/uKKRd5prX3wOu8Q0GBylRpsDB26R6ExOg=="
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script
|
||||
src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"
|
||||
integrity="sha512-Wr9OKCTtq1anK0hq5bY3X/AvDI5EflDSAh0mE9gma+4hl+kXdTJPKZ3TwLMBcrgUeoY0s3dq9JjhCQc7vddtFg=="
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
|
||||
<!--
|
||||
These two files can be found in the npm module, however you may wish to
|
||||
copy them directly into your environment, or perhaps include them in your
|
||||
favored resource bundler.
|
||||
-->
|
||||
<link rel="stylesheet" href="https://unpkg.com/graphiql/graphiql.min.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="graphiql">Loading...</div>
|
||||
<script
|
||||
src="https://unpkg.com/graphiql/graphiql.min.js"
|
||||
type="application/javascript"
|
||||
></script>
|
||||
<script>
|
||||
// https://github.com/graphql/graphiql/blob/main/packages/graphiql/resources/renderExample.js
|
||||
|
||||
// Parse the search string to get url parameters.
|
||||
var search = window.location.search;
|
||||
var parameters = {};
|
||||
search
|
||||
.substr(1)
|
||||
.split('&')
|
||||
.forEach(function (entry) {
|
||||
var eq = entry.indexOf('=');
|
||||
if (eq >= 0) {
|
||||
parameters[decodeURIComponent(entry.slice(0, eq))] = decodeURIComponent(
|
||||
entry.slice(eq + 1),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// When the query and variables string is edited, update the URL bar so
|
||||
// that it can be easily shared.
|
||||
function onEditQuery(newQuery) {
|
||||
parameters.query = newQuery;
|
||||
updateURL();
|
||||
}
|
||||
|
||||
function onEditVariables(newVariables) {
|
||||
parameters.variables = newVariables;
|
||||
updateURL();
|
||||
}
|
||||
|
||||
function onEditHeaders(newHeaders) {
|
||||
parameters.headers = newHeaders;
|
||||
updateURL();
|
||||
}
|
||||
|
||||
function onTabChange(tabsState) {
|
||||
const activeTab = tabsState.tabs[tabsState.activeTabIndex];
|
||||
parameters.query = activeTab.query;
|
||||
parameters.variables = activeTab.variables;
|
||||
parameters.headers = activeTab.headers;
|
||||
updateURL();
|
||||
}
|
||||
|
||||
function updateURL() {
|
||||
var newSearch =
|
||||
'?' +
|
||||
Object.keys(parameters)
|
||||
.filter(function (key) {
|
||||
return Boolean(parameters[key]);
|
||||
})
|
||||
.map(function (key) {
|
||||
return (
|
||||
encodeURIComponent(key) + '=' + encodeURIComponent(parameters[key])
|
||||
);
|
||||
})
|
||||
.join('&');
|
||||
history.replaceState(null, null, newSearch);
|
||||
}
|
||||
|
||||
// Render <GraphiQL /> into the body.
|
||||
// See the README in the top level of this module to learn more about
|
||||
// how you can customize GraphiQL by providing different values or
|
||||
// additional child elements.
|
||||
ReactDOM.render(
|
||||
React.createElement(GraphiQL, {
|
||||
fetcher: GraphiQL.createFetcher({
|
||||
url: {{.apiURL}}
|
||||
}),
|
||||
query: parameters.query,
|
||||
variables: parameters.variables,
|
||||
headers: parameters.headers,
|
||||
defaultHeaders: parameters.defaultHeaders,
|
||||
onEditQuery: onEditQuery,
|
||||
onEditVariables: onEditVariables,
|
||||
onEditHeaders: onEditHeaders,
|
||||
defaultEditorToolsVisibility: true,
|
||||
isHeadersEditorEnabled: true,
|
||||
shouldPersistHeaders: true,
|
||||
onTabChange,
|
||||
}),
|
||||
document.getElementById('graphiql'),
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
@ -5,9 +5,10 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/cors"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
@ -16,6 +17,16 @@ func Server(ctx client.Context) {
|
||||
if !viper.GetBool("gql-server") {
|
||||
return
|
||||
}
|
||||
|
||||
router := chi.NewRouter()
|
||||
|
||||
// Add CORS middleware around every request
|
||||
// See https://github.com/rs/cors for full option listing
|
||||
router.Use(cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
Debug: false,
|
||||
}).Handler)
|
||||
|
||||
logFile := viper.GetString("log-file")
|
||||
|
||||
port := viper.GetString("gql-port")
|
||||
@ -25,20 +36,20 @@ func Server(ctx client.Context) {
|
||||
logFile: logFile,
|
||||
}}))
|
||||
|
||||
http.Handle("/", playground.Handler("GraphQL playground", "/api"))
|
||||
router.Handle("/", PlaygroundHandler("/api"))
|
||||
|
||||
if viper.GetBool("gql-playground") {
|
||||
apiBase := viper.GetString("gql-playground-api-base")
|
||||
|
||||
http.Handle("/webui", playground.Handler("GraphQL playground", apiBase+"/api"))
|
||||
http.Handle("/console", playground.Handler("GraphQL playground", apiBase+"/graphql"))
|
||||
router.Handle("/webui", PlaygroundHandler(apiBase+"/api"))
|
||||
router.Handle("/console", PlaygroundHandler(apiBase+"/graphql"))
|
||||
}
|
||||
|
||||
http.Handle("/api", srv)
|
||||
http.Handle("/graphql", srv)
|
||||
router.Handle("/api", srv)
|
||||
router.Handle("/graphql", srv)
|
||||
|
||||
log.Info("Connect to GraphQL playground", "url", fmt.Sprintf("http://localhost:%s", port))
|
||||
err := http.ListenAndServe(":"+port, nil) //nolint: all
|
||||
err := http.ListenAndServe(":"+port, router) //nolint: all
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ package indexer
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
@ -110,12 +110,12 @@ func (kv *KVIndexer) IndexBlock(block *tmtypes.Block, txResults []*abci.Response
|
||||
ethTxIndex++
|
||||
|
||||
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 {
|
||||
return sdkerrors.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
||||
return errorsmod.Wrapf(err, "IndexBlock %d, write batch", block.Height)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -134,14 +134,14 @@ func (kv *KVIndexer) FirstIndexedBlock() (int64, error) {
|
||||
func (kv *KVIndexer) GetByTxHash(hash common.Hash) (*ethermint.TxResult, error) {
|
||||
bz, err := kv.db.Get(TxHashKey(hash))
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
}
|
||||
if len(bz) == 0 {
|
||||
return nil, fmt.Errorf("tx not found, hash: %s", hash.Hex())
|
||||
}
|
||||
var txKey ethermint.TxResult
|
||||
if err := kv.clientCtx.Codec.Unmarshal(bz, &txKey); err != nil {
|
||||
return nil, sdkerrors.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
return nil, errorsmod.Wrapf(err, "GetByTxHash %s", hash.Hex())
|
||||
}
|
||||
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) {
|
||||
bz, err := kv.db.Get(TxIndexKey(blockNumber, txIndex))
|
||||
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 {
|
||||
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) {
|
||||
it, err := db.ReverseIterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(err, "LoadLastBlock")
|
||||
return 0, errorsmod.Wrap(err, "LoadLastBlock")
|
||||
}
|
||||
defer it.Close()
|
||||
if !it.Valid() {
|
||||
@ -187,7 +187,7 @@ func LoadLastBlock(db dbm.DB) (int64, error) {
|
||||
func LoadFirstBlock(db dbm.DB) (int64, error) {
|
||||
it, err := db.Iterator([]byte{KeyPrefixTxIndex}, []byte{KeyPrefixTxIndex + 1})
|
||||
if err != nil {
|
||||
return 0, sdkerrors.Wrap(err, "LoadFirstBlock")
|
||||
return 0, errorsmod.Wrap(err, "LoadFirstBlock")
|
||||
}
|
||||
defer it.Close()
|
||||
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 {
|
||||
bz := codec.MustMarshal(txResult)
|
||||
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 {
|
||||
return sdkerrors.Wrap(err, "set tx-index key")
|
||||
return errorsmod.Wrap(err, "set tx-index key")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
2
init.bat
2
init.bat
@ -9,7 +9,7 @@ rem 3. add path C:\msys64\mingw64\bin
|
||||
rem C:\msys64\usr\bin
|
||||
|
||||
set KEY="mykey"
|
||||
set CHAINID="ethermint_9000-1"
|
||||
set CHAINID="laconic_9000-1"
|
||||
set MONIKER="localtestnet"
|
||||
set KEYRING="test"
|
||||
set KEYALGO="eth_secp256k1"
|
||||
|
4
init.sh
4
init.sh
@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
KEY="mykey"
|
||||
CHAINID="ethermint_9000-1"
|
||||
CHAINID="laconic_9000-1"
|
||||
MONIKER="localtestnet"
|
||||
KEYRING="test"
|
||||
KEYALGO="eth_secp256k1"
|
||||
LOGLEVEL="info"
|
||||
# to trace evm
|
||||
# trace evm
|
||||
TRACE="--trace"
|
||||
# TRACE=""
|
||||
|
||||
|
5
mlc_config.json
Normal file
5
mlc_config.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"retryOn429": true,
|
||||
"retryCount": 3,
|
||||
"fallbackRetryDelay": "20s"
|
||||
}
|
@ -15,7 +15,7 @@ COPY . .
|
||||
RUN make build-linux
|
||||
|
||||
# Final image
|
||||
FROM golang:1.18 as final
|
||||
FROM golang:1.19 as final
|
||||
|
||||
WORKDIR /
|
||||
|
||||
|
@ -27,7 +27,7 @@ import sources.nixpkgs {
|
||||
dotenv = builtins.path { name = "dotenv"; path = ../scripts/.env; };
|
||||
};
|
||||
})
|
||||
(_: pkgs: { test-env = import ./testenv.nix { inherit pkgs; }; })
|
||||
(_: pkgs: { test-env = pkgs.callPackage ./testenv.nix { }; })
|
||||
(_: pkgs: {
|
||||
cosmovisor = pkgs.buildGo118Module rec {
|
||||
name = "cosmovisor";
|
||||
|
@ -1,4 +1,4 @@
|
||||
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit }:
|
||||
{ lib, stdenv, buildGoModule, fetchFromGitHub, libobjc, IOKit, nixosTests }:
|
||||
|
||||
let
|
||||
# A list of binaries to put into separate outputs
|
||||
@ -7,19 +7,18 @@ let
|
||||
"clef"
|
||||
];
|
||||
|
||||
in
|
||||
buildGoModule rec {
|
||||
in buildGoModule rec {
|
||||
pname = "go-ethereum";
|
||||
version = "1.10.19";
|
||||
version = "1.10.25";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ethereum";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "0f6n9rg42ph47mvykc9f0lf99yzwqy4jm7mlzyks4l6i6fl1g3q1";
|
||||
sha256 = "sha256-mnf0kMfQEEQMricZJfyF7ZB/2F1dyPBx9iT2v/rGh1U=";
|
||||
};
|
||||
|
||||
vendorSha256 = "1s5yfpk2yn7f3zwjl2fdrh6c63ki2b8rlmnlss27yxibsidaj0yd";
|
||||
vendorSha256 = "sha256-Dj+xN8lr98LJyYr2FwJ7yUIJkUeUrr1fkcbj4hShJI0=";
|
||||
|
||||
doCheck = false;
|
||||
|
||||
@ -47,14 +46,19 @@ buildGoModule rec {
|
||||
"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
|
||||
propagatedBuildInputs =
|
||||
lib.optionals stdenv.isDarwin [ libobjc IOKit ];
|
||||
|
||||
passthru.tests = { inherit (nixosTests) geth; };
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://geth.ethereum.org/";
|
||||
description = "Official golang implementation of the Ethereum protocol";
|
||||
license = with licenses; [ lgpl3Plus gpl3Plus ];
|
||||
maintainers = with maintainers; [ adisbladis lionello RaghavSood ];
|
||||
maintainers = with maintainers; [ adisbladis RaghavSood ];
|
||||
};
|
||||
}
|
||||
|
50
nix/sources.json
Normal file
50
nix/sources.json
Normal 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"
|
||||
}
|
||||
}
|
@ -1,18 +1,38 @@
|
||||
{ pkgs }:
|
||||
pkgs.poetry2nix.mkPoetryEnv {
|
||||
{ poetry2nix, lib, python310 }:
|
||||
poetry2nix.mkPoetryEnv {
|
||||
projectDir = ../tests/integration_tests;
|
||||
python = pkgs.python39;
|
||||
overrides = pkgs.poetry2nix.overrides.withDefaults (self: super: {
|
||||
python = python310;
|
||||
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 {
|
||||
preConfigure = ''
|
||||
substituteInPlace setup.py --replace \'setuptools-markdown\' ""
|
||||
'';
|
||||
};
|
||||
|
||||
pystarport = super.pystarport.overridePythonAttrs (
|
||||
old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ self.poetry ];
|
||||
}
|
||||
);
|
||||
});
|
||||
pyyaml-include = super.pyyaml-include.overridePythonAttrs {
|
||||
preConfigure = ''
|
||||
substituteInPlace setup.py --replace "setup()" "setup(version=\"1.3\")"
|
||||
'';
|
||||
};
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
8
proto/buf.gen.gogo.yaml
Normal file
8
proto/buf.gen.gogo.yaml
Normal 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
|
15
proto/buf.gen.swagger.yaml
Normal file
15
proto/buf.gen.swagger.yaml
Normal 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
19
proto/buf.lock
Normal 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
|
@ -1,4 +1,10 @@
|
||||
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:
|
||||
use:
|
||||
- DEFAULT
|
||||
|
@ -11,11 +11,13 @@ option go_package = "github.com/cerc-io/laconicd/crypto/ethsecp256k1";
|
||||
message PubKey {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
// key is the public key in byte form
|
||||
bytes key = 1;
|
||||
}
|
||||
|
||||
// PrivKey defines a type alias for an ecdsa.PrivateKey that implements
|
||||
// Tendermint's PrivateKey interface.
|
||||
message PrivKey {
|
||||
// key is the private key in byte form
|
||||
bytes key = 1;
|
||||
}
|
||||
|
@ -7,18 +7,18 @@ option go_package = "github.com/cerc-io/laconicd/x/evm/types";
|
||||
|
||||
// Params defines the EVM module parameters
|
||||
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.
|
||||
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\""];
|
||||
// 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\""];
|
||||
// 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\""];
|
||||
// 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];
|
||||
// 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.
|
||||
bool allow_unprotected_txs = 6;
|
||||
}
|
||||
@ -26,67 +26,67 @@ message Params {
|
||||
// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
|
||||
// instead of *big.Int.
|
||||
message ChainConfig {
|
||||
// Homestead switch block (nil no fork, 0 = already homestead)
|
||||
// homestead_block switch (nil no fork, 0 = already homestead)
|
||||
string homestead_block = 1 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customname) = "DAOForkBlock",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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
|
||||
[(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)
|
||||
string eip150_block = 4 [
|
||||
(gogoproto.customname) = "EIP150Block",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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\""];
|
||||
// EIP155Block HF block
|
||||
// eip155_block: EIP155Block HF block
|
||||
string eip155_block = 6 [
|
||||
(gogoproto.customname) = "EIP155Block",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"eip155_block\""
|
||||
];
|
||||
// EIP158 HF block
|
||||
// eip158_block: EIP158 HF block
|
||||
string eip158_block = 7 [
|
||||
(gogoproto.customname) = "EIP158Block",
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.moretags) = "yaml:\"berlin_block\""
|
||||
@ -94,12 +94,12 @@ message ChainConfig {
|
||||
// DEPRECATED: EWASM, YOLOV3 and Catalyst block have been deprecated
|
||||
reserved 14, 15, 16;
|
||||
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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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
|
||||
reserved 19;
|
||||
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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(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.
|
||||
message State {
|
||||
// key is the stored key
|
||||
string key = 1;
|
||||
// value is the stored value for the given key
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
@ -129,38 +142,38 @@ message State {
|
||||
// with a given hash. It it used for import/export data as transactions are not
|
||||
// persisted on blockchain state after an upgrade.
|
||||
message TransactionLogs {
|
||||
// hash of the transaction
|
||||
string hash = 1;
|
||||
// logs is an array of Logs for the given transaction hash
|
||||
repeated Log logs = 2;
|
||||
}
|
||||
|
||||
// Log represents an protobuf compatible Ethereum Log that defines a contract
|
||||
// log event. These events are generated by the LOG opcode and stored/indexed by
|
||||
// the node.
|
||||
//
|
||||
// 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 {
|
||||
// Consensus fields:
|
||||
|
||||
// address of the contract that generated the event
|
||||
string address = 1;
|
||||
// list of topics provided by the contract.
|
||||
// topics is a list of topics provided by the contract.
|
||||
repeated string topics = 2;
|
||||
// supplied by the contract, usually ABI-encoded
|
||||
// data which is supplied by the contract, usually ABI-encoded
|
||||
bytes data = 3;
|
||||
|
||||
// Derived fields. These fields are filled in by the node
|
||||
// but not secured by consensus.
|
||||
|
||||
// block in which the transaction was included
|
||||
// block_number of the block in which the transaction was included
|
||||
uint64 block_number = 4 [(gogoproto.jsontag) = "blockNumber"];
|
||||
// hash of the transaction
|
||||
// tx_hash is the transaction hash
|
||||
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"];
|
||||
// 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"];
|
||||
// index of the log in the block
|
||||
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
|
||||
// through a filter query.
|
||||
bool removed = 9;
|
||||
@ -191,9 +204,9 @@ message TxResult {
|
||||
message AccessTuple {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// hex formatted ethereum address
|
||||
// address is a hex formatted ethereum address
|
||||
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"];
|
||||
}
|
||||
|
||||
@ -204,25 +217,27 @@ message TraceConfig {
|
||||
reserved 4, 7;
|
||||
reserved "disable_memory", "disable_return_data";
|
||||
|
||||
// custom javascript tracer
|
||||
// tracer is a custom javascript tracer
|
||||
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
|
||||
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;
|
||||
// disable stack capture
|
||||
// disable_stack switches stack capture
|
||||
bool disable_stack = 5 [(gogoproto.jsontag) = "disableStack"];
|
||||
// disable storage capture
|
||||
// disable_storage switches storage capture
|
||||
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;
|
||||
// maximum length of output, but zero means unlimited
|
||||
// limit defines the maximum length of output, but zero means unlimited
|
||||
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;
|
||||
// enable memory capture
|
||||
// enable_memory switches memory capture
|
||||
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"];
|
||||
// tracer_json_config configures the tracer using a JSON string
|
||||
string tracer_json_config = 13 [(gogoproto.jsontag) = "tracerConfig"];
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.evm.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/cerc-io/laconicd/x/evm/types";
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.evm.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
import "ethermint/evm/v1/tx.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/cerc-io/laconicd/x/evm/types";
|
||||
@ -89,7 +89,7 @@ message QueryAccountRequest {
|
||||
message QueryAccountResponse {
|
||||
// balance is the balance of the EVM denomination.
|
||||
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;
|
||||
// nonce is the account's sequence number.
|
||||
uint64 nonce = 3;
|
||||
@ -112,7 +112,7 @@ message QueryCosmosAccountResponse {
|
||||
string cosmos_address = 1;
|
||||
// sequence is the account's sequence number.
|
||||
uint64 sequence = 2;
|
||||
// account_number is the account numbert
|
||||
// account_number is the account number
|
||||
uint64 account_number = 3;
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ message QueryStorageRequest {
|
||||
option (gogoproto.equal) = 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;
|
||||
|
||||
// key defines the key of the storage state
|
||||
@ -167,7 +167,7 @@ message QueryStorageRequest {
|
||||
// QueryStorageResponse is the response type for the Query/Storage RPC
|
||||
// method.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ message QueryTxLogsRequest {
|
||||
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 {
|
||||
// logs represents the ethereum logs generated from the given transaction.
|
||||
repeated Log logs = 1;
|
||||
@ -217,60 +217,73 @@ message QueryParamsResponse {
|
||||
|
||||
// EthCallRequest defines EthCall request
|
||||
message EthCallRequest {
|
||||
// same json format as the json rpc api.
|
||||
// args uses the same json format as the json rpc api.
|
||||
bytes args = 1;
|
||||
// the default gas cap to be used
|
||||
// gas_cap defines the default gas cap to be used
|
||||
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
|
||||
message EstimateGasResponse {
|
||||
// the estimated gas
|
||||
// gas returns the estimated gas
|
||||
uint64 gas = 1;
|
||||
}
|
||||
|
||||
// QueryTraceTxRequest defines TraceTx request
|
||||
message QueryTraceTxRequest {
|
||||
// msgEthereumTx for the requested transaction
|
||||
// msg is the MsgEthereumTx for the requested transaction
|
||||
MsgEthereumTx msg = 1;
|
||||
// tx_index is not necessary anymore
|
||||
reserved 2;
|
||||
reserved "tx_index";
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
// trace_config holds extra parameters to trace functions.
|
||||
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.
|
||||
repeated MsgEthereumTx predecessors = 4;
|
||||
// block number of requested transaction
|
||||
// block_number of requested transaction
|
||||
int64 block_number = 5;
|
||||
// block hex hash of requested transaction
|
||||
// block_hash of requested transaction
|
||||
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];
|
||||
// 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
|
||||
message QueryTraceTxResponse {
|
||||
// response serialized in bytes
|
||||
// data is the response serialized in bytes
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
// QueryTraceBlockRequest defines TraceTx request
|
||||
message QueryTraceBlockRequest {
|
||||
// txs messages in the block
|
||||
// txs is an array of messages in the block
|
||||
repeated MsgEthereumTx txs = 1;
|
||||
// TraceConfig holds extra parameters to trace functions.
|
||||
// trace_config holds extra parameters to trace functions.
|
||||
TraceConfig trace_config = 3;
|
||||
// block number
|
||||
// block_number of the traced block
|
||||
int64 block_number = 5;
|
||||
// block hex hash
|
||||
// block_hash (hex) of the traced block
|
||||
string block_hash = 6;
|
||||
// block time
|
||||
// block_time of the traced block
|
||||
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
|
||||
message QueryTraceBlockResponse {
|
||||
// data is the response serialized in bytes
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
@ -278,7 +291,8 @@ message QueryTraceBlockResponse {
|
||||
// fee.
|
||||
message QueryBaseFeeRequest {}
|
||||
|
||||
// BaseFeeResponse returns the EIP1559 base fee.
|
||||
// QueryBaseFeeResponse returns the EIP1559 base fee.
|
||||
message QueryBaseFeeResponse {
|
||||
// base_fee is the EIP1559 base fee
|
||||
string base_fee = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.evm.v1;
|
||||
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "ethermint/evm/v1/evm.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.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";
|
||||
|
||||
@ -21,15 +21,14 @@ service Msg {
|
||||
message MsgEthereumTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// inner transaction data
|
||||
// data is inner transaction data of the Ethereum transaction
|
||||
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) = "-"];
|
||||
// transaction hash in hex format
|
||||
// hash of the transaction in hex format
|
||||
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
|
||||
// secp256k1 elliptic curve
|
||||
string from = 4;
|
||||
@ -44,16 +43,16 @@ message LegacyTx {
|
||||
|
||||
// nonce corresponds to the account nonce (transaction sequence).
|
||||
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"];
|
||||
// gas defines the gas limit defined for the transaction.
|
||||
uint64 gas = 3 [(gogoproto.customname) = "GasLimit"];
|
||||
// hex formatted address of the recipient
|
||||
// to is the hex formatted address of the recipient
|
||||
string to = 4;
|
||||
// value defines the unsigned integer value of the transaction amount.
|
||||
string value = 5
|
||||
[(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;
|
||||
// v defines the signature value
|
||||
bytes v = 7;
|
||||
@ -68,7 +67,7 @@ message AccessListTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "TxData";
|
||||
|
||||
// destination EVM chain ID
|
||||
// chain_id of the destination EVM chain
|
||||
string chain_id = 1 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.customname) = "ChainID",
|
||||
@ -76,17 +75,18 @@ message AccessListTx {
|
||||
];
|
||||
// nonce corresponds to the account nonce (transaction sequence).
|
||||
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"];
|
||||
// gas defines the gas limit defined for the transaction.
|
||||
uint64 gas = 4 [(gogoproto.customname) = "GasLimit"];
|
||||
// hex formatted address of the recipient
|
||||
// to is the recipient address in hex format
|
||||
string to = 5;
|
||||
// value defines the unsigned integer value of the transaction amount.
|
||||
string value = 6
|
||||
[(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;
|
||||
// accesses is an array of access tuples
|
||||
repeated AccessTuple accesses = 8
|
||||
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
||||
// v defines the signature value
|
||||
@ -102,7 +102,7 @@ message DynamicFeeTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
option (cosmos_proto.implements_interface) = "TxData";
|
||||
|
||||
// destination EVM chain ID
|
||||
// chain_id of the destination EVM chain
|
||||
string chain_id = 1 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.customname) = "ChainID",
|
||||
@ -110,19 +110,20 @@ message DynamicFeeTx {
|
||||
];
|
||||
// nonce corresponds to the account nonce (transaction sequence).
|
||||
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"];
|
||||
// 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"];
|
||||
// gas defines the gas limit defined for the transaction.
|
||||
uint64 gas = 5 [(gogoproto.customname) = "GasLimit"];
|
||||
// hex formatted address of the recipient
|
||||
// to is the hex formatted address of the recipient
|
||||
string to = 6;
|
||||
// value defines the the transaction amount.
|
||||
string value = 7
|
||||
[(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;
|
||||
// accesses is an array of access tuples
|
||||
repeated AccessTuple accesses = 9
|
||||
[(gogoproto.castrepeated) = "AccessList", (gogoproto.jsontag) = "accessList", (gogoproto.nullable) = false];
|
||||
// v defines the signature value
|
||||
@ -133,6 +134,7 @@ message DynamicFeeTx {
|
||||
bytes s = 12;
|
||||
}
|
||||
|
||||
// ExtensionOptionsEthereumTx is an extension option for ethereum transactions
|
||||
message ExtensionOptionsEthereumTx {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
}
|
||||
@ -141,18 +143,18 @@ message ExtensionOptionsEthereumTx {
|
||||
message MsgEthereumTxResponse {
|
||||
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
|
||||
// https://github.com/tendermint/tendermint/issues/6539 for reference
|
||||
string hash = 1;
|
||||
// logs contains the transaction hash and the proto-compatible ethereum
|
||||
// logs.
|
||||
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)
|
||||
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;
|
||||
// gas consumed by the transaction
|
||||
// gas_used specifies how much gas was consumed by the transaction
|
||||
uint64 gas_used = 5;
|
||||
}
|
||||
|
@ -7,26 +7,26 @@ option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
|
||||
|
||||
// Params defines the EVM module parameters
|
||||
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;
|
||||
// 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.
|
||||
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.
|
||||
uint32 elasticity_multiplier = 3;
|
||||
// DEPRECATED: initial base fee for EIP-1559 blocks.
|
||||
reserved 4;
|
||||
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;
|
||||
// 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];
|
||||
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
|
||||
string min_gas_price = 7
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||
// min gas denominator bounds the minimum gasUsed to be charged
|
||||
// to senders based on GasLimit
|
||||
// min_gas_multiplier bounds the minimum gas used to be charged
|
||||
// to senders based on gas limit
|
||||
string min_gas_multiplier = 8
|
||||
[(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false];
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
syntax = "proto3";
|
||||
package ethermint.feemarket.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "ethermint/feemarket/v1/feemarket.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
|
||||
|
||||
@ -14,7 +14,7 @@ message GenesisState {
|
||||
// Zero by default.
|
||||
reserved 2;
|
||||
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.
|
||||
uint64 block_gas = 3;
|
||||
}
|
@ -3,8 +3,8 @@ package ethermint.feemarket.v1;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
// import "cosmos/base/query/v1beta1/pagination.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "ethermint/feemarket/v1/feemarket.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option go_package = "github.com/cerc-io/laconicd/x/feemarket/types";
|
||||
|
||||
@ -39,8 +39,9 @@ message QueryParamsResponse {
|
||||
// fee.
|
||||
message QueryBaseFeeRequest {}
|
||||
|
||||
// BaseFeeResponse returns the EIP1559 base fee.
|
||||
// QueryBaseFeeResponse returns the EIP1559 base fee.
|
||||
message QueryBaseFeeResponse {
|
||||
// base_fee is the EIP1559 base fee
|
||||
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.
|
||||
message QueryBlockGasResponse {
|
||||
// gas is the returned block gas
|
||||
int64 gas = 1;
|
||||
}
|
@ -16,7 +16,10 @@ message EthAccount {
|
||||
|
||||
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
|
||||
[(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\""];
|
||||
}
|
||||
|
@ -9,21 +9,22 @@ option go_package = "github.com/cerc-io/laconicd/types";
|
||||
message TxResult {
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// the block height
|
||||
// height of the blockchain
|
||||
int64 height = 1;
|
||||
// cosmos tx index
|
||||
// tx_index of the cosmos transaction
|
||||
uint32 tx_index = 2;
|
||||
// the msg index in a batch tx
|
||||
// msg_index in a batch transaction
|
||||
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.
|
||||
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;
|
||||
// gas used by tx, if exceeds block gas limit,
|
||||
// it's set to gas limit which is what's actually deducted by ante handler.
|
||||
// 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.
|
||||
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;
|
||||
}
|
||||
|
@ -5,19 +5,21 @@ import "gogoproto/gogo.proto";
|
||||
|
||||
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 {
|
||||
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).
|
||||
uint64 typed_data_chain_id = 1
|
||||
[(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.
|
||||
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.
|
||||
bytes fee_payer_sig = 3 [(gogoproto.jsontag) = "feePayerSig,omitempty"];
|
||||
}
|
||||
|
@ -75,16 +75,10 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for proof
|
||||
var proofStr string
|
||||
if proof != nil {
|
||||
proofStr = proof.String()
|
||||
}
|
||||
|
||||
storageProofs[i] = rpctypes.StorageResult{
|
||||
Key: key,
|
||||
Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)),
|
||||
Proof: []string{proofStr},
|
||||
Proof: GetHexProofs(proof),
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,12 +99,6 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// check for proof
|
||||
var accProofStr string
|
||||
if proof != nil {
|
||||
accProofStr = proof.String()
|
||||
}
|
||||
|
||||
balance, ok := sdkmath.NewIntFromString(res.Balance)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid balance")
|
||||
@ -118,7 +106,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
|
||||
|
||||
return &rpctypes.AccountResult{
|
||||
Address: address,
|
||||
AccountProof: []string{accProofStr},
|
||||
AccountProof: GetHexProofs(proof),
|
||||
Balance: (*hexutil.Big)(balance.BigInt()),
|
||||
CodeHash: common.HexToHash(res.CodeHash),
|
||||
Nonce: hexutil.Uint64(res.Nonce),
|
||||
|
408
rpc/backend/account_info_test.go
Normal file
408
rpc/backend/account_info_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -5,13 +5,11 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/hd"
|
||||
rpctypes "github.com/cerc-io/laconicd/rpc/types"
|
||||
"github.com/cerc-io/laconicd/server/config"
|
||||
ethermint "github.com/cerc-io/laconicd/types"
|
||||
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -21,7 +19,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
@ -162,23 +159,6 @@ func NewBackend(
|
||||
panic(err)
|
||||
}
|
||||
|
||||
algos, _ := clientCtx.Keyring.SupportedAlgorithms()
|
||||
if !algos.Contains(hd.EthSecp256k1) {
|
||||
kr, err := keyring.New(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
clientCtx.KeyringDir,
|
||||
clientCtx.Input,
|
||||
clientCtx.Codec,
|
||||
hd.EthSecp256k1Option(),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
clientCtx = clientCtx.WithKeyring(kr)
|
||||
}
|
||||
|
||||
return &Backend{
|
||||
ctx: context.Background(),
|
||||
clientCtx: clientCtx,
|
||||
|
@ -2,12 +2,13 @@ package backend
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
|
||||
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
@ -25,52 +26,76 @@ import (
|
||||
"github.com/cerc-io/laconicd/indexer"
|
||||
"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"
|
||||
)
|
||||
|
||||
type BackendTestSuite struct {
|
||||
suite.Suite
|
||||
backend *Backend
|
||||
acc sdk.AccAddress
|
||||
signer keyring.Signer
|
||||
}
|
||||
|
||||
func TestBackendTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(BackendTestSuite))
|
||||
}
|
||||
|
||||
const ChainID = "ethermint_9000-1"
|
||||
|
||||
// SetupTest is executed before every BackendTestSuite test
|
||||
func (suite *BackendTestSuite) SetupTest() {
|
||||
ctx := server.NewDefaultContext()
|
||||
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
||||
|
||||
baseDir := suite.T().TempDir()
|
||||
nodeDirName := fmt.Sprintf("node")
|
||||
nodeDirName := "node"
|
||||
clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli")
|
||||
keyRing, err := suite.generateTestKeyring(clientDir)
|
||||
if err != nil {
|
||||
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)
|
||||
clientCtx := client.Context{}.WithChainID("ethermint_9000-1").
|
||||
clientCtx := client.Context{}.WithChainID(ChainID).
|
||||
WithHeight(1).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithKeyringDir(clientDir).
|
||||
WithKeyring(keyRing)
|
||||
WithKeyring(keyRing).
|
||||
WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts})
|
||||
|
||||
allowUnprotectedTxs := false
|
||||
|
||||
idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx)
|
||||
|
||||
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer)
|
||||
suite.backend.queryClient.QueryClient = mocks.NewQueryClient(suite.T())
|
||||
suite.backend.queryClient.QueryClient = mocks.NewEVMQueryClient(suite.T())
|
||||
suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
|
||||
suite.backend.queryClient.FeeMarket = mocks.NewFeeMarketQueryClient(suite.T())
|
||||
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
|
||||
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
|
||||
msgEthereumTx := evmtypes.NewTx(
|
||||
big.NewInt(1),
|
||||
suite.backend.chainID,
|
||||
uint64(0),
|
||||
&common.Address{},
|
||||
big.NewInt(0),
|
||||
@ -120,6 +145,7 @@ func (suite *BackendTestSuite) buildFormattedBlock(
|
||||
uint64(header.Height),
|
||||
uint64(0),
|
||||
baseFee,
|
||||
suite.backend.chainID,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
ethRPCTxs = []interface{}{rpcTx}
|
||||
@ -145,3 +171,25 @@ func (suite *BackendTestSuite) generateTestKeyring(clientDir string) (keyring.Ke
|
||||
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||
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
|
||||
}
|
||||
|
@ -376,6 +376,7 @@ func (b *Backend) RPCBlockFromTendermintBlock(
|
||||
uint64(block.Height),
|
||||
uint64(txIndex),
|
||||
baseFee,
|
||||
b.chainID,
|
||||
)
|
||||
if err != nil {
|
||||
b.logger.Debug("NewTransactionFromData for receipt failed", "hash", tx.Hash().Hex(), "error", err.Error())
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user