diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml deleted file mode 100644 index 653472200..000000000 --- a/.github/workflows/changelog.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Checks if a changelog is missing in the PR diff -name: Changelog Reminder -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - paths: ["**/*.go"] -permissions: - pull-requests: write -jobs: - remind: - name: Changelog Reminder - runs-on: depot-ubuntu-22.04-4 - # Skip draft PRs and PRs starting with: revert, test, chore, ci, docs, style, build, refactor - if: "!github.event.pull_request.draft && !contains(github.event.pull_request.title, 'revert') && !contains(github.event.pull_request.title, 'test') && !contains(github.event.pull_request.title, 'chore') && !contains(github.event.pull_request.title, 'ci') && !contains(github.event.pull_request.title, 'docs') && !contains(github.event.pull_request.title, 'style') && !contains(github.event.pull_request.title, 'build') && !contains(github.event.pull_request.title, 'refactor')" - steps: - - uses: actions/checkout@v4 - - uses: mskelton/changelog-reminder-action@v3 - with: - message: "@${{ github.actor }} your pull request is missing a changelog!" diff --git a/.github/workflows/check-changelog.yml b/.github/workflows/check-changelog.yml new file mode 100644 index 000000000..27ee6709f --- /dev/null +++ b/.github/workflows/check-changelog.yml @@ -0,0 +1,53 @@ +on: + pull_request: + types: [ opened, synchronize, reopened, ready_for_review, edited ] + paths: [ "**/*.go" ] +name: Changelog Reminder +jobs: + remind: + name: Changelog Reminder + runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check PR title for semantic commit type + run: | + # Get the PR title + PR_TITLE="${{ github.event.pull_request.title }}" + echo "PR Title: $PR_TITLE" + + # Check if PR title starts with feat, refactor, or fix + if echo "$PR_TITLE" | grep -qE "^(feat|refactor|fix)(\(.+\))?!?:"; then + echo "✅ PR title has relevant semantic commit type (feat, refactor, or fix)" + echo "has_relevant_pr_title=true" >> $GITHUB_ENV + else + echo "ℹ️ PR title doesn't have relevant semantic commit type. Skipping changelog check." + echo "has_relevant_pr_title=false" >> $GITHUB_ENV + fi + + - name: Check if CHANGELOG.md was modified + if: env.has_relevant_pr_title == 'true' + run: | + # Get the list of changed files in this PR + CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) + + # Check if CHANGELOG.md (case insensitive) is in the changed files + if echo "$CHANGED_FILES" | grep -qi "changelog\.md"; then + echo "✅ CHANGELOG.md has been modified in this PR" + echo "changelog_modified=true" >> $GITHUB_ENV + else + echo "❌ CHANGELOG.md has not been modified in this PR" + echo "changelog_modified=false" >> $GITHUB_ENV + fi + + - name: Fail if changelog not updated + if: env.has_relevant_pr_title == 'true' && env.changelog_modified == 'false' + run: | + echo "::error::CHANGELOG.md must be updated for PRs with feat, refactor, or fix commits" + exit 1 \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7bb3c3e39..f53336477 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -52,23 +52,14 @@ jobs: make lint-go markdown-lint: - name: markdownlint (cli2, minimal, non-blocking) + name: markdownlint (cli2, minimal) runs-on: ubuntu-latest timeout-minutes: 10 permissions: - contents: write # allows auto-fix pushes on same-repo PRs; forks stay read-only + contents: read # read-only permissions steps: - # Same-repo PRs: checkout the head branch so fixes can be pushed back - - name: Checkout PR head (same-repo) - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - ref: ${{ github.event.pull_request.head.ref }} - - # Fork PRs, merge queue, and any other case: default checkout (safe merge ref) - - name: Checkout (default) - if: github.event_name == 'merge_group' || github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + # Standard checkout for all cases + - name: Checkout uses: actions/checkout@v4 # Only run if markdown or configs changed @@ -85,32 +76,12 @@ jobs: with: node-version: "20" - # Lint (non-blocking): auto-fix on same-repo PRs, never fail the job - - name: markdownlint (check or fix) + # Lint: check only, fail on errors + - name: markdownlint (check only) id: md_lint if: env.GIT_DIFF - continue-on-error: true uses: DavidAnson/markdownlint-cli2-action@v16 with: globs: "**/*.md" config: .markdownlint.yml - fix: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }} - - # If fixes applied, commit & push (same-repo PRs only, not merge queue) - - name: Push auto-fixes (same-repo PRs only) - if: env.GIT_DIFF && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository - run: | - if [[ -n $(git status -s) ]]; then - git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - git add -A - git commit -m "Auto-fix markdown lint issues" - git push - fi - - # Warn if any issues remain after auto-fix (or on forks) - - name: Report remaining markdown issues (non-blocking) - if: env.GIT_DIFF && steps.md_lint.outcome == 'failure' - run: | - echo "::warning::Markdown lint issues remain after the check/fix step. For local fixes, run:" - echo " npx markdownlint-cli2 --config .markdownlint.yml --fix '**/*.md'" + fix: false diff --git a/.github/workflows/pr_title.yml b/.github/workflows/pr_title.yml new file mode 100644 index 000000000..f86d7c76b --- /dev/null +++ b/.github/workflows/pr_title.yml @@ -0,0 +1,15 @@ +name: PR Conventional Commit Validation + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + +jobs: + validate-pr-title: + runs-on: ubuntu-latest + steps: + - name: PR Conventional Commit Validation + uses: ytanikin/pr-conventional-commits@1.4.0 + with: + task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert","style","build"]' + add_label: 'false' \ No newline at end of file diff --git a/.github/workflows/system-test.yml b/.github/workflows/system-test.yml index 107b27974..1704bac9b 100644 --- a/.github/workflows/system-test.yml +++ b/.github/workflows/system-test.yml @@ -29,6 +29,9 @@ jobs: with: version: stable - uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true - uses: technote-space/get-diff-action@v6.1.2 with: PATTERNS: | diff --git a/CHANGELOG.md b/CHANGELOG.md index c4162096d..2c5713f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,56 @@ ## UNRELEASED -## v0.4.0 +### DEPENDENCIES + +### BUG FIXES + +- [\#471](https://github.com/cosmos/evm/pull/471) Notify new block for mempool in time +- [\#492](https://github.com/cosmos/evm/pull/492) Duplicate case switch to avoid empty execution block +- [\#509](https://github.com/cosmos/evm/pull/509) Allow value with slashes when query token_pairs +- [\#495](https://github.com/cosmos/evm/pull/495) Allow immediate SIGINT interrupt when mempool is not empty +- [\#416](https://github.com/cosmos/evm/pull/416) Fix regression in CometBlockResultByNumber when height is 0 to use the latest block. This fixes eth_getFilterLogs RPC. +- [\#545](https://github.com/cosmos/evm/pull/545) Check if mempool is not nil before accepting nonce gap error tx. +- [\#585](https://github.com/cosmos/evm/pull/585) Use zero constructor to avoid nil pointer panic when BaseFee is 0d +- [\#591](https://github.com/cosmos/evm/pull/591) CheckTxHandler should handle "invalid nonce" tx + +### IMPROVEMENTS + +- [\#538](https://github.com/cosmos/evm/pull/538) Optimize `eth_estimateGas` gRPC path: short-circuit plain transfers, add optimistic gas bound based on `MaxUsedGas`. +- [\#513](https://github.com/cosmos/evm/pull/513) Replace `TestEncodingConfig` with production `EncodingConfig` in encoding package to remove test dependencies from production code. +- [\#467](https://github.com/cosmos/evm/pull/467) Replace GlobalEVMMempool by passing to JSONRPC on initiate. +- [\#352](https://github.com/cosmos/evm/pull/352) Remove the creation of a Geth EVM instance, stateDB during the AnteHandler balance check. +- [\#496](https://github.com/cosmos/evm/pull/496) Simplify mempool instantiation by using configs instead of objects. +- [\#512](https://github.com/cosmos/evm/pull/512) Add integration test for appside mempool. +- [\#568](https://github.com/cosmos/evm/pull/568) Avoid unnecessary block notifications when the event bus is already set up. +- [\#511](https://github.com/cosmos/evm/pull/511) Minor code cleanup for `AddPrecompileFn`. +- [\#576](https://github.com/cosmos/evm/pull/576) Parse logs from the txResult.Data and avoid emitting EVM events to cosmos-sdk events. +- [\#584](https://github.com/cosmos/evm/pull/584) Fill block hash and timestamp for json rpc. +- [\#582](https://github.com/cosmos/evm/pull/582) Add block max-gas (from genesis.json) and new min-tip (from app.toml/flags) ingestion into mempool config +- [\#580](https://github.com/cosmos/evm/pull/580) add appside mempool e2e test +- [\#598](https://github.com/cosmos/evm/pull/598) Reduce number of times CreateQueryContext in mempool. +- [\#606](https://github.com/cosmos/evm/pull/606) Regenerate mock file for bank keeper related test. +- [\#609](https://github.com/cosmos/evm/pull/609) Make `erc20Keeper` optional in the EVM keeper +- [\#624](https://github.com/cosmos/evm/pull/624) Cleanup unnecessary `fix-revert-gas-refund-height`. +- [\#635](https://github.com/cosmos/evm/pull/635) Move DefaultStaticPrecompiles to /evm and allow projects to set it by default alongside the keeper. + + +### FEATURES + +- [\#346](https://github.com/cosmos/evm/pull/346) Add eth_createAccessList method and implementation +- [\#405](https://github.com/cosmos/evm/pull/405) Add erc20 factory precompile. +- [\#502](https://github.com/cosmos/evm/pull/502) Add block time in derived logs. +- [\#588](https://github.com/cosmos/evm/pull/588) go-ethereum metrics are now available in Cosmos SDK's telemetry server at host:port/geth/metrics (default localhost:1317/geth/metrics). + + +### STATE BREAKING + +### API-BREAKING + +- [\#477](https://github.com/cosmos/evm/pull/477) Refactor precompile constructors to accept keeper interfaces instead of concrete implementations, breaking the existing `NewPrecompile` function signatures. +- [\#594](https://github.com/cosmos/evm/pull/594) Remove all usage of x/params + +## v0.4.1 ### DEPENDENCIES @@ -45,6 +94,7 @@ - [\#398](https://github.com/cosmos/evm/pull/398) Post-audit security fixes (batch 4) - [\#442](https://github.com/cosmos/evm/pull/442) Prevent nil pointer by checking error in gov precompile FromResponse. - [\#387](https://github.com/cosmos/evm/pull/387) (Experimental) EVM-compatible appside mempool +- [\#476](https://github.com/cosmos/evm/pull/476) Add revert error e2e tests for contract and precompile calls ### FEATURES diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index edd96b8b7..c8827944f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,10 @@ We appreciate community contributions! To ensure a smooth process, please follow - All commits must be [signed](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). - Unsigned commits will be rejected. -3. **Documentation Contributions** +3. **Conventional Commit PR Titles** + - PR titles should use the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/#summary) format. + +4. **Documentation Contributions** - We only accept documentation PRs that make **substantial or impactful changes**. - Minor typo or style-only fixes in documentation will not be accepted. diff --git a/Makefile b/Makefile index cefd9633b..5bd994ea3 100644 --- a/Makefile +++ b/Makefile @@ -378,14 +378,90 @@ test-rpc-compat-stop: .PHONY: localnet-start localnet-stop localnet-build-env localnet-build-nodes test-rpc-compat test-rpc-compat-stop -test-system: build - ulimit -n 1300 +test-system: build-v04 build mkdir -p ./tests/systemtests/binaries/ cp $(BUILDDIR)/evmd ./tests/systemtests/binaries/ $(MAKE) -C tests/systemtests test +build-v04: + mkdir -p ./tests/systemtests/binaries/v0.4 + git checkout v0.4.1 + make build + cp $(BUILDDIR)/evmd ./tests/systemtests/binaries/v0.4 + git checkout - + mocks: @echo "--> generating mocks" @go get github.com/vektra/mockery/v2 @go generate ./... @make format-go + +############################################################################### +### D2 Diagrams ### +############################################################################### + +D2_THEME=300 +D2_DARK_THEME=200 +D2_LAYOUT=tala + +D2_ENV_VARS=D2_THEME=$(D2_THEME) \ + D2_DARK_THEME=$(D2_DARK_THEME) \ + D2_LAYOUT=$(D2_LAYOUT) + +.PHONY: d2check d2watch d2gen d2gen-all + +d2check: + @echo "🔍 checking if d2 is installed..." + @which d2 > /dev/null 2>&1 || { \ + echo "🔴 d2 is not installed, see installation docs: https://d2lang.com/tour/install/"; \ + exit 1; \ + } + @echo "🟢 d2 is installed" + @echo "🔍 checking if $(D2_LAYOUT) layout is installed..." + @d2 layout | grep $(D2_LAYOUT) > /dev/null 2>&1 || { \ + echo "🔴 $(D2_LAYOUT) layout is not installed, see docs: https://d2lang.com/tour/layouts/"; \ + exit 1; \ + } + @echo "🟢 $(D2_LAYOUT) layout is installed" + +d2watch: d2check + @if [ -z "$(FILE)" ]; then \ + echo "🔴 missing required parameter FILE, the correct usage is: make d2watch FILE=path/to/file.d2"; \ + exit 1; \ + fi + @if [ ! -f "$(FILE)" ]; then \ + echo "🔴 file $(FILE) does not exist"; \ + exit 1; \ + fi + @echo "🔄 watching $(FILE) for changes..." + @dir=$$(dirname "$(FILE)"); \ + basename=$$(basename "$(FILE)" .d2); \ + svgfile="$$dir/$$basename.svg"; \ + printf "📊 generating $$svgfile from $(FILE)... "; \ + $(D2_ENV_VARS) d2 --watch "$(FILE)" "$$svgfile" + +d2gen: d2check + @if [ -z "$(FILE)" ]; then \ + echo "🔴 missing required parameter FILE, the correct usage is: make d2gen FILE=path/to/file.d2"; \ + exit 1; \ + fi + @if [ ! -f "$(FILE)" ]; then \ + echo "🔴 file $(FILE) does not exist"; \ + exit 1; \ + fi + @dir=$$(dirname "$(FILE)"); \ + basename=$$(basename "$(FILE)" .d2); \ + svgfile="$$dir/$$basename.svg"; \ + printf "📊 generating $$svgfile from $(FILE)... "; \ + $(D2_ENV_VARS) d2 "$(FILE)" "$$svgfile" > /dev/null 2>&1 && echo "done ✅" || echo "failed ❌"; + +d2gen-all: d2check + @echo "🟢 generating svg files for all d2 diagrams..." + @find . -name "*.d2" -type f | while read d2file; do \ + dir=$$(dirname "$$d2file"); \ + basename=$$(basename "$$d2file" .d2); \ + svgfile="$$dir/$$basename.svg"; \ + printf "📊 generating $$svgfile from $$d2file... "; \ + $(D2_ENV_VARS) d2 "$$d2file" "$$svgfile" > /dev/null 2>&1 && echo "done ✅" || echo "failed ❌"; \ + done + @echo "✅ svg files generated for all d2 diagrams" diff --git a/README.md b/README.md index 6f716654f..4505ed86a 100644 --- a/README.md +++ b/README.md @@ -197,3 +197,8 @@ We welcome open source contributions and discussions! For more on contributing, Cosmos EVM is open-source under the Apache 2.0 license, an extension of the license of the original codebase (https://github.com/evmos/OS) created by Tharsis and the evmOS team - who conducted the foundational work for EVM compatibility and interoperability in Cosmos. + +### Key Contributors + +We at ICL want to thank our key contributors at [B-Harvest](https://bharvest.io/) and +[Mantra](https://www.mantrachain.io/) for contributing to and helping us drive the development of Cosmos EVM. diff --git a/ante/evm/05_signature_verification.go b/ante/evm/05_signature_verification.go index a845c75c5..4c2dd9146 100644 --- a/ante/evm/05_signature_verification.go +++ b/ante/evm/05_signature_verification.go @@ -32,11 +32,9 @@ func NewEthSigVerificationDecorator(ek anteinterfaces.EVMKeeper) EthSigVerificat // 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) { - evmParams := esvd.evmKeeper.GetParams(ctx) ethCfg := evmtypes.GetEthChainConfig() blockNum := big.NewInt(ctx.BlockHeight()) signer := ethtypes.MakeSigner(ethCfg, blockNum, uint64(ctx.BlockTime().Unix())) //#nosec G115 -- int overflow is not a concern here - allowUnprotectedTxs := evmParams.GetAllowUnprotectedTxs() msgs := tx.GetMsgs() if msgs == nil { @@ -49,7 +47,7 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) } - err := SignatureVerification(msgEthTx, msgEthTx.AsTransaction(), signer, allowUnprotectedTxs) + err := SignatureVerification(msgEthTx, msgEthTx.AsTransaction(), signer) if err != nil { return ctx, err } @@ -66,23 +64,7 @@ func SignatureVerification( msg *evmtypes.MsgEthereumTx, ethTx *ethtypes.Transaction, signer ethtypes.Signer, - allowUnprotectedTxs bool, ) error { - ethCfg := evmtypes.GetEthChainConfig() - - if !allowUnprotectedTxs { - if !ethTx.Protected() { - return errorsmod.Wrapf( - errortypes.ErrNotSupported, - "rejected unprotected ethereum transaction; please sign your transaction according to EIP-155 to protect it against replay-attacks") - } - if ethTx.ChainId().Uint64() != ethCfg.ChainID.Uint64() { - return errorsmod.Wrapf( - errortypes.ErrInvalidChainID, - "rejected ethereum transaction with incorrect chain-id; expected %d, got %d", ethCfg.ChainID, ethTx.ChainId()) - } - } - if err := msg.VerifySender(signer); err != nil { return errorsmod.Wrapf(errortypes.ErrorInvalidSigner, "signature verification failed: %s", err.Error()) } diff --git a/ante/evm/07_can_transfer.go b/ante/evm/07_can_transfer.go index 8ff5c966d..21d0fe6c0 100644 --- a/ante/evm/07_can_transfer.go +++ b/ante/evm/07_can_transfer.go @@ -3,12 +3,10 @@ package evm import ( "math/big" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" anteinterfaces "github.com/cosmos/evm/ante/interfaces" "github.com/cosmos/evm/utils" - "github.com/cosmos/evm/x/vm/statedb" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -34,23 +32,13 @@ func CanTransfer( ) } - // NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below - cfg := &statedb.EVMConfig{ - Params: params, - CoinBase: common.Address{}, - BaseFee: baseFee, - } - - stateDB := statedb.New(ctx, evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) - evm := evmKeeper.NewEVM(ctx, msg, 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 convertedValue, err := utils.Uint256FromBigInt(msg.Value) if err != nil { return err } - if msg.Value.Sign() > 0 && !evm.Context.CanTransfer(stateDB, msg.From, convertedValue) { + if msg.Value.Sign() > 0 && evmKeeper.GetAccount(ctx, msg.From).Balance.Cmp(convertedValue) < 0 { return errorsmod.Wrapf( errortypes.ErrInsufficientFunds, "failed to transfer %s from address %s using the EVM block context transfer function", diff --git a/ante/evm/09_increment_sequence.go b/ante/evm/09_increment_sequence.go index 3440d7c61..fe28cf896 100644 --- a/ante/evm/09_increment_sequence.go +++ b/ante/evm/09_increment_sequence.go @@ -22,15 +22,15 @@ func IncrementNonce( accountNonce := account.GetSequence() // we merged the accountNonce verification to accountNonce increment, so when tx includes multiple messages // with same sender, they'll be accepted. - if txNonce != accountNonce { - if txNonce > accountNonce { - return errorsmod.Wrapf( - mempool.ErrNonceGap, - "tx nonce: %d, account accountNonce: %d", txNonce, accountNonce, - ) - } + if txNonce > accountNonce { return errorsmod.Wrapf( - errortypes.ErrInvalidSequence, + mempool.ErrNonceGap, + "tx nonce: %d, account accountNonce: %d", txNonce, accountNonce, + ) + } + if txNonce < accountNonce { + return errorsmod.Wrapf( + mempool.ErrNonceLow, "invalid nonce; got %d, expected %d", txNonce, accountNonce, ) } diff --git a/ante/evm/mono_decorator.go b/ante/evm/mono_decorator.go index 3277fbc76..982336cf2 100644 --- a/ante/evm/mono_decorator.go +++ b/ante/evm/mono_decorator.go @@ -157,7 +157,6 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne ethMsg, ethTx, decUtils.Signer, - decUtils.EvmParams.AllowUnprotectedTxs, ); err != nil { return ctx, err } diff --git a/api/cosmos/evm/erc20/v1/erc20.pulsar.go b/api/cosmos/evm/erc20/v1/erc20.pulsar.go index d582bb6c1..388117150 100644 --- a/api/cosmos/evm/erc20/v1/erc20.pulsar.go +++ b/api/cosmos/evm/erc20/v1/erc20.pulsar.go @@ -3550,8 +3550,8 @@ func (Owner) EnumDescriptor() ([]byte, []int) { return file_cosmos_evm_erc20_v1_erc20_proto_rawDescGZIP(), []int{0} } -// TokenPair defines an instance that records a pairing consisting of a native -// Cosmos Coin and an ERC20 token address. +// TokenPair defines an instance that records a pairing (mapping) consisting of a native +// Cosmos Coin and an ERC20 token address. The "pair" does not imply an asset swap exchange. type TokenPair struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/api/cosmos/evm/erc20/v1/genesis.pulsar.go b/api/cosmos/evm/erc20/v1/genesis.pulsar.go index 2a8af313b..f10f894c9 100644 --- a/api/cosmos/evm/erc20/v1/genesis.pulsar.go +++ b/api/cosmos/evm/erc20/v1/genesis.pulsar.go @@ -1458,7 +1458,7 @@ type GenesisState struct { // params are the erc20 module parameters at genesis Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` - // token_pairs is a slice of the registered token pairs at genesis + // token_pairs is a slice of the registered token pairs (mappings) at genesis TokenPairs []*TokenPair `protobuf:"bytes,2,rep,name=token_pairs,json=tokenPairs,proto3" json:"token_pairs,omitempty"` // allowances is a slice of the registered allowances at genesis Allowances []*Allowance `protobuf:"bytes,3,rep,name=allowances,proto3" json:"allowances,omitempty"` diff --git a/api/cosmos/evm/erc20/v1/query.pulsar.go b/api/cosmos/evm/erc20/v1/query.pulsar.go index 857714876..766fa21bb 100644 --- a/api/cosmos/evm/erc20/v1/query.pulsar.go +++ b/api/cosmos/evm/erc20/v1/query.pulsar.go @@ -2961,7 +2961,7 @@ var file_cosmos_evm_erc20_v1_query_proto_rawDesc = []byte{ 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x32, 0xb7, 0x03, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x91, 0x01, 0x0a, 0x0a, 0x54, + 0x32, 0xba, 0x03, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x91, 0x01, 0x0a, 0x0a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, @@ -2970,38 +2970,38 @@ var file_cosmos_evm_erc20_v1_query_proto_rawDesc = []byte{ 0x72, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2f, - 0x76, 0x31, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x96, + 0x76, 0x31, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x09, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, 0x2f, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x12, 0x2b, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x2f, - 0x7b, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, - 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x65, 0x72, 0x63, 0x32, 0x30, - 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0xc2, 0x01, 0x0a, 0x17, 0x63, - 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, - 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, - 0x6d, 0x2f, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x72, 0x63, 0x32, 0x30, - 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x45, 0x45, 0xaa, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x45, 0x72, 0x63, 0x32, - 0x30, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, - 0x6d, 0x5c, 0x45, 0x72, 0x63, 0x32, 0x30, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, - 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x45, 0x72, 0x63, 0x32, 0x30, 0x3a, 0x3a, 0x56, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x7b, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x06, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, + 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x65, 0x72, 0x63, 0x32, + 0x30, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, + 0x12, 0x1b, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x65, 0x72, + 0x63, 0x32, 0x30, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0xc2, 0x01, + 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, + 0x2e, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x65, 0x72, 0x63, 0x32, 0x30, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x72, + 0x63, 0x32, 0x30, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x45, 0x45, 0xaa, 0x02, 0x13, 0x43, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x63, 0x32, 0x30, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x45, + 0x72, 0x63, 0x32, 0x30, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1f, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x45, 0x72, 0x63, 0x32, 0x30, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x43, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x45, 0x72, 0x63, 0x32, 0x30, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/cosmos/evm/erc20/v1/query_grpc.pb.go b/api/cosmos/evm/erc20/v1/query_grpc.pb.go index 14fa6fbd2..c31355491 100644 --- a/api/cosmos/evm/erc20/v1/query_grpc.pb.go +++ b/api/cosmos/evm/erc20/v1/query_grpc.pb.go @@ -28,9 +28,9 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type QueryClient interface { - // TokenPairs retrieves registered token pairs + // TokenPairs retrieves registered token pairs (mappings)x TokenPairs(ctx context.Context, in *QueryTokenPairsRequest, opts ...grpc.CallOption) (*QueryTokenPairsResponse, error) - // TokenPair retrieves a registered token pair + // TokenPair retrieves a registered token pair (mapping) TokenPair(ctx context.Context, in *QueryTokenPairRequest, opts ...grpc.CallOption) (*QueryTokenPairResponse, error) // Params retrieves the erc20 module params Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) @@ -75,9 +75,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . // All implementations must embed UnimplementedQueryServer // for forward compatibility type QueryServer interface { - // TokenPairs retrieves registered token pairs + // TokenPairs retrieves registered token pairs (mappings)x TokenPairs(context.Context, *QueryTokenPairsRequest) (*QueryTokenPairsResponse, error) - // TokenPair retrieves a registered token pair + // TokenPair retrieves a registered token pair (mapping) TokenPair(context.Context, *QueryTokenPairRequest) (*QueryTokenPairResponse, error) // Params retrieves the erc20 module params Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) diff --git a/api/cosmos/evm/vm/v1/evm.pulsar.go b/api/cosmos/evm/vm/v1/evm.pulsar.go index 8d1585d6b..7980ded78 100644 --- a/api/cosmos/evm/vm/v1/evm.pulsar.go +++ b/api/cosmos/evm/vm/v1/evm.pulsar.go @@ -156,10 +156,10 @@ var ( md_Params protoreflect.MessageDescriptor fd_Params_evm_denom protoreflect.FieldDescriptor fd_Params_extra_eips protoreflect.FieldDescriptor - fd_Params_allow_unprotected_txs protoreflect.FieldDescriptor fd_Params_evm_channels protoreflect.FieldDescriptor fd_Params_access_control protoreflect.FieldDescriptor fd_Params_active_static_precompiles protoreflect.FieldDescriptor + fd_Params_history_serve_window protoreflect.FieldDescriptor ) func init() { @@ -167,10 +167,10 @@ func init() { md_Params = File_cosmos_evm_vm_v1_evm_proto.Messages().ByName("Params") fd_Params_evm_denom = md_Params.Fields().ByName("evm_denom") fd_Params_extra_eips = md_Params.Fields().ByName("extra_eips") - fd_Params_allow_unprotected_txs = md_Params.Fields().ByName("allow_unprotected_txs") fd_Params_evm_channels = md_Params.Fields().ByName("evm_channels") fd_Params_access_control = md_Params.Fields().ByName("access_control") fd_Params_active_static_precompiles = md_Params.Fields().ByName("active_static_precompiles") + fd_Params_history_serve_window = md_Params.Fields().ByName("history_serve_window") } var _ protoreflect.Message = (*fastReflection_Params)(nil) @@ -250,12 +250,6 @@ func (x *fastReflection_Params) Range(f func(protoreflect.FieldDescriptor, proto return } } - if x.AllowUnprotectedTxs != false { - value := protoreflect.ValueOfBool(x.AllowUnprotectedTxs) - if !f(fd_Params_allow_unprotected_txs, value) { - return - } - } if len(x.EvmChannels) != 0 { value := protoreflect.ValueOfList(&_Params_7_list{list: &x.EvmChannels}) if !f(fd_Params_evm_channels, value) { @@ -274,6 +268,12 @@ func (x *fastReflection_Params) Range(f func(protoreflect.FieldDescriptor, proto return } } + if x.HistoryServeWindow != uint64(0) { + value := protoreflect.ValueOfUint64(x.HistoryServeWindow) + if !f(fd_Params_history_serve_window, value) { + return + } + } } // Has reports whether a field is populated. @@ -293,14 +293,14 @@ func (x *fastReflection_Params) Has(fd protoreflect.FieldDescriptor) bool { return x.EvmDenom != "" case "cosmos.evm.vm.v1.Params.extra_eips": return len(x.ExtraEips) != 0 - case "cosmos.evm.vm.v1.Params.allow_unprotected_txs": - return x.AllowUnprotectedTxs != false case "cosmos.evm.vm.v1.Params.evm_channels": return len(x.EvmChannels) != 0 case "cosmos.evm.vm.v1.Params.access_control": return x.AccessControl != nil case "cosmos.evm.vm.v1.Params.active_static_precompiles": return len(x.ActiveStaticPrecompiles) != 0 + case "cosmos.evm.vm.v1.Params.history_serve_window": + return x.HistoryServeWindow != uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Params")) @@ -321,14 +321,14 @@ func (x *fastReflection_Params) Clear(fd protoreflect.FieldDescriptor) { x.EvmDenom = "" case "cosmos.evm.vm.v1.Params.extra_eips": x.ExtraEips = nil - case "cosmos.evm.vm.v1.Params.allow_unprotected_txs": - x.AllowUnprotectedTxs = false case "cosmos.evm.vm.v1.Params.evm_channels": x.EvmChannels = nil case "cosmos.evm.vm.v1.Params.access_control": x.AccessControl = nil case "cosmos.evm.vm.v1.Params.active_static_precompiles": x.ActiveStaticPrecompiles = nil + case "cosmos.evm.vm.v1.Params.history_serve_window": + x.HistoryServeWindow = uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Params")) @@ -354,9 +354,6 @@ func (x *fastReflection_Params) Get(descriptor protoreflect.FieldDescriptor) pro } listValue := &_Params_4_list{list: &x.ExtraEips} return protoreflect.ValueOfList(listValue) - case "cosmos.evm.vm.v1.Params.allow_unprotected_txs": - value := x.AllowUnprotectedTxs - return protoreflect.ValueOfBool(value) case "cosmos.evm.vm.v1.Params.evm_channels": if len(x.EvmChannels) == 0 { return protoreflect.ValueOfList(&_Params_7_list{}) @@ -372,6 +369,9 @@ func (x *fastReflection_Params) Get(descriptor protoreflect.FieldDescriptor) pro } listValue := &_Params_9_list{list: &x.ActiveStaticPrecompiles} return protoreflect.ValueOfList(listValue) + case "cosmos.evm.vm.v1.Params.history_serve_window": + value := x.HistoryServeWindow + return protoreflect.ValueOfUint64(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Params")) @@ -398,8 +398,6 @@ func (x *fastReflection_Params) Set(fd protoreflect.FieldDescriptor, value proto lv := value.List() clv := lv.(*_Params_4_list) x.ExtraEips = *clv.list - case "cosmos.evm.vm.v1.Params.allow_unprotected_txs": - x.AllowUnprotectedTxs = value.Bool() case "cosmos.evm.vm.v1.Params.evm_channels": lv := value.List() clv := lv.(*_Params_7_list) @@ -410,6 +408,8 @@ func (x *fastReflection_Params) Set(fd protoreflect.FieldDescriptor, value proto lv := value.List() clv := lv.(*_Params_9_list) x.ActiveStaticPrecompiles = *clv.list + case "cosmos.evm.vm.v1.Params.history_serve_window": + x.HistoryServeWindow = value.Uint() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Params")) @@ -455,8 +455,8 @@ func (x *fastReflection_Params) Mutable(fd protoreflect.FieldDescriptor) protore return protoreflect.ValueOfList(value) case "cosmos.evm.vm.v1.Params.evm_denom": panic(fmt.Errorf("field evm_denom of message cosmos.evm.vm.v1.Params is not mutable")) - case "cosmos.evm.vm.v1.Params.allow_unprotected_txs": - panic(fmt.Errorf("field allow_unprotected_txs of message cosmos.evm.vm.v1.Params is not mutable")) + case "cosmos.evm.vm.v1.Params.history_serve_window": + panic(fmt.Errorf("field history_serve_window of message cosmos.evm.vm.v1.Params is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Params")) @@ -475,8 +475,6 @@ func (x *fastReflection_Params) NewField(fd protoreflect.FieldDescriptor) protor case "cosmos.evm.vm.v1.Params.extra_eips": list := []int64{} return protoreflect.ValueOfList(&_Params_4_list{list: &list}) - case "cosmos.evm.vm.v1.Params.allow_unprotected_txs": - return protoreflect.ValueOfBool(false) case "cosmos.evm.vm.v1.Params.evm_channels": list := []string{} return protoreflect.ValueOfList(&_Params_7_list{list: &list}) @@ -486,6 +484,8 @@ func (x *fastReflection_Params) NewField(fd protoreflect.FieldDescriptor) protor case "cosmos.evm.vm.v1.Params.active_static_precompiles": list := []string{} return protoreflect.ValueOfList(&_Params_9_list{list: &list}) + case "cosmos.evm.vm.v1.Params.history_serve_window": + return protoreflect.ValueOfUint64(uint64(0)) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Params")) @@ -566,9 +566,6 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { } n += 1 + runtime.Sov(uint64(l)) + l } - if x.AllowUnprotectedTxs { - n += 2 - } if len(x.EvmChannels) > 0 { for _, s := range x.EvmChannels { l = len(s) @@ -585,6 +582,9 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { n += 1 + l + runtime.Sov(uint64(l)) } } + if x.HistoryServeWindow != 0 { + n += 1 + runtime.Sov(uint64(x.HistoryServeWindow)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -614,6 +614,11 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.HistoryServeWindow != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.HistoryServeWindow)) + i-- + dAtA[i] = 0x50 + } if len(x.ActiveStaticPrecompiles) > 0 { for iNdEx := len(x.ActiveStaticPrecompiles) - 1; iNdEx >= 0; iNdEx-- { i -= len(x.ActiveStaticPrecompiles[iNdEx]) @@ -646,16 +651,6 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { dAtA[i] = 0x3a } } - if x.AllowUnprotectedTxs { - i-- - if x.AllowUnprotectedTxs { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x28 - } if len(x.ExtraEips) > 0 { var pksize2 int for _, num := range x.ExtraEips { @@ -841,26 +836,6 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { } else { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ExtraEips", wireType) } - case 5: - if wireType != 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field AllowUnprotectedTxs", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - x.AllowUnprotectedTxs = bool(v != 0) case 7: if wireType != 2 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field EvmChannels", wireType) @@ -961,6 +936,25 @@ func (x *fastReflection_Params) ProtoMethods() *protoiface.Methods { } x.ActiveStaticPrecompiles = append(x.ActiveStaticPrecompiles, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 10: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field HistoryServeWindow", wireType) + } + x.HistoryServeWindow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.HistoryServeWindow |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -5001,16 +4995,17 @@ func (x *_Log_2_list) IsValid() bool { } var ( - md_Log protoreflect.MessageDescriptor - fd_Log_address protoreflect.FieldDescriptor - fd_Log_topics protoreflect.FieldDescriptor - fd_Log_data protoreflect.FieldDescriptor - fd_Log_block_number protoreflect.FieldDescriptor - fd_Log_tx_hash protoreflect.FieldDescriptor - fd_Log_tx_index protoreflect.FieldDescriptor - fd_Log_block_hash protoreflect.FieldDescriptor - fd_Log_index protoreflect.FieldDescriptor - fd_Log_removed protoreflect.FieldDescriptor + md_Log protoreflect.MessageDescriptor + fd_Log_address protoreflect.FieldDescriptor + fd_Log_topics protoreflect.FieldDescriptor + fd_Log_data protoreflect.FieldDescriptor + fd_Log_block_number protoreflect.FieldDescriptor + fd_Log_tx_hash protoreflect.FieldDescriptor + fd_Log_tx_index protoreflect.FieldDescriptor + fd_Log_block_hash protoreflect.FieldDescriptor + fd_Log_index protoreflect.FieldDescriptor + fd_Log_removed protoreflect.FieldDescriptor + fd_Log_block_timestamp protoreflect.FieldDescriptor ) func init() { @@ -5025,6 +5020,7 @@ func init() { fd_Log_block_hash = md_Log.Fields().ByName("block_hash") fd_Log_index = md_Log.Fields().ByName("index") fd_Log_removed = md_Log.Fields().ByName("removed") + fd_Log_block_timestamp = md_Log.Fields().ByName("block_timestamp") } var _ protoreflect.Message = (*fastReflection_Log)(nil) @@ -5146,6 +5142,12 @@ func (x *fastReflection_Log) Range(f func(protoreflect.FieldDescriptor, protoref return } } + if x.BlockTimestamp != uint64(0) { + value := protoreflect.ValueOfUint64(x.BlockTimestamp) + if !f(fd_Log_block_timestamp, value) { + return + } + } } // Has reports whether a field is populated. @@ -5179,6 +5181,8 @@ func (x *fastReflection_Log) Has(fd protoreflect.FieldDescriptor) bool { return x.Index != uint64(0) case "cosmos.evm.vm.v1.Log.removed": return x.Removed != false + case "cosmos.evm.vm.v1.Log.block_timestamp": + return x.BlockTimestamp != uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Log")) @@ -5213,6 +5217,8 @@ func (x *fastReflection_Log) Clear(fd protoreflect.FieldDescriptor) { x.Index = uint64(0) case "cosmos.evm.vm.v1.Log.removed": x.Removed = false + case "cosmos.evm.vm.v1.Log.block_timestamp": + x.BlockTimestamp = uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Log")) @@ -5259,6 +5265,9 @@ func (x *fastReflection_Log) Get(descriptor protoreflect.FieldDescriptor) protor case "cosmos.evm.vm.v1.Log.removed": value := x.Removed return protoreflect.ValueOfBool(value) + case "cosmos.evm.vm.v1.Log.block_timestamp": + value := x.BlockTimestamp + return protoreflect.ValueOfUint64(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Log")) @@ -5299,6 +5308,8 @@ func (x *fastReflection_Log) Set(fd protoreflect.FieldDescriptor, value protoref x.Index = value.Uint() case "cosmos.evm.vm.v1.Log.removed": x.Removed = value.Bool() + case "cosmos.evm.vm.v1.Log.block_timestamp": + x.BlockTimestamp = value.Uint() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Log")) @@ -5341,6 +5352,8 @@ func (x *fastReflection_Log) Mutable(fd protoreflect.FieldDescriptor) protorefle panic(fmt.Errorf("field index of message cosmos.evm.vm.v1.Log is not mutable")) case "cosmos.evm.vm.v1.Log.removed": panic(fmt.Errorf("field removed of message cosmos.evm.vm.v1.Log is not mutable")) + case "cosmos.evm.vm.v1.Log.block_timestamp": + panic(fmt.Errorf("field block_timestamp of message cosmos.evm.vm.v1.Log is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Log")) @@ -5373,6 +5386,8 @@ func (x *fastReflection_Log) NewField(fd protoreflect.FieldDescriptor) protorefl return protoreflect.ValueOfUint64(uint64(0)) case "cosmos.evm.vm.v1.Log.removed": return protoreflect.ValueOfBool(false) + case "cosmos.evm.vm.v1.Log.block_timestamp": + return protoreflect.ValueOfUint64(uint64(0)) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.Log")) @@ -5476,6 +5491,9 @@ func (x *fastReflection_Log) ProtoMethods() *protoiface.Methods { if x.Removed { n += 2 } + if x.BlockTimestamp != 0 { + n += 1 + runtime.Sov(uint64(x.BlockTimestamp)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -5505,6 +5523,11 @@ func (x *fastReflection_Log) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.BlockTimestamp != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.BlockTimestamp)) + i-- + dAtA[i] = 0x50 + } if x.Removed { i-- if x.Removed { @@ -5855,6 +5878,25 @@ func (x *fastReflection_Log) ProtoMethods() *protoiface.Methods { } } x.Removed = bool(v != 0) + case 10: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BlockTimestamp", wireType) + } + x.BlockTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.BlockTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -8785,9 +8827,6 @@ type Params struct { EvmDenom string `protobuf:"bytes,1,opt,name=evm_denom,json=evmDenom,proto3" json:"evm_denom,omitempty"` // extra_eips defines the additional EIPs for the vm.Config ExtraEips []int64 `protobuf:"varint,4,rep,packed,name=extra_eips,json=extraEips,proto3" json:"extra_eips,omitempty"` - // allow_unprotected_txs defines if replay-protected (i.e non EIP155 - // signed) transactions can be executed on the state machine. - AllowUnprotectedTxs bool `protobuf:"varint,5,opt,name=allow_unprotected_txs,json=allowUnprotectedTxs,proto3" json:"allow_unprotected_txs,omitempty"` // evm_channels is the list of channel identifiers from EVM compatible chains EvmChannels []string `protobuf:"bytes,7,rep,name=evm_channels,json=evmChannels,proto3" json:"evm_channels,omitempty"` // access_control defines the permission policy of the EVM @@ -8795,6 +8834,7 @@ type Params struct { // active_static_precompiles defines the slice of hex addresses of the // precompiled contracts that are active ActiveStaticPrecompiles []string `protobuf:"bytes,9,rep,name=active_static_precompiles,json=activeStaticPrecompiles,proto3" json:"active_static_precompiles,omitempty"` + HistoryServeWindow uint64 `protobuf:"varint,10,opt,name=history_serve_window,json=historyServeWindow,proto3" json:"history_serve_window,omitempty"` } func (x *Params) Reset() { @@ -8831,13 +8871,6 @@ func (x *Params) GetExtraEips() []int64 { return nil } -func (x *Params) GetAllowUnprotectedTxs() bool { - if x != nil { - return x.AllowUnprotectedTxs - } - return false -} - func (x *Params) GetEvmChannels() []string { if x != nil { return x.EvmChannels @@ -8859,6 +8892,13 @@ func (x *Params) GetActiveStaticPrecompiles() []string { return nil } +func (x *Params) GetHistoryServeWindow() uint64 { + if x != nil { + return x.HistoryServeWindow + } + return 0 +} + // AccessControl defines the permission policy of the EVM // for creating and calling contracts type AccessControl struct { @@ -9338,6 +9378,8 @@ type Log struct { // reorganisation. You must pay attention to this field if you receive logs // through a filter query. Removed bool `protobuf:"varint,9,opt,name=removed,proto3" json:"removed,omitempty"` + // block_timestamp is the timestamp of the block in which the transaction was + BlockTimestamp uint64 `protobuf:"varint,10,opt,name=block_timestamp,json=blockTimestamp,proto3" json:"block_timestamp,omitempty"` } func (x *Log) Reset() { @@ -9423,6 +9465,13 @@ func (x *Log) GetRemoved() bool { return false } +func (x *Log) GetBlockTimestamp() uint64 { + if x != nil { + return x.BlockTimestamp + } + return 0 +} + // TxResult stores results of Tx execution. type TxResult struct { state protoimpl.MessageState @@ -9746,7 +9795,7 @@ var file_cosmos_evm_vm_v1_evm_proto_rawDesc = []byte{ 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x1a, 0x11, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, - 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb0, 0x03, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb4, 0x03, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x31, 0x0a, 0x09, 0x65, 0x76, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xf2, 0xde, 0x1f, 0x10, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x65, 0x76, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x52, 0x08, 0x65, 0x76, 0x6d, @@ -9754,295 +9803,299 @@ var file_cosmos_evm_vm_v1_evm_proto_rawDesc = []byte{ 0x69, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x03, 0x42, 0x22, 0xe2, 0xde, 0x1f, 0x09, 0x45, 0x78, 0x74, 0x72, 0x61, 0x45, 0x49, 0x50, 0x73, 0xf2, 0xde, 0x1f, 0x11, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x65, 0x69, 0x70, 0x73, 0x22, 0x52, 0x09, 0x65, - 0x78, 0x74, 0x72, 0x61, 0x45, 0x69, 0x70, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x5f, 0x75, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x78, - 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x6e, - 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x78, 0x73, 0x12, 0x32, 0x0a, 0x0c, - 0x65, 0x76, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x09, 0x42, 0x0f, 0xe2, 0xde, 0x1f, 0x0b, 0x45, 0x56, 0x4d, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x73, 0x52, 0x0b, 0x65, 0x76, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, - 0x12, 0x5d, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x15, 0xc8, 0xde, 0x1f, 0x00, 0xe2, - 0xde, 0x1f, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, - 0x3a, 0x0a, 0x19, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, - 0x5f, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, - 0x50, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x3a, 0x1b, 0x8a, 0xe7, 0xb0, - 0x2a, 0x16, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x78, 0x2f, 0x76, - 0x6d, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, - 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x91, 0x01, 0x0a, 0x0d, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x41, 0x0a, 0x06, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x54, 0x79, 0x70, - 0x65, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, - 0x3d, 0x0a, 0x04, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x78, 0x74, 0x72, 0x61, 0x45, 0x69, 0x70, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x65, 0x76, 0x6d, 0x5f, + 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0f, + 0xe2, 0xde, 0x1f, 0x0b, 0x45, 0x56, 0x4d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, + 0x0b, 0x65, 0x76, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x5d, 0x0a, 0x0e, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, + 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x15, 0xc8, 0xde, 0x1f, 0x00, 0xe2, 0xde, 0x1f, 0x0d, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x52, 0x0d, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x70, 0x72, 0x65, + 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x50, 0x72, 0x65, 0x63, + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x3a, 0x1b, 0x8a, 0xe7, 0xb0, 0x2a, 0x16, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x78, 0x2f, 0x76, 0x6d, 0x2f, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, + 0x10, 0x04, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x91, + 0x01, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x12, 0x41, 0x0a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x54, 0x79, 0x70, 0x65, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x63, 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x04, 0x63, 0x61, + 0x6c, 0x6c, 0x22, 0xdd, 0x01, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x54, 0x79, - 0x70, 0x65, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x04, 0x63, 0x61, 0x6c, 0x6c, 0x22, 0xdd, - 0x01, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x42, 0x24, 0xe2, 0xde, 0x1f, 0x0a, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0xf2, 0xde, 0x1f, 0x12, 0x79, 0x61, 0x6d, 0x6c, 0x3a, - 0x22, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x52, 0x0a, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, 0x13, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x6c, 0x69, 0x73, 0x74, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x33, 0xe2, 0xde, 0x1f, 0x11, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x73, 0x74, 0xf2, 0xde, 0x1f, - 0x1a, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x52, 0x11, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x73, 0x74, 0x22, 0xa8, - 0x10, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, - 0x0a, 0x0f, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, - 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x16, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x68, 0x6f, 0x6d, 0x65, - 0x73, 0x74, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0e, 0x68, 0x6f, - 0x6d, 0x65, 0x73, 0x74, 0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x68, 0x0a, 0x0e, - 0x64, 0x61, 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x42, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xe2, - 0xde, 0x1f, 0x0c, 0x44, 0x41, 0x4f, 0x46, 0x6f, 0x72, 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0xf2, - 0xde, 0x1f, 0x15, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x64, 0x61, 0x6f, 0x5f, 0x66, 0x6f, 0x72, - 0x6b, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0c, 0x64, 0x61, 0x6f, 0x46, 0x6f, 0x72, - 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, 0x10, 0x64, 0x61, 0x6f, 0x5f, 0x66, 0x6f, - 0x72, 0x6b, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x42, 0x2d, 0xe2, 0xde, 0x1f, 0x0e, 0x44, 0x41, 0x4f, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0xf2, 0xde, 0x1f, 0x17, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x64, 0x61, - 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x52, - 0x0e, 0x64, 0x61, 0x6f, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, - 0x62, 0x0a, 0x0c, 0x65, 0x69, 0x70, 0x31, 0x35, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, - 0xe2, 0xde, 0x1f, 0x0b, 0x45, 0x49, 0x50, 0x31, 0x35, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0xf2, - 0xde, 0x1f, 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x65, 0x69, 0x70, 0x31, 0x35, 0x30, 0x5f, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, 0x65, 0x69, 0x70, 0x31, 0x35, 0x30, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x62, 0x0a, 0x0c, 0x65, 0x69, 0x70, 0x31, 0x35, 0x35, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3f, 0xda, 0xde, 0x1f, 0x15, 0x63, + 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x42, 0x24, 0xe2, 0xde, 0x1f, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0xf2, 0xde, 0x1f, 0x12, 0x79, + 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x22, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x63, 0x0a, + 0x13, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, + 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x33, 0xe2, 0xde, 0x1f, 0x11, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, 0x73, + 0x74, 0xf2, 0xde, 0x1f, 0x1a, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x52, + 0x11, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x4c, 0x69, + 0x73, 0x74, 0x22, 0xa8, 0x10, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x0f, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x61, 0x64, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xda, 0xde, 0x1f, + 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, + 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x16, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, + 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, + 0x52, 0x0e, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x12, 0x68, 0x0a, 0x0e, 0x64, 0x61, 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x42, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, + 0x49, 0x6e, 0x74, 0xe2, 0xde, 0x1f, 0x0c, 0x44, 0x41, 0x4f, 0x46, 0x6f, 0x72, 0x6b, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0xf2, 0xde, 0x1f, 0x15, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x64, 0x61, 0x6f, + 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0c, 0x64, 0x61, + 0x6f, 0x46, 0x6f, 0x72, 0x6b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, 0x10, 0x64, 0x61, + 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x42, 0x2d, 0xe2, 0xde, 0x1f, 0x0e, 0x44, 0x41, 0x4f, 0x46, 0x6f, 0x72, + 0x6b, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0xf2, 0xde, 0x1f, 0x17, 0x79, 0x61, 0x6d, 0x6c, + 0x3a, 0x22, 0x64, 0x61, 0x6f, 0x5f, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x22, 0x52, 0x0e, 0x64, 0x61, 0x6f, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x12, 0x62, 0x0a, 0x0c, 0x65, 0x69, 0x70, 0x31, 0x35, 0x30, 0x5f, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, - 0x2e, 0x49, 0x6e, 0x74, 0xe2, 0xde, 0x1f, 0x0b, 0x45, 0x49, 0x50, 0x31, 0x35, 0x35, 0x42, 0x6c, + 0x2e, 0x49, 0x6e, 0x74, 0xe2, 0xde, 0x1f, 0x0b, 0x45, 0x49, 0x50, 0x31, 0x35, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0xf2, 0xde, 0x1f, 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x65, 0x69, 0x70, - 0x31, 0x35, 0x35, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, 0x65, 0x69, 0x70, 0x31, - 0x35, 0x35, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x62, 0x0a, 0x0c, 0x65, 0x69, 0x70, 0x31, 0x35, - 0x38, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3f, 0xda, + 0x31, 0x35, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, 0x65, 0x69, 0x70, 0x31, + 0x35, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x62, 0x0a, 0x0c, 0x65, 0x69, 0x70, 0x31, 0x35, + 0x35, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xe2, 0xde, 0x1f, 0x0b, 0x45, 0x49, 0x50, 0x31, - 0x35, 0x38, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0xf2, 0xde, 0x1f, 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, - 0x22, 0x65, 0x69, 0x70, 0x31, 0x35, 0x38, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, - 0x65, 0x69, 0x70, 0x31, 0x35, 0x38, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x5c, 0x0a, 0x0f, 0x62, - 0x79, 0x7a, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x35, 0x35, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0xf2, 0xde, 0x1f, 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, + 0x22, 0x65, 0x69, 0x70, 0x31, 0x35, 0x35, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, + 0x65, 0x69, 0x70, 0x31, 0x35, 0x35, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x62, 0x0a, 0x0c, 0x65, + 0x69, 0x70, 0x31, 0x35, 0x38, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x3f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, + 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xe2, 0xde, 0x1f, 0x0b, + 0x45, 0x49, 0x50, 0x31, 0x35, 0x38, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0xf2, 0xde, 0x1f, 0x13, 0x79, + 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x65, 0x69, 0x70, 0x31, 0x35, 0x38, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x22, 0x52, 0x0b, 0x65, 0x69, 0x70, 0x31, 0x35, 0x38, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x5c, 0x0a, 0x0f, 0x62, 0x79, 0x7a, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x33, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, + 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x16, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x62, 0x79, 0x7a, + 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0e, 0x62, + 0x79, 0x7a, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x6b, 0x0a, + 0x14, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, + 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, + 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x1b, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, + 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x5f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x13, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, + 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x5f, 0x0a, 0x10, 0x70, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x34, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, - 0xde, 0x1f, 0x16, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x62, 0x79, 0x7a, 0x61, 0x6e, 0x74, 0x69, - 0x75, 0x6d, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0e, 0x62, 0x79, 0x7a, 0x61, 0x6e, - 0x74, 0x69, 0x75, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x6b, 0x0a, 0x14, 0x63, 0x6f, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, - 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x1b, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x63, 0x6f, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x22, 0x52, 0x13, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x70, 0x6c, - 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x5f, 0x0a, 0x10, 0x70, 0x65, 0x74, 0x65, 0x72, 0x73, - 0x62, 0x75, 0x72, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x34, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, - 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x17, 0x79, - 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x70, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x5f, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0f, 0x70, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, - 0x72, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x59, 0x0a, 0x0e, 0x69, 0x73, 0x74, 0x61, 0x6e, - 0x62, 0x75, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x32, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, - 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x15, 0x79, 0x61, - 0x6d, 0x6c, 0x3a, 0x22, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x22, 0x52, 0x0d, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x64, 0x0a, 0x12, 0x6d, 0x75, 0x69, 0x72, 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, - 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36, - 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, - 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x19, 0x79, 0x61, 0x6d, - 0x6c, 0x3a, 0x22, 0x6d, 0x75, 0x69, 0x72, 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x10, 0x6d, 0x75, 0x69, 0x72, 0x47, 0x6c, 0x61, 0x63, - 0x69, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x53, 0x0a, 0x0c, 0x62, 0x65, 0x72, 0x6c, - 0x69, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, - 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, - 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x13, 0x79, 0x61, 0x6d, - 0x6c, 0x3a, 0x22, 0x62, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, - 0x52, 0x0b, 0x62, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x53, 0x0a, - 0x0c, 0x6c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x11, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x30, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0xde, 0x1f, 0x17, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x70, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, + 0x75, 0x72, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0f, 0x70, 0x65, 0x74, 0x65, + 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x59, 0x0a, 0x0e, 0x69, + 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x32, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, - 0x1f, 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, 0x6c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x67, 0x0a, 0x13, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x67, 0x6c, 0x61, 0x63, - 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x37, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, - 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x1a, 0x79, 0x61, - 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, - 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x11, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x47, - 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x64, 0x0a, 0x12, 0x67, - 0x72, 0x61, 0x79, 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, - 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x19, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x67, 0x72, 0x61, 0x79, - 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, - 0x10, 0x67, 0x72, 0x61, 0x79, 0x47, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x6a, 0x0a, 0x14, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x6e, 0x65, 0x74, 0x73, 0x70, - 0x6c, 0x69, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x38, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, - 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x1b, 0x79, 0x61, - 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x6e, 0x65, 0x74, 0x73, 0x70, 0x6c, - 0x69, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x12, 0x6d, 0x65, 0x72, 0x67, 0x65, - 0x4e, 0x65, 0x74, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x19, 0x0a, - 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x18, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, - 0x6d, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x1a, - 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x56, 0x0a, 0x0d, 0x73, 0x68, - 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x31, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, - 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x14, - 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x73, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x63, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, + 0x1f, 0x15, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, + 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0d, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, + 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x64, 0x0a, 0x12, 0x6d, 0x75, 0x69, 0x72, 0x5f, 0x67, + 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x36, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, + 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, + 0x19, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x75, 0x69, 0x72, 0x5f, 0x67, 0x6c, 0x61, 0x63, + 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x10, 0x6d, 0x75, 0x69, 0x72, + 0x47, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x53, 0x0a, 0x0c, + 0x62, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x30, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, + 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, + 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x62, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x5f, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, 0x62, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x53, 0x0a, 0x0c, 0x6c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x42, 0x30, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, - 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x12, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x63, 0x61, 0x6e, 0x63, - 0x75, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0a, 0x63, 0x61, 0x6e, 0x63, 0x75, 0x6e, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x70, 0x72, 0x61, 0x67, 0x75, 0x65, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xda, 0xde, 0x1f, 0x15, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, - 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x12, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x70, 0x72, - 0x61, 0x67, 0x75, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0a, 0x70, 0x72, 0x61, 0x67, - 0x75, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x76, 0x65, 0x72, 0x6b, 0x6c, 0x65, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xda, 0xde, 0x1f, + 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x13, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6c, 0x6f, 0x6e, 0x64, + 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x0b, 0x6c, 0x6f, 0x6e, 0x64, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x67, 0x0a, 0x13, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, + 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x37, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, + 0x1f, 0x1a, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x67, 0x6c, + 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x11, 0x61, 0x72, + 0x72, 0x6f, 0x77, 0x47, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x64, 0x0a, 0x12, 0x67, 0x72, 0x61, 0x79, 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0x36, 0xda, 0xde, 0x1f, + 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, + 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x19, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, + 0x67, 0x72, 0x61, 0x79, 0x5f, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x22, 0x52, 0x10, 0x67, 0x72, 0x61, 0x79, 0x47, 0x6c, 0x61, 0x63, 0x69, 0x65, 0x72, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x6a, 0x0a, 0x14, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x6e, + 0x65, 0x74, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, + 0x1f, 0x1b, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x5f, 0x6e, 0x65, + 0x74, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x52, 0x12, 0x6d, + 0x65, 0x72, 0x67, 0x65, 0x4e, 0x65, 0x74, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x18, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, + 0x6f, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x1a, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x56, + 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, + 0x1b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x31, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, + 0xf2, 0xde, 0x1f, 0x14, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x73, 0x68, 0x61, 0x6e, 0x67, 0x68, + 0x61, 0x69, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0c, 0x73, 0x68, 0x61, 0x6e, 0x67, 0x68, + 0x61, 0x69, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x63, 0x61, 0x6e, 0x63, 0x75, 0x6e, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x12, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, - 0x76, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0a, 0x76, 0x65, - 0x72, 0x6b, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x6f, 0x73, 0x61, 0x6b, - 0x61, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2e, 0xda, 0xde, - 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, - 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x11, 0x79, 0x61, 0x6d, 0x6c, 0x3a, - 0x22, 0x6f, 0x73, 0x61, 0x6b, 0x61, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x09, 0x6f, 0x73, - 0x61, 0x6b, 0x61, 0x54, 0x69, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, - 0x16, 0x10, 0x17, 0x4a, 0x04, 0x08, 0x17, 0x10, 0x18, 0x22, 0x2f, 0x0a, 0x05, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x50, 0x0a, 0x0f, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, - 0x68, 0x12, 0x29, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x22, 0xca, 0x02, 0x0a, - 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, - 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x0c, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x0f, 0xea, 0xde, 0x1f, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, - 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x13, 0xea, 0xde, 0x1f, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2f, 0x0a, 0x08, - 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x42, 0x14, - 0xea, 0xde, 0x1f, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2c, 0x0a, - 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x0d, 0xea, 0xde, 0x1f, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x05, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x42, 0x0c, 0xea, 0xde, 0x1f, 0x08, - 0x6c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0x90, 0x02, 0x0a, 0x08, 0x54, 0x78, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x1b, 0xf2, 0xde, 0x1f, 0x17, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, - 0x6c, 0x6f, 0x6f, 0x6d, 0x12, 0x57, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, - 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x42, 0x1b, 0xc8, 0xde, 0x1f, 0x00, 0xf2, 0xde, - 0x1f, 0x0e, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x74, 0x78, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x22, - 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x06, 0x74, 0x78, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x10, 0x0a, - 0x03, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x65, 0x74, 0x12, - 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, - 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, - 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, 0x22, 0x61, 0x0a, 0x0b, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0f, 0xea, 0xde, 0x1f, - 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x0b, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, 0x22, - 0xa0, 0x04, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x65, 0x78, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x06, 0x72, 0x65, 0x65, 0x78, 0x65, 0x63, 0x12, 0x35, 0x0a, 0x0d, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x42, 0x10, 0xea, 0xde, 0x1f, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, - 0x12, 0x3b, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x12, 0xea, 0xde, 0x1f, 0x0e, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x0e, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, 0x65, - 0x62, 0x75, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x3b, 0x0a, 0x09, 0x6f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x6f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x42, 0x10, 0xea, - 0xde, 0x1f, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, - 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x42, 0x0a, - 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x42, 0x14, 0xea, 0xde, 0x1f, 0x10, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, - 0x10, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x3e, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xea, - 0xde, 0x1f, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x10, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x52, 0x0e, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x13, 0x64, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x4e, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, - 0x64, 0x65, 0x2a, 0xc0, 0x01, 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x4c, 0x45, 0x53, 0x53, 0x10, - 0x00, 0x1a, 0x1c, 0x8a, 0x9d, 0x20, 0x18, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, - 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x12, - 0x34, 0x0a, 0x16, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, - 0x45, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x18, 0x8a, 0x9d, 0x20, - 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x45, - 0x44, 0x10, 0x02, 0x1a, 0x1a, 0x8a, 0x9d, 0x20, 0x16, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, - 0x79, 0x70, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x1a, - 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x42, 0xab, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x42, 0x08, - 0x45, 0x76, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x26, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x76, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x6d, - 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x45, 0x56, 0xaa, 0x02, 0x10, 0x43, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, 0x56, 0x6d, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x43, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, 0x56, 0x31, 0xe2, 0x02, - 0x1c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, 0x56, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, - 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x56, 0x6d, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0a, 0x63, 0x61, + 0x6e, 0x63, 0x75, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x70, 0x72, 0x61, 0x67, + 0x75, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xda, + 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, + 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x12, 0x79, 0x61, 0x6d, 0x6c, + 0x3a, 0x22, 0x70, 0x72, 0x61, 0x67, 0x75, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x52, 0x0a, + 0x70, 0x72, 0x61, 0x67, 0x75, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x50, 0x0a, 0x0b, 0x76, 0x65, + 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x2f, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, + 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x12, 0x79, 0x61, + 0x6d, 0x6c, 0x3a, 0x22, 0x76, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, + 0x52, 0x0a, 0x76, 0x65, 0x72, 0x6b, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0a, + 0x6f, 0x73, 0x61, 0x6b, 0x61, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x2e, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, + 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xf2, 0xde, 0x1f, 0x11, 0x79, + 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x6f, 0x73, 0x61, 0x6b, 0x61, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, + 0x52, 0x09, 0x6f, 0x73, 0x61, 0x6b, 0x61, 0x54, 0x69, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x05, 0x10, + 0x06, 0x4a, 0x04, 0x08, 0x16, 0x10, 0x17, 0x4a, 0x04, 0x08, 0x17, 0x10, 0x18, 0x22, 0x2f, 0x0a, + 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x50, + 0x0a, 0x0f, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x29, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, + 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, + 0x22, 0x87, 0x03, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x32, + 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x0f, 0xea, 0xde, 0x1f, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x13, 0xea, 0xde, 0x1f, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x2f, 0x0a, 0x08, 0x74, 0x78, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x14, 0xea, 0xde, 0x1f, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x74, 0x78, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x2c, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xea, 0xde, 0x1f, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x48, 0x61, 0x73, 0x68, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x22, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x42, 0x0c, + 0xea, 0xde, 0x1f, 0x08, 0x6c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x3b, 0x0a, + 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x42, 0x12, 0xea, 0xde, 0x1f, 0x0e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x90, 0x02, 0x0a, 0x08, 0x54, + 0x78, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x1b, 0xf2, 0xde, 0x1f, 0x17, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x12, 0x57, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x6c, 0x6f, 0x67, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x6f, 0x67, 0x73, 0x42, 0x1b, 0xc8, 0xde, 0x1f, 0x00, 0xf2, + 0xde, 0x1f, 0x0e, 0x79, 0x61, 0x6d, 0x6c, 0x3a, 0x22, 0x74, 0x78, 0x5f, 0x6c, 0x6f, 0x67, 0x73, + 0x22, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x06, 0x74, 0x78, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x10, + 0x0a, 0x03, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x65, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, + 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, 0x22, 0x61, 0x0a, + 0x0b, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x75, 0x70, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0f, 0xea, 0xde, + 0x1f, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x0b, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, + 0x22, 0xa0, 0x04, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, + 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x65, 0x78, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x72, 0x65, 0x65, 0x78, 0x65, 0x63, 0x12, 0x35, 0x0a, 0x0d, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x42, 0x10, 0xea, 0xde, 0x1f, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, + 0x61, 0x63, 0x6b, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x63, + 0x6b, 0x12, 0x3b, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x12, 0xea, 0xde, 0x1f, 0x0e, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x0e, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, + 0x65, 0x62, 0x75, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x3b, 0x0a, 0x09, 0x6f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x6f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x42, 0x10, + 0xea, 0xde, 0x1f, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x42, + 0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x42, 0x14, 0xea, 0xde, 0x1f, 0x10, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x10, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x44, 0x61, + 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, + 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, + 0xea, 0xde, 0x1f, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x10, 0x74, 0x72, 0x61, 0x63, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x52, 0x0e, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x13, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x64, + 0x61, 0x74, 0x61, 0x22, 0x4e, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, + 0x6f, 0x64, 0x65, 0x2a, 0xc0, 0x01, 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x4c, 0x45, 0x53, 0x53, + 0x10, 0x00, 0x1a, 0x1c, 0x8a, 0x9d, 0x20, 0x18, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, + 0x70, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x6c, 0x65, 0x73, 0x73, + 0x12, 0x34, 0x0a, 0x16, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x52, 0x45, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x18, 0x8a, 0x9d, + 0x20, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x73, 0x74, + 0x72, 0x69, 0x63, 0x74, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, + 0x45, 0x44, 0x10, 0x02, 0x1a, 0x1a, 0x8a, 0x9d, 0x20, 0x16, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x54, 0x79, 0x70, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, + 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x42, 0xab, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x42, + 0x08, 0x45, 0x76, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x26, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x76, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x76, + 0x6d, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x45, 0x56, 0xaa, 0x02, 0x10, 0x43, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, 0x56, 0x6d, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x43, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, 0x56, 0x31, 0xe2, + 0x02, 0x1c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, + 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x56, 0x6d, + 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/cosmos/evm/vm/v1/tx.pulsar.go b/api/cosmos/evm/vm/v1/tx.pulsar.go index 89f899c3c..f39f7451e 100644 --- a/api/cosmos/evm/vm/v1/tx.pulsar.go +++ b/api/cosmos/evm/vm/v1/tx.pulsar.go @@ -913,12 +913,15 @@ func (x *_MsgEthereumTxResponse_2_list) IsValid() bool { } var ( - md_MsgEthereumTxResponse protoreflect.MessageDescriptor - fd_MsgEthereumTxResponse_hash protoreflect.FieldDescriptor - fd_MsgEthereumTxResponse_logs protoreflect.FieldDescriptor - fd_MsgEthereumTxResponse_ret protoreflect.FieldDescriptor - fd_MsgEthereumTxResponse_vm_error protoreflect.FieldDescriptor - fd_MsgEthereumTxResponse_gas_used protoreflect.FieldDescriptor + md_MsgEthereumTxResponse protoreflect.MessageDescriptor + fd_MsgEthereumTxResponse_hash protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_logs protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_ret protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_vm_error protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_gas_used protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_max_used_gas protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_block_hash protoreflect.FieldDescriptor + fd_MsgEthereumTxResponse_block_timestamp protoreflect.FieldDescriptor ) func init() { @@ -929,6 +932,9 @@ func init() { fd_MsgEthereumTxResponse_ret = md_MsgEthereumTxResponse.Fields().ByName("ret") fd_MsgEthereumTxResponse_vm_error = md_MsgEthereumTxResponse.Fields().ByName("vm_error") fd_MsgEthereumTxResponse_gas_used = md_MsgEthereumTxResponse.Fields().ByName("gas_used") + fd_MsgEthereumTxResponse_max_used_gas = md_MsgEthereumTxResponse.Fields().ByName("max_used_gas") + fd_MsgEthereumTxResponse_block_hash = md_MsgEthereumTxResponse.Fields().ByName("block_hash") + fd_MsgEthereumTxResponse_block_timestamp = md_MsgEthereumTxResponse.Fields().ByName("block_timestamp") } var _ protoreflect.Message = (*fastReflection_MsgEthereumTxResponse)(nil) @@ -1026,6 +1032,24 @@ func (x *fastReflection_MsgEthereumTxResponse) Range(f func(protoreflect.FieldDe return } } + if x.MaxUsedGas != uint64(0) { + value := protoreflect.ValueOfUint64(x.MaxUsedGas) + if !f(fd_MsgEthereumTxResponse_max_used_gas, value) { + return + } + } + if len(x.BlockHash) != 0 { + value := protoreflect.ValueOfBytes(x.BlockHash) + if !f(fd_MsgEthereumTxResponse_block_hash, value) { + return + } + } + if x.BlockTimestamp != uint64(0) { + value := protoreflect.ValueOfUint64(x.BlockTimestamp) + if !f(fd_MsgEthereumTxResponse_block_timestamp, value) { + return + } + } } // Has reports whether a field is populated. @@ -1051,6 +1075,12 @@ func (x *fastReflection_MsgEthereumTxResponse) Has(fd protoreflect.FieldDescript return x.VmError != "" case "cosmos.evm.vm.v1.MsgEthereumTxResponse.gas_used": return x.GasUsed != uint64(0) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.max_used_gas": + return x.MaxUsedGas != uint64(0) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_hash": + return len(x.BlockHash) != 0 + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_timestamp": + return x.BlockTimestamp != uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.MsgEthereumTxResponse")) @@ -1077,6 +1107,12 @@ func (x *fastReflection_MsgEthereumTxResponse) Clear(fd protoreflect.FieldDescri x.VmError = "" case "cosmos.evm.vm.v1.MsgEthereumTxResponse.gas_used": x.GasUsed = uint64(0) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.max_used_gas": + x.MaxUsedGas = uint64(0) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_hash": + x.BlockHash = nil + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_timestamp": + x.BlockTimestamp = uint64(0) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.MsgEthereumTxResponse")) @@ -1111,6 +1147,15 @@ func (x *fastReflection_MsgEthereumTxResponse) Get(descriptor protoreflect.Field case "cosmos.evm.vm.v1.MsgEthereumTxResponse.gas_used": value := x.GasUsed return protoreflect.ValueOfUint64(value) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.max_used_gas": + value := x.MaxUsedGas + return protoreflect.ValueOfUint64(value) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_hash": + value := x.BlockHash + return protoreflect.ValueOfBytes(value) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_timestamp": + value := x.BlockTimestamp + return protoreflect.ValueOfUint64(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.MsgEthereumTxResponse")) @@ -1143,6 +1188,12 @@ func (x *fastReflection_MsgEthereumTxResponse) Set(fd protoreflect.FieldDescript x.VmError = value.Interface().(string) case "cosmos.evm.vm.v1.MsgEthereumTxResponse.gas_used": x.GasUsed = value.Uint() + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.max_used_gas": + x.MaxUsedGas = value.Uint() + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_hash": + x.BlockHash = value.Bytes() + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_timestamp": + x.BlockTimestamp = value.Uint() default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.MsgEthereumTxResponse")) @@ -1177,6 +1228,12 @@ func (x *fastReflection_MsgEthereumTxResponse) Mutable(fd protoreflect.FieldDesc panic(fmt.Errorf("field vm_error of message cosmos.evm.vm.v1.MsgEthereumTxResponse is not mutable")) case "cosmos.evm.vm.v1.MsgEthereumTxResponse.gas_used": panic(fmt.Errorf("field gas_used of message cosmos.evm.vm.v1.MsgEthereumTxResponse is not mutable")) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.max_used_gas": + panic(fmt.Errorf("field max_used_gas of message cosmos.evm.vm.v1.MsgEthereumTxResponse is not mutable")) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_hash": + panic(fmt.Errorf("field block_hash of message cosmos.evm.vm.v1.MsgEthereumTxResponse is not mutable")) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_timestamp": + panic(fmt.Errorf("field block_timestamp of message cosmos.evm.vm.v1.MsgEthereumTxResponse is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.MsgEthereumTxResponse")) @@ -1201,6 +1258,12 @@ func (x *fastReflection_MsgEthereumTxResponse) NewField(fd protoreflect.FieldDes return protoreflect.ValueOfString("") case "cosmos.evm.vm.v1.MsgEthereumTxResponse.gas_used": return protoreflect.ValueOfUint64(uint64(0)) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.max_used_gas": + return protoreflect.ValueOfUint64(uint64(0)) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_hash": + return protoreflect.ValueOfBytes(nil) + case "cosmos.evm.vm.v1.MsgEthereumTxResponse.block_timestamp": + return protoreflect.ValueOfUint64(uint64(0)) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: cosmos.evm.vm.v1.MsgEthereumTxResponse")) @@ -1291,6 +1354,16 @@ func (x *fastReflection_MsgEthereumTxResponse) ProtoMethods() *protoiface.Method if x.GasUsed != 0 { n += 1 + runtime.Sov(uint64(x.GasUsed)) } + if x.MaxUsedGas != 0 { + n += 1 + runtime.Sov(uint64(x.MaxUsedGas)) + } + l = len(x.BlockHash) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.BlockTimestamp != 0 { + n += 1 + runtime.Sov(uint64(x.BlockTimestamp)) + } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -1320,6 +1393,23 @@ func (x *fastReflection_MsgEthereumTxResponse) ProtoMethods() *protoiface.Method i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } + if x.BlockTimestamp != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.BlockTimestamp)) + i-- + dAtA[i] = 0x40 + } + if len(x.BlockHash) > 0 { + i -= len(x.BlockHash) + copy(dAtA[i:], x.BlockHash) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.BlockHash))) + i-- + dAtA[i] = 0x3a + } + if x.MaxUsedGas != 0 { + i = runtime.EncodeVarint(dAtA, i, uint64(x.MaxUsedGas)) + i-- + dAtA[i] = 0x30 + } if x.GasUsed != 0 { i = runtime.EncodeVarint(dAtA, i, uint64(x.GasUsed)) i-- @@ -1562,6 +1652,78 @@ func (x *fastReflection_MsgEthereumTxResponse) ProtoMethods() *protoiface.Method break } } + case 6: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field MaxUsedGas", wireType) + } + x.MaxUsedGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.MaxUsedGas |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.BlockHash = append(x.BlockHash[:0], dAtA[iNdEx:postIndex]...) + if x.BlockHash == nil { + x.BlockHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field BlockTimestamp", wireType) + } + x.BlockTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + x.BlockTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -3474,6 +3636,12 @@ type MsgEthereumTxResponse struct { VmError string `protobuf:"bytes,4,opt,name=vm_error,json=vmError,proto3" json:"vm_error,omitempty"` // gas_used specifies how much gas was consumed by the transaction GasUsed uint64 `protobuf:"varint,5,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` + // max_used_gas specifies the gas consumed by the transaction, not including refunds + MaxUsedGas uint64 `protobuf:"varint,6,opt,name=max_used_gas,json=maxUsedGas,proto3" json:"max_used_gas,omitempty"` + // include the block hash for json-rpc to use + BlockHash []byte `protobuf:"bytes,7,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` + // include the block timestamp for json-rpc to use + BlockTimestamp uint64 `protobuf:"varint,8,opt,name=block_timestamp,json=blockTimestamp,proto3" json:"block_timestamp,omitempty"` } func (x *MsgEthereumTxResponse) Reset() { @@ -3531,6 +3699,27 @@ func (x *MsgEthereumTxResponse) GetGasUsed() uint64 { return 0 } +func (x *MsgEthereumTxResponse) GetMaxUsedGas() uint64 { + if x != nil { + return x.MaxUsedGas + } + return 0 +} + +func (x *MsgEthereumTxResponse) GetBlockHash() []byte { + if x != nil { + return x.BlockHash + } + return nil +} + +func (x *MsgEthereumTxResponse) GetBlockTimestamp() uint64 { + if x != nil { + return x.BlockTimestamp + } + return 0 +} + // MsgUpdateParams defines a Msg for updating the x/vm module parameters. type MsgUpdateParams struct { state protoimpl.MessageState @@ -3706,7 +3895,7 @@ var file_cosmos_evm_vm_v1_tx_proto_rawDesc = []byte{ 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x22, 0x0a, 0x1a, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, 0x22, - 0xa4, 0x01, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, + 0x8e, 0x02, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x29, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, @@ -3716,69 +3905,76 @@ var file_cosmos_evm_vm_v1_tx_proto_rawDesc = []byte{ 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, - 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, 0x22, 0xba, 0x01, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, - 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x09, 0xc8, 0xde, - 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, - 0x32, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x8a, - 0xe7, 0xb0, 0x2a, 0x1f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x78, - 0x2f, 0x76, 0x6d, 0x2f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd6, - 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, - 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, - 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x12, 0x49, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, - 0x0b, 0x70, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x3a, 0x39, 0x82, 0xe7, - 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x8a, 0xe7, 0xb0, 0x2a, - 0x26, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x78, 0x2f, 0x76, 0x6d, - 0x2f, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x52, 0x65, + 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x61, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x65, 0x64, 0x47, + 0x61, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, + 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x3a, 0x04, 0x88, 0xa0, 0x1f, 0x00, + 0x22, 0xba, 0x01, 0x0a, 0x0f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x06, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x09, 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, + 0x01, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x32, 0x82, 0xe7, 0xb0, 0x2a, 0x09, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x8a, 0xe7, 0xb0, 0x2a, 0x1f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x78, 0x2f, 0x76, 0x6d, 0x2f, 0x4d, 0x73, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x19, 0x0a, + 0x17, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd6, 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x0b, 0x70, + 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x42, 0x09, + 0xc8, 0xde, 0x1f, 0x00, 0xa8, 0xe7, 0xb0, 0x2a, 0x01, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x3a, 0x39, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x8a, 0xe7, 0xb0, 0x2a, 0x26, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x78, 0x2f, 0x76, 0x6d, 0x2f, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xdc, 0x02, 0x0a, 0x03, 0x4d, 0x73, - 0x67, 0x12, 0x7d, 0x0a, 0x0a, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x12, - 0x1f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, - 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, - 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1f, 0x22, 0x1d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x76, - 0x6d, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5f, 0x74, 0x78, - 0x12, 0x5c, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x12, 0x21, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, - 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, - 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, - 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x1a, - 0x30, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, + 0x73, 0x22, 0x20, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x32, 0xdc, 0x02, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x7d, 0x0a, 0x0a, 0x45, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x1d, 0x2f, 0x63, 0x6f, + 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x76, 0x6d, 0x2f, 0x76, 0x31, 0x2f, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5f, 0x74, 0x78, 0x12, 0x5c, 0x0a, 0x0c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x21, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x29, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x12, + 0x28, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, - 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0xaa, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, - 0x31, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x26, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x65, 0x76, 0x6d, 0x2f, 0x76, 0x6d, 0x2f, 0x76, 0x31, 0x3b, - 0x76, 0x6d, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x45, 0x56, 0xaa, 0x02, 0x10, 0x43, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x45, 0x76, 0x6d, 0x2e, 0x56, 0x6d, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, - 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, 0x56, 0x31, - 0xe2, 0x02, 0x1c, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, - 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x56, - 0x6d, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x73, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x72, 0x65, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, + 0x2a, 0x01, 0x42, 0xaa, 0x01, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x65, 0x76, 0x6d, 0x2e, 0x76, 0x6d, 0x2e, 0x76, 0x31, 0x42, 0x07, 0x54, 0x78, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x26, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, + 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, + 0x65, 0x76, 0x6d, 0x2f, 0x76, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x6d, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x43, 0x45, 0x56, 0xaa, 0x02, 0x10, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x45, 0x76, + 0x6d, 0x2e, 0x56, 0x6d, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x10, 0x43, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1c, 0x43, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x5c, 0x45, 0x76, 0x6d, 0x5c, 0x56, 0x6d, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, + 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x43, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x3a, 0x3a, 0x45, 0x76, 0x6d, 0x3a, 0x3a, 0x56, 0x6d, 0x3a, 0x3a, 0x56, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/config/server_app_options.go b/config/server_app_options.go new file mode 100644 index 000000000..cac9cc7a1 --- /dev/null +++ b/config/server_app_options.go @@ -0,0 +1,94 @@ +package config + +import ( + "math" + "path/filepath" + + "github.com/holiman/uint256" + "github.com/spf13/cast" + + srvflags "github.com/cosmos/evm/server/flags" + + "cosmossdk.io/log" + + "github.com/cosmos/cosmos-sdk/client/flags" + sdkserver "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" +) + +// GetBlockGasLimit reads the genesis json file using AppGenesisFromFile +// to extract the consensus block gas limit before InitChain is called. +func GetBlockGasLimit(appOpts servertypes.AppOptions, logger log.Logger) uint64 { + homeDir := cast.ToString(appOpts.Get(flags.FlagHome)) + if homeDir == "" { + logger.Error("home directory not found in app options, using zero block gas limit") + return math.MaxUint64 + } + genesisPath := filepath.Join(homeDir, "config", "genesis.json") + + appGenesis, err := genutiltypes.AppGenesisFromFile(genesisPath) + if err != nil { + logger.Error("failed to load genesis using SDK AppGenesisFromFile, using zero block gas limit", "path", genesisPath, "error", err) + return 0 + } + genDoc, err := appGenesis.ToGenesisDoc() + if err != nil { + logger.Error("failed to convert AppGenesis to GenesisDoc, using zero block gas limit", "path", genesisPath, "error", err) + return 0 + } + + if genDoc.ConsensusParams == nil { + logger.Error("consensus parameters not found in genesis (nil), using zero block gas limit") + return 0 + } + + maxGas := genDoc.ConsensusParams.Block.MaxGas + if maxGas == -1 { + logger.Warn("genesis max_gas is unlimited (-1), using max uint64") + return math.MaxUint64 + } + if maxGas < -1 { + logger.Error("invalid max_gas value in genesis, using zero block gas limit") + return 0 + } + blockGasLimit := uint64(maxGas) // #nosec G115 -- maxGas >= 0 checked above + + logger.Debug( + "extracted block gas limit from genesis using SDK AppGenesisFromFile", + "genesis_path", genesisPath, + "max_gas", maxGas, + "block_gas_limit", blockGasLimit, + ) + + return blockGasLimit +} + +// GetMinGasPrices reads the min gas prices from the app options, set from app.toml +// This is currently not used, but is kept in case this is useful for the mempool, +// in addition to the min tip flag +func GetMinGasPrices(appOpts servertypes.AppOptions, logger log.Logger) sdk.DecCoins { + minGasPricesStr := cast.ToString(appOpts.Get(sdkserver.FlagMinGasPrices)) + minGasPrices, err := sdk.ParseDecCoins(minGasPricesStr) + if err != nil { + logger.With("error", err).Info("failed to parse min gas prices, using empty DecCoins") + minGasPrices = sdk.DecCoins{} + } + + return minGasPrices +} + +// GetMinTip reads the min tip from the app options, set from app.toml +// This field is also known as the minimum priority fee +func GetMinTip(appOpts servertypes.AppOptions, logger log.Logger) *uint256.Int { + minTipUint64 := cast.ToUint64(appOpts.Get(srvflags.EVMMinTip)) + minTip := uint256.NewInt(minTipUint64) + + if minTip.Cmp(uint256.NewInt(0)) >= 0 { // zero or positive + return minTip + } + + logger.Error("invalid min tip value in app.toml or flag, falling back to nil", "min_tip", minTipUint64) + return nil +} diff --git a/config/server_app_options_test.go b/config/server_app_options_test.go new file mode 100644 index 000000000..ee4ed2ff1 --- /dev/null +++ b/config/server_app_options_test.go @@ -0,0 +1,332 @@ +package config + +import ( + "encoding/json" + "fmt" + "math" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/log" + sdkmath "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/client/flags" + sdkserver "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type mockAppOptions struct { + values map[string]interface{} +} + +func newMockAppOptions() *mockAppOptions { + return &mockAppOptions{ + values: make(map[string]interface{}), + } +} + +func (m *mockAppOptions) Get(key string) interface{} { + return m.values[key] +} + +func (m *mockAppOptions) Set(key string, value interface{}) { + m.values[key] = value +} + +func TestGetBlockGasLimit(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + setupFn func() servertypes.AppOptions + expected uint64 + }{ + { + name: "empty home directory returns max uint64", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + return opts + }, + expected: math.MaxUint64, + }, + { + name: "genesis file not found returns 0", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(flags.FlagHome, "/non/existent/directory") + return opts + }, + expected: 0, + }, + { + name: "valid genesis with max_gas = -1 returns max uint64", + setupFn: func() servertypes.AppOptions { + homeDir := createGenesisWithMaxGas(t, -1) + opts := newMockAppOptions() + opts.Set(flags.FlagHome, homeDir) + return opts + }, + expected: math.MaxUint64, + }, + { + name: "valid genesis with max_gas < -1 returns 0", + setupFn: func() servertypes.AppOptions { + homeDir := createGenesisWithMaxGas(t, -5) + opts := newMockAppOptions() + opts.Set(flags.FlagHome, homeDir) + return opts + }, + expected: 0, + }, + { + name: "valid genesis with max_gas = 0 returns 0", + setupFn: func() servertypes.AppOptions { + homeDir := createGenesisWithMaxGas(t, 0) + opts := newMockAppOptions() + opts.Set(flags.FlagHome, homeDir) + return opts + }, + expected: 0, + }, + { + name: "valid genesis with max_gas = 1000000 returns 1000000", + setupFn: func() servertypes.AppOptions { + homeDir := createGenesisWithMaxGas(t, 1000000) + opts := newMockAppOptions() + opts.Set(flags.FlagHome, homeDir) + return opts + }, + expected: 1000000, + }, + { + name: "genesis without consensus params returns 0", + setupFn: func() servertypes.AppOptions { + homeDir := createGenesisWithoutConsensusParams(t) + opts := newMockAppOptions() + opts.Set(flags.FlagHome, homeDir) + return opts + }, + expected: 0, + }, + { + name: "invalid genesis JSON returns 0", + setupFn: func() servertypes.AppOptions { + homeDir := createInvalidGenesis(t) + opts := newMockAppOptions() + opts.Set(flags.FlagHome, homeDir) + return opts + }, + expected: 0, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(_ *testing.T) { + appOpts := tc.setupFn() + logger := log.NewNopLogger() + + result := GetBlockGasLimit(appOpts, logger) + require.Equal(t, tc.expected, result, "GetBlockGasLimit returned unexpected value") + }) + } +} + +func TestGetMinGasPrices(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + setupFn func() servertypes.AppOptions + expected sdk.DecCoins + }{ + { + name: "valid single gas price", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "0.025uatom") + return opts + }, + expected: sdk.DecCoins{sdk.NewDecCoinFromDec("uatom", sdkmath.LegacyMustNewDecFromStr("0.025"))}, + }, + { + name: "valid multiple gas prices", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "0.025uatom,0.001stake") + return opts + }, + expected: sdk.DecCoins{ + sdk.NewDecCoinFromDec("stake", sdkmath.LegacyMustNewDecFromStr("0.001")), + sdk.NewDecCoinFromDec("uatom", sdkmath.LegacyMustNewDecFromStr("0.025")), + }, + }, + { + name: "empty gas prices returns empty DecCoins", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "") + return opts + }, + expected: nil, + }, + { + name: "missing gas prices flag returns empty DecCoins", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + return opts + }, + expected: nil, + }, + { + name: "invalid gas price format returns empty DecCoins", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "invalid-format") + return opts + }, + expected: sdk.DecCoins{}, + }, + { + name: "malformed coin denomination returns empty DecCoins", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "0.025") + return opts + }, + expected: sdk.DecCoins{}, + }, + { + name: "zero amount gas price", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "0uatom") + return opts + }, + expected: sdk.DecCoins{}, + }, + { + name: "large decimal precision gas price", + setupFn: func() servertypes.AppOptions { + opts := newMockAppOptions() + opts.Set(sdkserver.FlagMinGasPrices, "0.000000000000000001uatom") + return opts + }, + expected: sdk.DecCoins{sdk.NewDecCoinFromDec("uatom", sdkmath.LegacyMustNewDecFromStr("0.000000000000000001"))}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(_ *testing.T) { + appOpts := tc.setupFn() + logger := log.NewNopLogger() + + result := GetMinGasPrices(appOpts, logger) + require.Equal(t, tc.expected, result, "GetMinGasPrices returned unexpected value") + }) + } +} + +func createGenesisWithMaxGas(t *testing.T, maxGas int64) string { + t.Helper() + tempDir := t.TempDir() + configDir := filepath.Join(tempDir, "config") + require.NoError(t, os.MkdirAll(configDir, 0o755)) + + genesis := map[string]interface{}{ + "app_name": "evmd", + "app_version": "test", + "chain_id": "test-chain", + "initial_height": 1, + "genesis_time": "2024-01-01T00:00:00Z", + "app_hash": nil, + "app_state": map[string]interface{}{ + "auth": map[string]interface{}{ + "params": map[string]interface{}{ + "max_memo_characters": "256", + "tx_sig_limit": "7", + "tx_size_cost_per_byte": "10", + "sig_verify_cost_ed25519": "590", + "sig_verify_cost_secp256k1": "1000", + }, + "accounts": []interface{}{}, + }, + }, + "consensus": map[string]interface{}{ + "params": map[string]interface{}{ + "block": map[string]interface{}{ + "max_bytes": "22020096", + "max_gas": fmt.Sprintf("%d", maxGas), + }, + "evidence": map[string]interface{}{ + "max_age_num_blocks": "100000", + "max_age_duration": "172800000000000", + "max_bytes": "1048576", + }, + "validator": map[string]interface{}{ + "pub_key_types": []string{"ed25519"}, + }, + "version": map[string]interface{}{ + "app": "0", + }, + }, + }, + } + + genesisBytes, err := json.MarshalIndent(genesis, "", " ") + require.NoError(t, err) + + genesisPath := filepath.Join(configDir, "genesis.json") + require.NoError(t, os.WriteFile(genesisPath, genesisBytes, 0o600)) + + return tempDir +} + +func createGenesisWithoutConsensusParams(t *testing.T) string { + t.Helper() + tempDir := t.TempDir() + configDir := filepath.Join(tempDir, "config") + require.NoError(t, os.MkdirAll(configDir, 0o755)) + + genesis := map[string]interface{}{ + "app_name": "evmd", + "app_version": "test", + "chain_id": "test-chain", + "initial_height": 1, + "genesis_time": "2024-01-01T00:00:00Z", + "app_hash": nil, + "app_state": map[string]interface{}{ + "auth": map[string]interface{}{ + "params": map[string]interface{}{}, + "accounts": []interface{}{}, + }, + }, + "consensus": map[string]interface{}{ + "params": nil, + }, + } + + genesisBytes, err := json.MarshalIndent(genesis, "", " ") + require.NoError(t, err) + + genesisPath := filepath.Join(configDir, "genesis.json") + require.NoError(t, os.WriteFile(genesisPath, genesisBytes, 0o600)) + + return tempDir +} + +func createInvalidGenesis(t *testing.T) string { + t.Helper() + tempDir := t.TempDir() + configDir := filepath.Join(tempDir, "config") + require.NoError(t, os.MkdirAll(configDir, 0o755)) + + invalidJSON := `{"invalid": json}` + genesisPath := filepath.Join(configDir, "genesis.json") + require.NoError(t, os.WriteFile(genesisPath, []byte(invalidJSON), 0o600)) + + return tempDir +} diff --git a/contracts/solidity/precompiles/testutil/contracts/StakingReverter.sol b/contracts/solidity/precompiles/testutil/contracts/StakingReverter.sol index 469267cb4..aef5d526b 100644 --- a/contracts/solidity/precompiles/testutil/contracts/StakingReverter.sol +++ b/contracts/solidity/precompiles/testutil/contracts/StakingReverter.sol @@ -49,6 +49,36 @@ contract StakingReverter { STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); } + /// @dev nestedTryCatchDelegations performs nested try/catch calls to precompile + /// where inner calls revert intentionally. Only the successful delegations + /// outside the reverting scope should persist. + /// + /// Expected successful delegations: 1 (before loop) + outerTimes (after each catch) + 1 (after loop) + function nestedTryCatchDelegations(uint outerTimes, uint innerTimes, string calldata validatorAddress) external { + // Initial successful delegate before any nested reverts + STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); + + for (uint i = 0; i < outerTimes; i++) { + // Outer call that will revert and be caught + try StakingReverter(address(this)).performDelegation(validatorAddress) { + // no-op + } catch { + // After catching the revert, perform a successful delegate + STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); + + // Inner nested loop of reverting calls + for (uint j = 0; j < innerTimes; j++) { + try StakingReverter(address(this)).performDelegation(validatorAddress) { + // no-op + } catch {} + } + } + } + + // Final successful delegate after the loops + STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); + } + function performDelegation(string calldata validatorAddress) external { STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); revert(); diff --git a/contrib/images/evmd-env/Dockerfile b/contrib/images/evmd-env/Dockerfile index 3a570ed6a..d043dca02 100644 --- a/contrib/images/evmd-env/Dockerfile +++ b/contrib/images/evmd-env/Dockerfile @@ -22,7 +22,7 @@ RUN addgroup -g 1025 nonroot RUN adduser -D nonroot -u 1025 -G nonroot # Set up the runtime environment -EXPOSE 26656 26657 1317 9090 +EXPOSE 26656 26657 1317 9090 26660 8545 8100 STOPSIGNAL SIGTERM VOLUME /evmd WORKDIR /evmd diff --git a/crypto/ethsecp256k1/ethsecp256k1.go b/crypto/ethsecp256k1/ethsecp256k1.go index ea4b4731e..11759a3c1 100644 --- a/crypto/ethsecp256k1/ethsecp256k1.go +++ b/crypto/ethsecp256k1/ethsecp256k1.go @@ -8,8 +8,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" - tmcrypto "github.com/cometbft/cometbft/crypto" - "github.com/cosmos/evm/ethereum/eip712" errorsmod "cosmossdk.io/errors" @@ -147,13 +145,13 @@ var ( // Address returns the address of the ECDSA public key. // The function will return an empty address if the public key is invalid. -func (pubKey PubKey) Address() tmcrypto.Address { +func (pubKey PubKey) Address() cryptotypes.Address { pubk, err := crypto.DecompressPubkey(pubKey.Key) if err != nil { return nil } - return tmcrypto.Address(crypto.PubkeyToAddress(*pubk).Bytes()) + return cryptotypes.Address(crypto.PubkeyToAddress(*pubk).Bytes()) } // Bytes returns the raw bytes of the ECDSA public key. diff --git a/crypto/hd/utils_test.go b/crypto/hd/utils_test.go index 1be10bae1..1c1bc03cd 100644 --- a/crypto/hd/utils_test.go +++ b/crypto/hd/utils_test.go @@ -135,8 +135,7 @@ func (w *Wallet) derivePrivateKey(path accounts.DerivationPath) (*ecdsa.PrivateK if w.fixIssue172 && key.IsAffectedByIssue172() { key, err = key.Derive(n) } else { - //lint:ignore SA1019 this is used for testing only - key, err = key.DeriveNonStandard(n) //nolint:staticcheck + key, err = key.DeriveNonStandard(n) //nolint:staticcheck // SA1019 this is used for testing only } if err != nil { return nil, err diff --git a/docs/migrations/v0.3.0_to_v0.4.0.md b/docs/migrations/v0.3.0_to_v0.4.0.md index d69cb1b3b..078f93fb7 100644 --- a/docs/migrations/v0.3.0_to_v0.4.0.md +++ b/docs/migrations/v0.3.0_to_v0.4.0.md @@ -7,6 +7,7 @@ - [ ] Bump **`cosmos/evm` to v0.4.0** and align **Cosmos SDK / IBC / CometBFT** constraints. - [ ] Rewire **keepers** and **AppModule** (imports, constructors, `RegisterServices`). - [ ] Audit and migrate **EVM & FeeMarket params** (EIP-1559 knobs, denom/decimals). +- [ ] Migrate existing **ERC20 dynamic/native precompiles** to new storage format (see Section 9). - [ ] Implement **store/params migrations** in your **UpgradeHandler**. --- @@ -135,7 +136,7 @@ Add a public method to register a listener by `txHash`: ```go // from "github.com/ethereum/go-ethereum/common")) { -func (app *MyApp) RegisterPendingTxListener(listener func(common.Hash +func (app *MyApp) RegisterPendingTxListener(listener func(common.Hash app.pendingTxListeners = append(app.pendingTxListeners, listener) } ``` @@ -174,7 +175,7 @@ func defaultOptionals() Optionals { // from addresscodec "github.com/cosmos/cosmos-sdk/codec/address"(sdk.GetConfig() // from sdk "github.com/cosmos/cosmos-sdk/types".GetBech32ValidatorAddrPrefix()), ValidatorAddrCodec: addresscodec.NewBech32Codec - // from addresscodec "github.com/cosmos/cosmos-sdk/codec/address"(sdk.GetConfig() + // from addresscodec "github.com/cosmos/cosmos-sdk/codec/address"(sdk.GetConfig() // from sdk "github.com/cosmos/cosmos-sdk/types".GetBech32ConsensusAddrPrefix()), ConsensusAddrCodec: addresscodec.NewBech32Codec } @@ -182,17 +183,17 @@ func defaultOptionals() Optionals { type Option func(*Optionals) -// from "cosmossdk.io/core/address") +// from "cosmossdk.io/core/address") // Option { return func(o *Optionals){ o.AddressCodec = c } } -func WithAddressCodec(c address.Codec +func WithAddressCodec(c address.Codec -// from "cosmossdk.io/core/address") +// from "cosmossdk.io/core/address") // Option { return func(o *Optionals){ o.ValidatorAddrCodec = c } } -func WithValidatorAddrCodec(c address.Codec +func WithValidatorAddrCodec(c address.Codec -// from "cosmossdk.io/core/address") +// from "cosmossdk.io/core/address") // Option { return func(o *Optionals){ o.ConsensusAddrCodec = c } } -func WithConsensusAddrCodec(c address.Codec +func WithConsensusAddrCodec(c address.Codec ``` ### 4.3 Update the precompile factory to accept options @@ -232,9 +233,9 @@ func WithConsensusAddrCodec(c address.Codec *(app/keepers/precompiles.go)* ```diff -- govPrecompile, err := govprecompile.NewPrecompile +- govPrecompile, err := govprecompile.NewPrecompile - // from govprecompile "github.com/cosmos/evm/precompiles/gov"(govKeeper, cdc) -+ govPrecompile, err := govprecompile.NewPrecompile ++ govPrecompile, err := govprecompile.NewPrecompile + // from govprecompile "github.com/cosmos/evm/precompiles/gov"(govKeeper, cdc, options.AddressCodec) ``` @@ -333,7 +334,41 @@ pcs := NewAvailableStaticPrecompiles(ctx, /* ... keepers ... */, opts...) --- -## 9) Verify before tagging +## 9) ERC20 Precompiles Migration + +**This is a breaking change for chains with existing ERC20 token pairs.** + +The storage mechanism for ERC20 precompiles has fundamentally changed in v0.4.0. Without proper migration, your ERC20 tokens will become inaccessible via EVM, showing zero balances and failing all operations. + +### Quick Impact Check + +Your chain needs this migration if you have: + +- IBC tokens converted to ERC20 +- Token factory tokens with ERC20 representations +- Any existing `DynamicPrecompiles` or `NativePrecompiles` in storage + +### Migration + +For full details see: [ERC20 Precompiles Migration Guide](./v0.4.0_erc20_precompiles_migration.md) + +*Thanks to Mantra team for their work on this: [MANTRA-Chain Implementation](https://github.com/MANTRA-Chain/mantrachain/pull/409)* + +### Quick Verification + +Post-upgrade, verify your migration succeeded: + +```bash +# Check ERC20 balance (should NOT be 0 if tokens existed before) +cast call $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS --rpc-url http://localhost:8545 + +# Verify precompiles in state +evmd export | jq '.app_state.erc20.dynamic_precompiles' +``` + +--- + +## 10) Verify before tagging - [ ] `go.mod` has **no `replace`** lines for `github.com/cosmos/evm`. - [ ] Node boots with expected **RPC namespaces**. diff --git a/docs/migrations/v0.4.0_erc20_precompiles_migration.md b/docs/migrations/v0.4.0_erc20_precompiles_migration.md new file mode 100644 index 000000000..b200215a3 --- /dev/null +++ b/docs/migrations/v0.4.0_erc20_precompiles_migration.md @@ -0,0 +1,353 @@ +# ERC20 Precompiles Migration + +## Breaking Change in v0.4.0 + +The storage mechanism for ERC20 dynamic and native precompiles has fundamentally changed in Cosmos EVM v0.4.0. This migration is mandatory for chains with existing ERC20 token pairs. + +### Impact Assessment + +**Affected Chains:** + +- Chains with IBC tokens converted to ERC20 +- Chains using token factory with ERC20 representations +- Any chain with existing `DynamicPrecompiles` or `NativePrecompiles` in parameter storage + +**Known Issues if Not Migrated:** + +- ERC20 balances will show as 0 when queried via EVM +- `totalSupply()` calls return 0 +- Token transfers via ERC20 interface fail +- Native Cosmos balances remain intact but inaccessible via EVM + +## Migration Overview + +### Storage Changes + +**Before (v0.3.x):** + +- Precompiles stored as concatenated hex strings in parameter storage +- Keys: `"DynamicPrecompiles"` and `"NativePrecompiles"` +- Format: Multiple addresses concatenated as 42-character hex strings + +**After (v0.4.0):** + +- Dedicated prefix stores for each precompile type +- Keys: `types.KeyPrefixDynamicPrecompiles` and `types.KeyPrefixNativePrecompiles` +- Individual storage entries per address + +## Implementation Guide + +### Quick Start + +The migration can be added to your existing upgrade handler: + +```go +// In your upgrade handler +store := ctx.KVStore(storeKeys[erc20types.StoreKey]) +const addressLength = 42 // "0x" + 40 hex characters + +// Migrate dynamic precompiles (IBC tokens, token factory) +if oldData := store.Get([]byte("DynamicPrecompiles")); len(oldData) > 0 { + for i := 0; i < len(oldData); i += addressLength { + address := common.HexToAddress(string(oldData[i : i+addressLength])) + erc20Keeper.SetDynamicPrecompile(ctx, address) + } + store.Delete([]byte("DynamicPrecompiles")) +} + +// Migrate native precompiles +if oldData := store.Get([]byte("NativePrecompiles")); len(oldData) > 0 { + for i := 0; i < len(oldData); i += addressLength { + address := common.HexToAddress(string(oldData[i : i+addressLength])) + erc20Keeper.SetNativePrecompile(ctx, address) + } + store.Delete([]byte("NativePrecompiles")) +} +``` + +
+📄 Complete Example Implementation (click to expand) + +### Create Upgrade Handler + +Create a new upgrade handler: + +```go +// app/upgrades/v040/handler.go +package v040 + +import ( + "context" + + storetypes "cosmossdk.io/store/types" + upgradetypes "cosmossdk.io/x/upgrade/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + erc20keeper "github.com/cosmos/evm/x/erc20/keeper" + erc20types "github.com/cosmos/evm/x/erc20/types" + "github.com/ethereum/go-ethereum/common" +) + +const UpgradeName = "v0.4.0" + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + keepers *UpgradeKeepers, + storeKeys map[string]*storetypes.KVStoreKey, +) upgradetypes.UpgradeHandler { + return func(c context.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + ctx := sdk.UnwrapSDKContext(c) + ctx.Logger().Info("Starting v0.4.0 upgrade...") + + // Run standard module migrations + vm, err := mm.RunMigrations(ctx, configurator, vm) + if err != nil { + return vm, err + } + + // Migrate ERC20 precompiles + if err := migrateERC20Precompiles(ctx, storeKeys[erc20types.StoreKey], keepers.Erc20Keeper); err != nil { + return vm, err + } + + ctx.Logger().Info("v0.4.0 upgrade complete") + return vm, nil + } +} +``` + +### Implement Migration + +```go +// app/upgrades/v040/erc20_migration.go +package v040 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + storetypes "cosmossdk.io/store/types" + erc20keeper "github.com/cosmos/evm/x/erc20/keeper" + "github.com/ethereum/go-ethereum/common" +) + +func migrateERC20Precompiles( + ctx sdk.Context, + storeKey *storetypes.KVStoreKey, + erc20Keeper erc20keeper.Keeper, +) error { + store := ctx.KVStore(storeKey) + const addressLength = 42 // "0x" + 40 hex characters + + migrations := []struct { + oldKey string + setter func(sdk.Context, common.Address) + description string + }{ + { + oldKey: "DynamicPrecompiles", + setter: erc20Keeper.SetDynamicPrecompile, + description: "dynamic precompiles (token factory, IBC tokens)", + }, + { + oldKey: "NativePrecompiles", + setter: erc20Keeper.SetNativePrecompile, + description: "native precompiles", + }, + } + + for _, migration := range migrations { + oldData := store.Get([]byte(migration.oldKey)) + if len(oldData) == 0 { + ctx.Logger().Info("No legacy data found", "type", migration.description) + continue + } + + addressCount := len(oldData) / addressLength + ctx.Logger().Info("Migrating precompiles", + "type", migration.description, + "count", addressCount, + "data_length", len(oldData), + ) + + migratedCount := 0 + for i := 0; i < len(oldData); i += addressLength { + if i+addressLength > len(oldData) { + ctx.Logger().Error("Invalid data length", + "type", migration.description, + "position", i, + "remaining", len(oldData)-i, + ) + break + } + + addressStr := string(oldData[i : i+addressLength]) + address := common.HexToAddress(addressStr) + + // Validate address + if address == (common.Address{}) { + ctx.Logger().Warn("Skipping zero address", + "type", migration.description, + "raw", addressStr, + ) + continue + } + + // Migrate to new storage + migration.setter(ctx, address) + migratedCount++ + + ctx.Logger().Debug("Migrated precompile", + "type", migration.description, + "address", address.String(), + "index", migratedCount, + ) + } + + // Clean up old storage + store.Delete([]byte(migration.oldKey)) + ctx.Logger().Info("Migration complete", + "type", migration.description, + "migrated", migratedCount, + "expected", addressCount, + ) + } + + return nil +} +``` + +
+ +### Define Upgrade Keepers + +```go +// app/upgrades/v040/types.go +package v040 + +import ( + erc20keeper "github.com/cosmos/evm/x/erc20/keeper" + // ... other keeper imports +) + +type UpgradeKeepers struct { + Erc20Keeper erc20keeper.Keeper + // ... other keepers needed for upgrade +} +``` + +### Register Upgrade Handler + +```go +// app/app.go +import ( + v040 "github.com/yourchain/app/upgrades/v040" +) + +func (app *App) RegisterUpgradeHandlers() { + app.UpgradeKeeper.SetUpgradeHandler( + v040.UpgradeName, + v040.CreateUpgradeHandler( + app.ModuleManager, + app.configurator, + &v040.UpgradeKeepers{ + Erc20Keeper: app.Erc20Keeper, + }, + app.keys, + ), + ) +} +``` + +## Testing + +### Pre-Upgrade + +```bash +# 1. Query existing token pairs +mantrachaind query erc20 token-pairs --output json | jq + +# 2. Check ERC20 balances for a known address +cast call $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS --rpc-url http://localhost:8545 + +# 3. Export state for backup +mantrachaind export > pre-upgrade-state.json +``` + +### Post-Upgrade + +```bash +# 1. Verify precompiles are accessible +cast call $TOKEN_ADDRESS "totalSupply()" --rpc-url http://localhost:8545 + +# 2. Check balance restoration +cast call $TOKEN_ADDRESS "balanceOf(address)" $USER_ADDRESS --rpc-url http://localhost:8545 + +# 3. Test token transfer +cast send $TOKEN_ADDRESS "transfer(address,uint256)" $RECIPIENT 1000 \ + --private-key $PRIVATE_KEY --rpc-url http://localhost:8545 + +# 4. Verify in exported state +mantrachaind export | jq '.app_state.erc20.dynamic_precompiles' +``` + +## Integration Test Example + +```go +// tests/upgrade_test.go +package tests + +import ( + "testing" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" +) + +func TestERC20PrecompileMigration(t *testing.T) { + // Setup test environment + app, ctx := setupTestApp(t) + + // Create legacy storage entries + store := ctx.KVStore(app.keys[erc20types.StoreKey]) + + // Add test addresses in old format + dynamicAddresses := []string{ + "0x6eC942095eCD4948d9C094337ABd59Dc3c521005", + "0x1234567890123456789012345678901234567890", + } + dynamicData := "" + for _, addr := range dynamicAddresses { + dynamicData += addr + } + store.Set([]byte("DynamicPrecompiles"), []byte(dynamicData)) + + // Run migration + err := migrateERC20Precompiles(ctx, app.keys[erc20types.StoreKey], app.Erc20Keeper) + require.NoError(t, err) + + // Verify migration + migratedAddresses := app.Erc20Keeper.GetDynamicPrecompiles(ctx) + require.Len(t, migratedAddresses, len(dynamicAddresses)) + + for i, addr := range dynamicAddresses { + require.Equal(t, addr, migratedAddresses[i]) + } + + // Verify old storage is cleaned + oldData := store.Get([]byte("DynamicPrecompiles")) + require.Nil(t, oldData) +} +``` + +## References + +- **GitHub Issue:** [#424](https://github.com/cosmos/evm/issues/424) +- **Reference Implementation:** [MANTRA-Chain PR #409](https://github.com/MANTRA-Chain/mantrachain/pull/409) +- **Test Suite:** [MANTRA-Chain E2E Tests](https://github.com/MANTRA-Chain/mantrachain-e2e/pull/41) + +## Verification Checklist + +- [ ] Test migration on testnet first +- [ ] Document all existing token pairs +- [ ] Verify ERC20 balances post-upgrade +- [ ] Test token transfers work +- [ ] Confirm IBC token conversions function diff --git a/docs/migrations/v0.4.0_to_v0.5.0_UNRELEASED.md b/docs/migrations/v0.4.0_to_v0.5.0_UNRELEASED.md new file mode 100644 index 000000000..10fc61266 --- /dev/null +++ b/docs/migrations/v0.4.0_to_v0.5.0_UNRELEASED.md @@ -0,0 +1,127 @@ +# Cosmos EVM v0.4.0 → v0.5.0 Migration (UNRELEASED) + +## 0) Prep + +- Create a branch: `git switch -c upgrade/evm-v0.5`. +- Ensure a clean build + tests green pre-upgrade. +- Snapshot your current params/genesis for comparison later. + +--- + +## 1) Dependency bumps (go.mod) + +- Bump `github.com/cosmos/evm` to v0.5.0 and run: + +```bash +go mod tidy +``` + +--- + +## 2) App wiring in `app.go` + +### Mempool + +#### Minimal setups: nothing to change + +If you use the default mempool wiring (no custom pools), your existing code continues to work. If `BlockGasLimit` is 0, it defaults to `100_000_000`. If `BroadCastTxFn` is not set, it's also set to a default value. + +```go +mempoolConfig := &evmmempool.EVMMempoolConfig{ + AnteHandler: app.GetAnteHandler(), + BlockGasLimit: 100_000_000, // or 0 to use default +} +evmMempool := evmmempool.NewExperimentalEVMMempool( + app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, app.clientCtx, mempoolConfig +) +``` + +#### Advanced setups: migrate your customizations + +PR [#496](https://github.com/cosmos/evm/pull/496) replaced pre-built pools with configs in `EVMMempoolConfig`: + +- Replace pools with configs + - Removed: `TxPool *txpool.TxPool`, `CosmosPool sdkmempool.ExtMempool` + - Added: `LegacyPoolConfig *legacypool.Config`, `CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int]` + +If you built custom pools yourself: + +```diff + mempoolConfig := &evmmempool.EVMMempoolConfig{ +- TxPool: customTxPool, +- CosmosPool: customCosmosPool, ++ LegacyPoolConfig: &legacyCfg, // or nil for defaults ++ CosmosPoolConfig: &cosmosCfg, // or nil for defaults + AnteHandler: app.GetAnteHandler(), + BroadCastTxFn: myBroadcast, // optional + } +``` + +Example custom configs: + +```go +// EVM legacy txpool tuning +legacyCfg := legacypool.DefaultConfig +legacyCfg.PriceLimit = 2 +mempoolConfig.LegacyPoolConfig = &legacyCfg + +// Cosmos priority mempool tuning +cosmosCfg := sdkmempool.PriorityNonceMempoolConfig[math.Int]{} +cosmosCfg.TxPriority = sdkmempool.TxPriority[math.Int]{ + GetTxPriority: func(goCtx context.Context, tx sdk.Tx) math.Int { + // Custom priority function + }, + Compare: func(a, b math.Int) int { return a.BigInt().Cmp(b.BigInt()) }, + MinValue: math.ZeroInt(), +} +mempoolConfig.CosmosPoolConfig = &cosmosCfg + +// Custom EVM broadcast (optional) +mempoolConfig.BroadCastTxFn = func(txs []*ethtypes.Transaction) error { return nil } +``` + +### Default Precompiles + +Default precompiles have been moved to `/evm/precompiles/types/defaults.go` and the function name was +changed to `DefaultStaticPrecompiles`. The function signature has also changed, and now takes pointers +as inputs for the `Erc20Keeper` and `TransferKeeper`. Finally, the `WithStaticPrecompiles` builder +function can now happen *alongside the keeper instantiation*, and not after. The new wiring is shown below: + +```go + app.EVMKeeper = evmkeeper.NewKeeper( + appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys, + authtypes.NewModuleAddress(govtypes.ModuleName), + app.AccountKeeper, + app.PreciseBankKeeper, + app.StakingKeeper, + app.FeeMarketKeeper, + &app.ConsensusParamsKeeper, + &app.Erc20Keeper, + tracer, + ).WithStaticPrecompiles( + precompiletypes.DefaultStaticPrecompiles( + *app.StakingKeeper, + app.DistrKeeper, + app.BankKeeper, + &app.Erc20Keeper, // UPDATED + &app.TransferKeeper, // UPDATED + app.IBCKeeper.ChannelKeeper, + app.GovKeeper, + app.SlashingKeeper, + appCodec, + ), + ) +``` + +--- + +## 3) Build & quick tests + +```bash +go build ./... +``` + +Smoke test on a single node: +- Send a few EVM txs; confirm promotion/broadcast (or your `BroadCastTxFn`). +- Send Cosmos txs; confirm ordering reflects your `CosmosPoolConfig` (if customized). + diff --git a/encoding/config.go b/encoding/config.go index 309645064..aa0c25629 100644 --- a/encoding/config.go +++ b/encoding/config.go @@ -11,17 +11,26 @@ import ( "cosmossdk.io/x/tx/signing" + "github.com/cosmos/cosmos-sdk/client" amino "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" - sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" "github.com/cosmos/cosmos-sdk/x/auth/tx" ) -// MakeConfig creates a new EncodingConfig and returns it -func MakeConfig(evmChainID uint64) sdktestutil.TestEncodingConfig { +// Config specifies the concrete encoding types to use for a given app. +// This is provided for compatibility between protobuf and amino implementations. +type Config struct { + InterfaceRegistry types.InterfaceRegistry + Codec amino.Codec + TxConfig client.TxConfig + Amino *amino.LegacyAmino +} + +// MakeConfig creates a new Config and returns it +func MakeConfig(evmChainID uint64) Config { cdc := amino.NewLegacyAmino() signingOptions := signing.Options{ AddressCodec: address.Bech32Codec{ @@ -49,7 +58,7 @@ func MakeConfig(evmChainID uint64) sdktestutil.TestEncodingConfig { legacytx.RegressionTestingAminoCodec = cdc eip712.SetEncodingConfig(cdc, interfaceRegistry, evmChainID) - return sdktestutil.TestEncodingConfig{ + return Config{ InterfaceRegistry: interfaceRegistry, Codec: codec, TxConfig: tx.NewTxConfig(codec, tx.DefaultSignModes), diff --git a/evmd/ante/evm_handler.go b/evmd/ante/evm_handler.go index ce84be9bb..bd87f9f3e 100644 --- a/evmd/ante/evm_handler.go +++ b/evmd/ante/evm_handler.go @@ -18,6 +18,6 @@ func newMonoEVMAnteHandler(options ante.HandlerOptions) sdk.AnteHandler { ), ante.NewTxListenerDecorator(options.PendingTxListener), } - + return sdk.ChainAnteDecorators(decorators...) } diff --git a/evmd/app.go b/evmd/app.go index b255192b3..e47152852 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -2,8 +2,11 @@ package evmd import ( "encoding/json" + "errors" "fmt" + precompiletypes "github.com/cosmos/evm/precompiles/types" "io" + "os" "github.com/spf13/cast" @@ -49,8 +52,6 @@ import ( ibctransfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer" ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v10/modules/core" - ibcclienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" - ibcconnectiontypes "github.com/cosmos/ibc-go/v10/modules/core/03-connection/types" porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported" @@ -83,7 +84,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/runtime" runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services" - "github.com/cosmos/cosmos-sdk/server" + sdkserver "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" @@ -119,15 +120,11 @@ import ( "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" - govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/mint" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" - paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" @@ -181,7 +178,6 @@ type EVMD struct { DistrKeeper distrkeeper.Keeper GovKeeper govkeeper.Keeper UpgradeKeeper *upgradekeeper.Keeper - ParamsKeeper paramskeeper.Keeper //nolint:staticcheck AuthzKeeper authzkeeper.Keeper EvidenceKeeper evidencekeeper.Keeper FeeGrantKeeper feegrantkeeper.Keeper @@ -275,7 +271,7 @@ func NewExampleApp( keys := storetypes.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.StoreKey, + govtypes.StoreKey, consensusparamtypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, authzkeeper.StoreKey, // ibc keys ibcexported.StoreKey, ibctransfertypes.StoreKey, @@ -283,7 +279,7 @@ func NewExampleApp( evmtypes.StoreKey, feemarkettypes.StoreKey, erc20types.StoreKey, precisebanktypes.StoreKey, ) - tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey) + tkeys := storetypes.NewTransientStoreKeys(evmtypes.TransientKey, feemarkettypes.TransientKey) // load state streaming if enabled if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil { @@ -306,7 +302,7 @@ func NewExampleApp( tkeys: tkeys, } - app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) + // removed x/params: no ParamsKeeper initialization // get authority address authAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String() @@ -408,7 +404,7 @@ func NewExampleApp( // get skipUpgradeHeights from the app options skipUpgradeHeights := map[int64]bool{} - for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) { + for _, h := range cast.ToIntSlice(appOpts.Get(sdkserver.FlagUnsafeSkipUpgrades)) { skipUpgradeHeights[int64(h)] = true } homePath := cast.ToString(appOpts.Get(flags.FlagHome)) @@ -426,7 +422,7 @@ func NewExampleApp( app.IBCKeeper = ibckeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[ibcexported.StoreKey]), - app.GetSubspace(ibcexported.ModuleName), + nil, app.UpgradeKeeper, authAddr, ) @@ -491,6 +487,18 @@ func NewExampleApp( &app.ConsensusParamsKeeper, &app.Erc20Keeper, tracer, + ).WithStaticPrecompiles( + precompiletypes.DefaultStaticPrecompiles( + *app.StakingKeeper, + app.DistrKeeper, + app.BankKeeper, + &app.Erc20Keeper, + &app.TransferKeeper, + app.IBCKeeper.ChannelKeeper, + app.GovKeeper, + app.SlashingKeeper, + appCodec, + ), ) app.Erc20Keeper = erc20keeper.NewKeeper( @@ -508,7 +516,6 @@ func NewExampleApp( app.TransferKeeper = transferkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]), - app.GetSubspace(ibctransfertypes.ModuleName), app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, app.MsgServiceRouter(), @@ -567,23 +574,6 @@ func NewExampleApp( // Override the ICS20 app module transferModule := transfer.NewAppModule(app.TransferKeeper) - // NOTE: we are adding all available Cosmos EVM EVM extensions. - // Not all of them need to be enabled, which can be configured on a per-chain basis. - app.EVMKeeper.WithStaticPrecompiles( - NewAvailableStaticPrecompiles( - *app.StakingKeeper, - app.DistrKeeper, - app.PreciseBankKeeper, - app.Erc20Keeper, - app.TransferKeeper, - app.IBCKeeper.ChannelKeeper, - app.EVMKeeper, - app.GovKeeper, - app.SlashingKeeper, - app.AppCodec(), - ), - ) - /**** Module Options ****/ // NOTE: Any module instantiated in the module manager that is later modified @@ -593,14 +583,14 @@ func NewExampleApp( app.AccountKeeper, app.StakingKeeper, app, app.txConfig, ), - auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)), + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), - gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)), - mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)), - slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName), app.interfaceRegistry), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)), + gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil), + mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil), + slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil), upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()), evidence.NewAppModule(app.EvidenceKeeper), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), @@ -624,13 +614,9 @@ func NewExampleApp( app.BasicModuleManager = module.NewBasicManagerFromManager( app.ModuleManager, map[string]module.AppModuleBasic{ - genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), - stakingtypes.ModuleName: staking.AppModuleBasic{}, - govtypes.ModuleName: gov.NewAppModuleBasic( - []govclient.ProposalHandler{ - paramsclient.ProposalHandler, - }, - ), + genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + stakingtypes.ModuleName: staking.AppModuleBasic{}, + govtypes.ModuleName: gov.NewAppModuleBasic(nil), ibctransfertypes.ModuleName: transfer.AppModuleBasic{AppModuleBasic: &ibctransfer.AppModuleBasic{}}, }, ) @@ -664,7 +650,7 @@ func NewExampleApp( evidencetypes.ModuleName, stakingtypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, govtypes.ModuleName, genutiltypes.ModuleName, authz.ModuleName, feegrant.ModuleName, - paramstypes.ModuleName, consensusparamtypes.ModuleName, + consensusparamtypes.ModuleName, precisebanktypes.ModuleName, vestingtypes.ModuleName, ) @@ -683,7 +669,7 @@ func NewExampleApp( distrtypes.ModuleName, slashingtypes.ModuleName, minttypes.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, - feegrant.ModuleName, paramstypes.ModuleName, upgradetypes.ModuleName, consensusparamtypes.ModuleName, + feegrant.ModuleName, upgradetypes.ModuleName, consensusparamtypes.ModuleName, precisebanktypes.ModuleName, vestingtypes.ModuleName, ) @@ -741,7 +727,7 @@ func NewExampleApp( // 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.GetSubspace(authtypes.ModuleName)), + authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil), } app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules) @@ -764,19 +750,20 @@ func NewExampleApp( // set the EVM priority nonce mempool // If you wish to use the noop mempool, remove this codeblock if evmtypes.GetChainConfig() != nil { - // TODO: Get the actual block gas limit from consensus parameters + // Get the block gas limit from genesis file + blockGasLimit := evmconfig.GetBlockGasLimit(appOpts, logger) + // Get GetMinTip from app.toml or cli flag configuration + mipTip := evmconfig.GetMinTip(appOpts, logger) + mempoolConfig := &evmmempool.EVMMempoolConfig{ AnteHandler: app.GetAnteHandler(), - BlockGasLimit: 100_000_000, + BlockGasLimit: blockGasLimit, + MinTip: mipTip, } evmMempool := evmmempool.NewExperimentalEVMMempool(app.CreateQueryContext, logger, app.EVMKeeper, app.FeeMarketKeeper, app.txConfig, app.clientCtx, mempoolConfig) app.EVMMempool = evmMempool - // Set the global mempool for RPC access - if err := evmmempool.SetGlobalEVMMempool(evmMempool); err != nil { - panic(err) - } app.SetMempool(evmMempool) checkTxHandler := evmmempool.NewCheckTxHandler(evmMempool) app.SetCheckTxHandler(checkTxHandler) @@ -983,14 +970,6 @@ func (app *EVMD) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { return app.memKeys[storeKey] } -// GetSubspace returns a param subspace for a given module name. -// -// NOTE: This is solely to be used for testing purposes. -func (app *EVMD) GetSubspace(moduleName string) paramstypes.Subspace { - subspace, _ := app.ParamsKeeper.GetSubspace(moduleName) - return subspace -} - // SimulationManager implements the SimulationApp interface func (app *EVMD) SimulationManager() *module.SimulationManager { return app.sm @@ -1013,7 +992,7 @@ func (app *EVMD) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfi app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // register swagger API from root so that other applications can override easily - if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { + if err := sdkserver.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil { panic(err) } } @@ -1149,6 +1128,25 @@ func (app *EVMD) SetClientCtx(clientCtx client.Context) { app.clientCtx = clientCtx } +// Close unsubscribes from the CometBFT event bus (if set) and closes the mempool and underlying BaseApp. +func (app *EVMD) Close() error { + var err error + if m, ok := app.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok { + app.Logger().Info("Shutting down mempool") + err = m.Close() + } + + msg := "Application gracefully shutdown" + err = errors.Join(err, app.BaseApp.Close()) + if err == nil { + app.Logger().Info(msg) + } else { + app.Logger().Error(msg, "error", err) + } + + return err +} + // AutoCliOpts returns the autocli options for the app. func (app *EVMD) AutoCliOpts() autocli.AppOptions { modules := make(map[string]appmodule.AppModule, 0) @@ -1169,25 +1167,3 @@ func (app *EVMD) AutoCliOpts() autocli.AppOptions { ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), } } - -// initParamsKeeper init params keeper and its subspaces -func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey) paramskeeper.Keeper { //nolint:staticcheck - paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey) //nolint:staticcheck - - paramsKeeper.Subspace(authtypes.ModuleName) - paramsKeeper.Subspace(banktypes.ModuleName) - paramsKeeper.Subspace(stakingtypes.ModuleName) - paramsKeeper.Subspace(minttypes.ModuleName) - paramsKeeper.Subspace(distrtypes.ModuleName) - paramsKeeper.Subspace(slashingtypes.ModuleName) - paramsKeeper.Subspace(govtypes.ModuleName) - - // ibc modules - keyTable := ibcclienttypes.ParamKeyTable() - keyTable.RegisterParamSet(&ibcconnectiontypes.Params{}) - paramsKeeper.Subspace(ibcexported.ModuleName).WithKeyTable(keyTable) - paramsKeeper.Subspace(ibctransfertypes.ModuleName).WithKeyTable(ibctransfertypes.ParamKeyTable()) - // TODO: do we need a keytable? copied from Evmos repo - - return paramsKeeper -} diff --git a/evmd/cmd/evmd/cmd/testnet.go b/evmd/cmd/evmd/cmd/testnet.go index c90690cb0..a98dfc052 100644 --- a/evmd/cmd/evmd/cmd/testnet.go +++ b/evmd/cmd/evmd/cmd/testnet.go @@ -288,9 +288,10 @@ func initTestnetFiles( sdkGRPCPort = 9090 // evmGRPC = 9900 // TODO: maybe need this? idk. - evmJSONRPC = 8545 - evmJSONRPCWS = 8546 - evmJSONRPCMetrics = 6065 + evmJSONRPC = 8545 + evmJSONRPCWS = 8546 + evmJSONRPCMetrics = 6065 + evmGethMetricsPort = 8100 ) p2pPortStart := 26656 @@ -317,6 +318,7 @@ func initTestnetFiles( evmCfg.JSONRPC.Address = fmt.Sprintf("127.0.0.1:%d", evmJSONRPC+evmPortOffset) evmCfg.JSONRPC.MetricsAddress = fmt.Sprintf("127.0.0.1:%d", evmJSONRPCMetrics+evmPortOffset) evmCfg.JSONRPC.WsAddress = fmt.Sprintf("127.0.0.1:%d", evmJSONRPCWS+evmPortOffset) + evmCfg.EVM.GethMetricsAddress = fmt.Sprintf("127.0.0.1:%d", evmGethMetricsPort+evmPortOffset) } else { evmCfg.JSONRPC.WsAddress = fmt.Sprintf("0.0.0.0:%d", evmJSONRPCWS) evmCfg.JSONRPC.Address = fmt.Sprintf("0.0.0.0:%d", evmJSONRPC) diff --git a/evmd/cmd/evmd/config/evmd_config.go b/evmd/cmd/evmd/config/evmd_config.go index 7ff2243cb..2f9303699 100644 --- a/evmd/cmd/evmd/config/evmd_config.go +++ b/evmd/cmd/evmd/config/evmd_config.go @@ -58,7 +58,6 @@ var maccPerms = map[string][]string{ func BlockedAddresses() map[string]bool { blockedAddrs := make(map[string]bool) - maps.Clone(maccPerms) maccPerms := GetMaccPerms() accs := make([]string, 0, len(maccPerms)) for acc := range maccPerms { diff --git a/evmd/go.mod b/evmd/go.mod index 001695461..321acf200 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -19,7 +19,7 @@ require ( github.com/cosmos/cosmos-sdk v0.53.4 github.com/cosmos/evm v0.2.0 github.com/cosmos/gogoproto v1.7.0 - github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b + github.com/cosmos/ibc-go/v10 v10.3.0 github.com/ethereum/go-ethereum v1.15.11 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.38.0 @@ -74,6 +74,7 @@ require ( github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/errors v1.12.0 // indirect + github.com/cockroachdb/fifo v0.0.0-20240616162244-4768e80dfb9a // indirect github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 // indirect github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.6 // indirect @@ -85,7 +86,6 @@ require ( github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.2.2 // indirect - github.com/cosmos/ibc-go/modules/capability v1.0.1 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect @@ -162,7 +162,6 @@ require ( github.com/holiman/uint256 v1.3.2 // indirect github.com/huandu/skiplist v1.2.1 // indirect github.com/huin/goupnp v1.3.0 // indirect - github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -275,8 +274,6 @@ require ( replace ( // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - // Pin this pebble version to avoid breaking compilation of geth - github.com/cockroachdb/pebble => github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 github.com/cosmos/evm => ../ github.com/cosmos/evm/evmd => ./evmd // use Cosmos geth fork diff --git a/evmd/go.sum b/evmd/go.sum index 1651dca61..4bd49aa31 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -826,10 +826,12 @@ github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaY github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/errors v1.12.0 h1:d7oCs6vuIMUQRVbi6jWWWEJZahLCfJpnJSVobd1/sUo= github.com/cockroachdb/errors v1.12.0/go.mod h1:SvzfYNNBshAVbZ8wzNc/UPK3w1vf0dKDUP41ucAIf7g= +github.com/cockroachdb/fifo v0.0.0-20240616162244-4768e80dfb9a h1:f52TdbU4D5nozMAhO9TvTJ2ZMCXtN4VIAmfrrZ0JXQ4= +github.com/cockroachdb/fifo v0.0.0-20240616162244-4768e80dfb9a/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506 h1:ASDL+UJcILMqgNeV5jiqR4j+sTuvQNHdf2chuKj1M5k= github.com/cockroachdb/logtags v0.0.0-20241215232642-bb51bb14a506/go.mod h1:Mw7HqKr2kdtu6aYGn3tPmAftiP3QPX63LdK/zcariIo= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/pebble v1.1.5 h1:5AAWCBWbat0uE0blr8qzufZP5tBjkRyy/jWe1QWLnvw= +github.com/cockroachdb/pebble v1.1.5/go.mod h1:17wO9el1YEigxkP/YtV8NtCivQDgoCyBg5c4VR/eOWo= github.com/cockroachdb/redact v1.1.6 h1:zXJBwDZ84xJNlHl1rMyCojqyIxv+7YUpQiJLQ7n4314= github.com/cockroachdb/redact v1.1.6/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= @@ -866,10 +868,8 @@ github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fr github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/iavl v1.2.2 h1:qHhKW3I70w+04g5KdsdVSHRbFLgt3yY3qTMd4Xa4rC8= github.com/cosmos/iavl v1.2.2/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= -github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= -github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= -github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b h1:+TaXFL0WksE7yBs6DqHrRIDtkKZfu3+Lirbs6rK4N20= -github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b/go.mod h1:AQ76dzfU5i3UB5UiktWe6q7hpbPyBXuZcnjMQekBkHs= +github.com/cosmos/ibc-go/v10 v10.3.0 h1:w5DkHih8qn15deAeFoTk778WJU+xC1krJ5kDnicfUBc= +github.com/cosmos/ibc-go/v10 v10.3.0/go.mod h1:CthaR7n4d23PJJ7wZHegmNgbVcLXCQql7EwHrAXnMtw= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= @@ -1298,8 +1298,6 @@ github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXM github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= -github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= diff --git a/evmd/tests/ibc/ics20_precompile_transfer_test.go b/evmd/tests/ibc/ics20_precompile_transfer_test.go index d06e34ff3..cae1ee3cb 100644 --- a/evmd/tests/ibc/ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/ics20_precompile_transfer_test.go @@ -51,7 +51,6 @@ func (suite *ICS20TransferTestSuite) SetupTest() { *evmAppA.StakingKeeper, evmAppA.TransferKeeper, evmAppA.IBCKeeper.ChannelKeeper, - evmAppA.EVMKeeper, ) evmAppB := suite.chainB.App.(*evmd.EVMD) suite.chainBPrecompile, _ = ics20.NewPrecompile( @@ -59,7 +58,6 @@ func (suite *ICS20TransferTestSuite) SetupTest() { *evmAppB.StakingKeeper, evmAppB.TransferKeeper, evmAppB.IBCKeeper.ChannelKeeper, - evmAppB.EVMKeeper, ) } diff --git a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go index b71d490b9..740f8c3d8 100644 --- a/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go +++ b/evmd/tests/ibc/v2_ics20_precompile_transfer_test.go @@ -52,7 +52,6 @@ func (suite *ICS20TransferV2TestSuite) SetupTest() { *evmAppA.StakingKeeper, evmAppA.TransferKeeper, evmAppA.IBCKeeper.ChannelKeeper, - evmAppA.EVMKeeper, ) evmAppB := suite.chainB.App.(*evmd.EVMD) suite.chainBPrecompile, _ = ics20.NewPrecompile( @@ -60,7 +59,6 @@ func (suite *ICS20TransferV2TestSuite) SetupTest() { *evmAppB.StakingKeeper, evmAppB.TransferKeeper, evmAppB.IBCKeeper.ChannelKeeper, - evmAppB.EVMKeeper, ) } diff --git a/evmd/tests/integration/mempool/mempool_test.go b/evmd/tests/integration/mempool/mempool_test.go index 3714c9afc..8c3830dba 100644 --- a/evmd/tests/integration/mempool/mempool_test.go +++ b/evmd/tests/integration/mempool/mempool_test.go @@ -1,9 +1,10 @@ package mempool import ( - "github.com/cosmos/evm/evmd/tests/integration" "testing" + "github.com/cosmos/evm/evmd/tests/integration" + "github.com/stretchr/testify/suite" "github.com/cosmos/evm/tests/integration/mempool" diff --git a/evmd/tests/integration/precompiles/erc20factory/precompile_erc20_factory_test.go b/evmd/tests/integration/precompiles/erc20factory/precompile_erc20_factory_test.go new file mode 100644 index 000000000..26eb5d1c2 --- /dev/null +++ b/evmd/tests/integration/precompiles/erc20factory/precompile_erc20_factory_test.go @@ -0,0 +1,14 @@ +package erc20factory + +import ( + "testing" + + "github.com/cosmos/evm/evmd/tests/integration" + factory "github.com/cosmos/evm/tests/integration/precompiles/erc20factory" + "github.com/stretchr/testify/suite" +) + +func TestErc20FactoryPrecompileTestSuite(t *testing.T) { + s := factory.NewPrecompileTestSuite(integration.CreateEvmd) + suite.Run(t, s) +} diff --git a/evmd/tests/integration/testutil_test.go b/evmd/tests/integration/testutil_test.go deleted file mode 100644 index a8e33354c..000000000 --- a/evmd/tests/integration/testutil_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package integration - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/evm/tests/integration/testutil" -) - -func TestTestUtilTestSuite(t *testing.T) { - s := testutil.NewTestSuite(CreateEvmd) - suite.Run(t, s) -} diff --git a/evmd/tests/integration/x_vm_test.go b/evmd/tests/integration/x_vm_test.go index 37c439a17..c1aec6e9f 100644 --- a/evmd/tests/integration/x_vm_test.go +++ b/evmd/tests/integration/x_vm_test.go @@ -1,13 +1,87 @@ package integration import ( + "encoding/json" "testing" - "github.com/stretchr/testify/suite" - + "github.com/cosmos/evm/server/config" "github.com/cosmos/evm/tests/integration/x/vm" + "github.com/cosmos/evm/testutil/integration/evm/network" + "github.com/cosmos/evm/testutil/keyring" + feemarkettypes "github.com/cosmos/evm/x/feemarket/types" + "github.com/cosmos/evm/x/vm/types" + "github.com/ethereum/go-ethereum/common" + + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" ) +func BenchmarkGasEstimation(b *testing.B) { + // Setup benchmark test environment + keys := keyring.New(2) + // Set custom balance based on test params + customGenesis := network.CustomGenesisState{} + feemarketGenesis := feemarkettypes.DefaultGenesisState() + feemarketGenesis.Params.NoBaseFee = true + customGenesis[feemarkettypes.ModuleName] = feemarketGenesis + opts := []network.ConfigOption{ + network.WithPreFundedAccounts(keys.GetAllAccAddrs()...), + network.WithCustomGenesis(customGenesis), + } + nw := network.NewUnitTestNetwork(CreateEvmd, opts...) + // gh := grpc.NewIntegrationHandler(nw) + // tf := factory.New(nw, gh) + + chainConfig := types.DefaultChainConfig(nw.GetEIP155ChainID().Uint64()) + // get the denom and decimals set on chain initialization + // because we'll need to set them again when resetting the chain config + denom := types.GetEVMCoinDenom() + extendedDenom := types.GetEVMCoinExtendedDenom() + displayDenom := types.GetEVMCoinDisplayDenom() + decimals := types.GetEVMCoinDecimals() + + configurator := types.NewEVMConfigurator() + configurator.ResetTestConfig() + err := configurator. + WithChainConfig(chainConfig). + WithEVMCoinInfo(types.EvmCoinInfo{ + Denom: denom, + ExtendedDenom: extendedDenom, + DisplayDenom: displayDenom, + Decimals: decimals, + }). + Configure() + require.NoError(b, err) + + // Use simple transaction args for consistent benchmarking + args := types.TransactionArgs{ + To: &common.Address{}, + } + + marshalArgs, err := json.Marshal(args) + require.NoError(b, err) + + req := types.EthCallRequest{ + Args: marshalArgs, + GasCap: config.DefaultGasCap, + ProposerAddress: nw.GetContext().BlockHeader().ProposerAddress, + } + + // Reset timer to exclude setup time + b.ResetTimer() + + // Run the benchmark + for i := 0; i < b.N; i++ { + _, err := nw.GetEvmClient().EstimateGas( + nw.GetContext(), + &req, + ) + if err != nil { + b.Fatal(err) + } + } +} + func TestKeeperTestSuite(t *testing.T) { s := vm.NewKeeperTestSuite(CreateEvmd) s.EnableFeemarket = false diff --git a/evmd/tests/ledger/evmosd_suite_test.go b/evmd/tests/ledger/evmosd_suite_test.go index ad5f7d7f3..200a8a5da 100644 --- a/evmd/tests/ledger/evmosd_suite_test.go +++ b/evmd/tests/ledger/evmosd_suite_test.go @@ -26,6 +26,7 @@ import ( clientkeys "github.com/cosmos/evm/client/keys" "github.com/cosmos/evm/crypto/hd" cosmosevmkeyring "github.com/cosmos/evm/crypto/keyring" + "github.com/cosmos/evm/encoding" "github.com/cosmos/evm/evmd" "github.com/cosmos/evm/evmd/tests/ledger/mocks" "github.com/cosmos/evm/testutil/constants" @@ -39,7 +40,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" - sdktestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" ) var s *LedgerTestSuite @@ -115,7 +115,7 @@ func (suite *LedgerTestSuite) SetupEvmosApp() { }) } -func (suite *LedgerTestSuite) NewKeyringAndCtxs(krHome string, input io.Reader, encCfg sdktestutil.TestEncodingConfig) (keyring.Keyring, client.Context, context.Context) { +func (suite *LedgerTestSuite) NewKeyringAndCtxs(krHome string, input io.Reader, encCfg encoding.Config) (keyring.Keyring, client.Context, context.Context) { kr, err := keyring.New( sdk.KeyringServiceName(), keyring.BackendTest, diff --git a/evmd/tests/ledger/ledger_test.go b/evmd/tests/ledger/ledger_test.go index cee58a793..8de8823b3 100644 --- a/evmd/tests/ledger/ledger_test.go +++ b/evmd/tests/ledger/ledger_test.go @@ -24,7 +24,6 @@ import ( sdktestutil "github.com/cosmos/cosmos-sdk/testutil" sdktestutilcli "github.com/cosmos/cosmos-sdk/testutil/cli" sdk "github.com/cosmos/cosmos-sdk/types" - sdktestutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli" ) @@ -42,7 +41,7 @@ var ( var _ = Describe("Ledger CLI and keyring functionality: ", func() { var ( receiverAccAddr sdk.AccAddress - encCfg sdktestutilmod.TestEncodingConfig + encCfg encoding.Config kr keyring.Keyring mockedIn sdktestutil.BufferReader clientCtx client.Context diff --git a/evmd/tests/network/util.go b/evmd/tests/network/util.go index a5a5d1184..fc4a538d4 100644 --- a/evmd/tests/network/util.go +++ b/evmd/tests/network/util.go @@ -30,7 +30,6 @@ import ( servercmtlog "github.com/cosmos/cosmos-sdk/server/log" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -138,6 +137,7 @@ func startInProcess(cfg Config, val *Validator) error { val.AppConfig, nil, app.(server.AppWithPendingTxStream), + nil, ) if err != nil { return err @@ -226,11 +226,6 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance inflationGenState.Params.MintDenom = cfg.BondDenom cfg.GenesisState[minttypes.ModuleName] = cfg.Codec.MustMarshalJSON(&inflationGenState) - var crisisGenState crisistypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[crisistypes.ModuleName], &crisisGenState) - - crisisGenState.ConstantFee.Denom = cfg.BondDenom - cfg.GenesisState[crisistypes.ModuleName] = cfg.Codec.MustMarshalJSON(&crisisGenState) var evmGenState evmtypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[evmtypes.ModuleName], &evmGenState) diff --git a/evmd/upgrades.go b/evmd/upgrades.go index d51f29c44..2413912c1 100644 --- a/evmd/upgrades.go +++ b/evmd/upgrades.go @@ -1,5 +1,42 @@ package evmd +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + storetypes "cosmossdk.io/store/types" + upgradetypes "cosmossdk.io/x/upgrade/types" +) + +// UpgradeName defines the on-chain upgrade name for the sample EVMD upgrade +// from v0.4.0 to v0.5.0. +// +// NOTE: This upgrade defines a reference implementation of what an upgrade +// could look like when an application is migrating from EVMD version +// v0.4.0 to v0.5.x +const UpgradeName = "v0.4.0-to-v0.5.0" + func (app EVMD) RegisterUpgradeHandlers() { - // No upgrades registered yet + app.UpgradeKeeper.SetUpgradeHandler( + UpgradeName, + func(ctx context.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + sdk.UnwrapSDKContext(ctx).Logger().Debug("this is a debug level message to test that verbose logging mode has properly been enabled during a chain upgrade") + return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) + }, + ) + + upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() + if err != nil { + panic(err) + } + + if upgradeInfo.Name == UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := storetypes.StoreUpgrades{ + Added: []string{}, + } + // configure store loader that checks if version == upgradeHeight and applies store upgrades + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) + } } diff --git a/go.mod b/go.mod index 7bbd55c08..e40893caf 100644 --- a/go.mod +++ b/go.mod @@ -22,11 +22,11 @@ require ( github.com/cosmos/cosmos-sdk v0.53.4 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.7.0 - github.com/cosmos/ibc-go/modules/capability v1.0.1 - github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b + github.com/cosmos/ibc-go/v10 v10.3.0 github.com/creachadair/tomledit v0.0.28 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/ethereum/go-ethereum v1.15.11 + github.com/gogo/protobuf v1.3.2 github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.3 @@ -92,6 +92,7 @@ require ( github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chigopher/pathlib v0.19.1 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cloudwego/base64x v0.1.5 // indirect github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect @@ -142,7 +143,6 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.2.5 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect @@ -171,11 +171,12 @@ require ( github.com/hdevalence/ed25519consensus v0.2.0 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huandu/skiplist v1.2.1 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/huin/goupnp v1.3.0 // indirect - github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/jinzhu/copier v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.18.0 // indirect @@ -234,6 +235,7 @@ require ( github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ulikunitz/xz v0.5.11 // indirect + github.com/vektra/mockery/v2 v2.53.4 // indirect github.com/zeebo/errs v1.4.0 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.4.0-alpha.1 // indirect @@ -252,6 +254,7 @@ require ( go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/arch v0.17.0 // indirect golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect + golang.org/x/mod v0.26.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sys v0.35.0 // indirect golang.org/x/term v0.34.0 // indirect @@ -273,7 +276,7 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // use Cosmos geth fork // branch: release/1.16 - github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v0.0.0-20250806193535-2fc7571efa91 + github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 // Security Advisory https://github.com/advisories/GHSA-h395-qcrw-5vmq github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1 // replace broken goleveldb diff --git a/go.sum b/go.sum index 6321d356d..3d8373130 100644 --- a/go.sum +++ b/go.sum @@ -783,6 +783,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chigopher/pathlib v0.19.1 h1:RoLlUJc0CqBGwq239cilyhxPNLXTK+HXoASGyGznx5A= +github.com/chigopher/pathlib v0.19.1/go.mod h1:tzC1dZLW8o33UQpWkNkhvPwL5n4yyFRFm/jL1YGWFvY= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -854,8 +856,8 @@ github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= -github.com/cosmos/go-ethereum v0.0.0-20250806193535-2fc7571efa91 h1:kgu2NkKzSeJJlVsKeS+KbdzfUeaFqrqmmhwixd/PNH4= -github.com/cosmos/go-ethereum v0.0.0-20250806193535-2fc7571efa91/go.mod h1:X5CIOyo8SuK1Q5GnaEizQVLHT/DfsiGWuNeVdQcEMNA= +github.com/cosmos/go-ethereum v1.16.2-cosmos-1 h1:QIaIS6HIdPSBdTvpFhxswhMLUJgcr4irbd2o9ZKldAI= +github.com/cosmos/go-ethereum v1.16.2-cosmos-1/go.mod h1:X5CIOyo8SuK1Q5GnaEizQVLHT/DfsiGWuNeVdQcEMNA= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= @@ -863,10 +865,8 @@ github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fr github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/iavl v1.2.2 h1:qHhKW3I70w+04g5KdsdVSHRbFLgt3yY3qTMd4Xa4rC8= github.com/cosmos/iavl v1.2.2/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= -github.com/cosmos/ibc-go/modules/capability v1.0.1 h1:ibwhrpJ3SftEEZRxCRkH0fQZ9svjthrX2+oXdZvzgGI= -github.com/cosmos/ibc-go/modules/capability v1.0.1/go.mod h1:rquyOV262nGJplkumH+/LeYs04P3eV8oB7ZM4Ygqk4E= -github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b h1:+TaXFL0WksE7yBs6DqHrRIDtkKZfu3+Lirbs6rK4N20= -github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250528142215-7d579b91ac6b/go.mod h1:AQ76dzfU5i3UB5UiktWe6q7hpbPyBXuZcnjMQekBkHs= +github.com/cosmos/ibc-go/v10 v10.3.0 h1:w5DkHih8qn15deAeFoTk778WJU+xC1krJ5kDnicfUBc= +github.com/cosmos/ibc-go/v10 v10.3.0/go.mod h1:CthaR7n4d23PJJ7wZHegmNgbVcLXCQql7EwHrAXnMtw= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= @@ -1281,11 +1281,11 @@ github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3 github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= -github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -1309,6 +1309,8 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= +github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= +github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= @@ -1708,6 +1710,8 @@ 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.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= +github.com/vektra/mockery/v2 v2.53.4 h1:abBWJLUQppM7T/VsLasBwgl7XXQRWH6lC3bnbJpOCLk= +github.com/vektra/mockery/v2 v2.53.4/go.mod h1:hIFFb3CvzPdDJJiU7J4zLRblUMv7OuezWsHPmswriwo= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= @@ -1879,6 +1883,8 @@ golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= 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= diff --git a/ibc/interfaces.go b/ibc/interfaces.go new file mode 100644 index 000000000..b0198ac4d --- /dev/null +++ b/ibc/interfaces.go @@ -0,0 +1,13 @@ +package ibc + +import ( + cmtbytes "github.com/cometbft/cometbft/libs/bytes" + + ibctypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type TransferKeeper interface { + GetDenom(ctx sdk.Context, denomHash cmtbytes.HexBytes) (ibctypes.Denom, bool) +} diff --git a/ibc/utils.go b/ibc/utils.go index 007cfd0b3..d3261f0b2 100644 --- a/ibc/utils.go +++ b/ibc/utils.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/cosmos/evm/utils" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" @@ -108,7 +107,7 @@ func GetSentCoin(rawDenom, rawAmt string) sdk.Coin { // GetDenom returns the denomination from the corresponding IBC denomination. If the // denomination is not an IBC voucher or the trace is not found, it returns an error. func GetDenom( - transferKeeper transferkeeper.Keeper, + transferKeeper TransferKeeper, ctx sdk.Context, voucherDenom string, ) (transfertypes.Denom, error) { diff --git a/interfaces.go b/interfaces.go index 30e3b2733..ecebf7e16 100644 --- a/interfaces.go +++ b/interfaces.go @@ -27,7 +27,6 @@ import ( distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) @@ -60,7 +59,6 @@ type EvmApp interface { //nolint:revive DefaultGenesis() map[string]json.RawMessage GetKey(storeKey string) *storetypes.KVStoreKey GetAnteHandler() sdk.AnteHandler - GetSubspace(moduleName string) paramstypes.Subspace MsgServiceRouter() *baseapp.MsgServiceRouter GetMempool() mempool.ExtMempool } diff --git a/local_node.sh b/local_node.sh index 6d3d0ba7c..fa0fff988 100755 --- a/local_node.sh +++ b/local_node.sh @@ -240,7 +240,7 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then jq '.app_state["bank"]["denom_metadata"]=[{"description":"The native staking token for evmd.","denom_units":[{"denom":"atest","exponent":0,"aliases":["attotest"]},{"denom":"test","exponent":18,"aliases":[]}],"base":"atest","display":"test","name":"Test Token","symbol":"TEST","uri":"","uri_hash":""}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["evm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805", "0x0000000000000000000000000000000000000806", "0x0000000000000000000000000000000000000807"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["evm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805", "0x0000000000000000000000000000000000000806", "0x0000000000000000000000000000000000000807", "0x0000000000000000000000000000000000000900"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" @@ -287,11 +287,6 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then sed -i.bak 's/"voting_period": "172800s"/"voting_period": "30s"/g' "$GENESIS" sed -i.bak 's/"expedited_voting_period": "86400s"/"expedited_voting_period": "15s"/g' "$GENESIS" - # pruning - sed -i.bak 's/pruning = "default"/pruning = "custom"/g' "$APP_TOML" - sed -i.bak 's/pruning-keep-recent = "0"/pruning-keep-recent = "100"/g' "$APP_TOML" - sed -i.bak 's/pruning-interval = "0"/pruning-interval = "10"/g' "$APP_TOML" - # fund validator (devs already funded in the loop) evmd genesis add-genesis-account "$VAL_KEY" 100000000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" @@ -363,7 +358,8 @@ fi evmd start "$TRACE" \ --pruning nothing \ --log_level $LOGLEVEL \ - --minimum-gas-prices=0.0001atest \ + --minimum-gas-prices=0atest \ + --evm.min-tip=0 \ --home "$CHAINDIR" \ --json-rpc.api eth,txpool,personal,net,debug,web3 \ --chain-id "$CHAINID" diff --git a/mempool/README.md b/mempool/README.md index dd55266b8..25230c870 100644 --- a/mempool/README.md +++ b/mempool/README.md @@ -82,11 +82,6 @@ if evmtypes.GetChainConfig() != nil { ) app.EVMMempool = evmMempool - // Set the global mempool for RPC access - if err := evmmempool.SetGlobalEVMMempool(evmMempool); err != nil { - panic(err) - } - // Replace BaseApp mempool app.SetMempool(evmMempool) @@ -103,6 +98,23 @@ if evmtypes.GetChainConfig() != nil { ) app.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler()) } + +// Close unsubscribes from the CometBFT event bus (if set) and closes the underlying BaseApp. +func (app *EVMD) Close() error { + var err error + if m, ok := app.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok { + err = m.Close() + } + err = errors.Join(err, app.BaseApp.Close()) + msg := "Application gracefully shutdown" + if err == nil { + app.Logger().Info(msg) + } else { + app.Logger().Error(msg, "error", err) + } + return err +} + ``` ### Configuration Options @@ -211,7 +223,7 @@ ERROR unable to publish transaction nonce=40 expected=12: invalid sequence ERROR unable to publish transaction nonce=41 expected=12: invalid sequence ``` -**Real-World Testing**: The [`tests/systemtests/Counter/script/SimpleSends.s.sol`](../../tests/systemtests/Counter/script/SimpleSends.s.sol) script demonstrates typical Ethereum tooling behavior - it sends 10 sequential transactions in a batch, which naturally arrive out of order and create nonce gaps. With the default Cosmos mempool, this script would fail with sequence errors. With the EVM mempool, all transactions are queued locally and promoted as gaps are filled, allowing the script to succeed. +**Real-World Testing**: The [`tests/systemtests/Counter/script/SimpleSends.s.sol`](../tests/systemtests/Counter/script/SimpleSends.s.sol) script demonstrates typical Ethereum tooling behavior - it sends 10 sequential transactions in a batch, which naturally arrive out of order and create nonce gaps. With the default Cosmos mempool, this script would fail with sequence errors. With the EVM mempool, all transactions are queued locally and promoted as gaps are filled, allowing the script to succeed. ### Design Principles @@ -399,7 +411,7 @@ The following diagrams illustrate the complete transaction flow architecture, sh ### Architecture Overview -![EVM Mempool Architecture](img/mempool_architecture.jpg) +![EVM Mempool Architecture](img/mempool_architecture.svg) ### Transaction Flow diff --git a/mempool/blockchain.go b/mempool/blockchain.go index 00fc7dd40..bd4f2f02c 100644 --- a/mempool/blockchain.go +++ b/mempool/blockchain.go @@ -41,6 +41,7 @@ type Blockchain struct { zeroHeader *types.Header blockGasLimit uint64 previousHeaderHash common.Hash + latestCtx sdk.Context } // newBlockchain creates a new Blockchain instance that bridges Cosmos SDK state with Ethereum mempools. @@ -78,14 +79,17 @@ func (b Blockchain) Config() *params.ChainConfig { // including block height, timestamp, gas limits, and base fee (if London fork is active). // Returns a zero header as placeholder if the context is not yet available. func (b Blockchain) CurrentBlock() *types.Header { - ctx, err := b.GetLatestCtx() - // This should only error out on the first block. + ctx, err := b.GetLatestContext() if err != nil { - b.logger.Debug("failed to get latest context, returning zero header", "error", err) return b.zeroHeader } blockHeight := ctx.BlockHeight() + // prevent the reorg from triggering after a restart since previousHeaderHash is stored as an in-memory variable + if blockHeight > 1 && b.previousHeaderHash == (common.Hash{}) { + return b.zeroHeader + } + blockTime := ctx.BlockTime().Unix() gasUsed := b.feeMarketKeeper.GetBlockGasWanted(ctx) appHash := common.BytesToHash(ctx.BlockHeader().AppHash) @@ -164,6 +168,12 @@ func (b Blockchain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event // NotifyNewBlock sends a chain head event when a new block is finalized func (b *Blockchain) NotifyNewBlock() { + latestCtx, err := b.newLatestContext() + if err != nil { + b.latestCtx = sdk.Context{} + b.logger.Debug("failed to get latest context, notifying chain head", "error", err) + } + b.latestCtx = latestCtx header := b.CurrentBlock() headerHash := header.Hash() @@ -192,22 +202,34 @@ func (b Blockchain) StateAt(hash common.Hash) (vm.StateDB, error) { } // Always get the latest context to avoid stale nonce state. - ctx, err := b.GetLatestCtx() + ctx, err := b.GetLatestContext() if err != nil { // If we can't get the latest context for blocks past 1, something is seriously wrong with the chain state return nil, fmt.Errorf("failed to get latest context for StateAt: %w", err) } appHash := ctx.BlockHeader().AppHash - stateDB := statedb.New(ctx, b.vmKeeper, statedb.NewEmptyTxConfig(common.Hash(appHash))) + stateDB := statedb.New(ctx, b.vmKeeper, statedb.NewEmptyTxConfig()) b.logger.Debug("StateDB created successfully", "app_hash", common.Hash(appHash).Hex()) return stateDB, nil } -// GetLatestCtx retrieves the most recent query context from the application. +// GetLatestContext returns the latest context as updated by the block, +// or attempts to retrieve it again if unavailable. +func (b Blockchain) GetLatestContext() (sdk.Context, error) { + b.logger.Debug("getting latest context") + + if b.latestCtx.Context() != nil { + return b.latestCtx, nil + } + + return b.newLatestContext() +} + +// newLatestContext retrieves the most recent query context from the application. // This provides access to the current blockchain state for transaction validation and execution. -func (b Blockchain) GetLatestCtx() (sdk.Context, error) { +func (b Blockchain) newLatestContext() (sdk.Context, error) { b.logger.Debug("getting latest context") ctx, err := b.getCtxCallback(0, false) diff --git a/mempool/check_tx.go b/mempool/check_tx.go index 438ad9783..f42a024fe 100644 --- a/mempool/check_tx.go +++ b/mempool/check_tx.go @@ -18,7 +18,7 @@ func NewCheckTxHandler(mempool *ExperimentalEVMMempool) types.CheckTxHandler { gInfo, result, anteEvents, err := runTx(request.Tx, nil) if err != nil { // detect if there is a nonce gap error (only returned for EVM transactions) - if errors.Is(err, ErrNonceGap) { + if errors.Is(err, ErrNonceGap) || errors.Is(err, ErrNonceLow) { // send it to the mempool for further triage err := mempool.InsertInvalidNonce(request.Tx) if err != nil { diff --git a/mempool/errors.go b/mempool/errors.go index 522d2f7e5..f42ddc530 100644 --- a/mempool/errors.go +++ b/mempool/errors.go @@ -8,4 +8,5 @@ var ( ErrExpectedOneError = errors.New("expected 1 error") ErrNotEVMTransaction = errors.New("transaction is not an EVM transaction") ErrNonceGap = errors.New("tx nonce is higher than account nonce") + ErrNonceLow = errors.New("tx nonce is lower than account nonce") ) diff --git a/mempool/img/mempool_architecture.d2 b/mempool/img/mempool_architecture.d2 new file mode 100644 index 000000000..20f07e9ab --- /dev/null +++ b/mempool/img/mempool_architecture.d2 @@ -0,0 +1,62 @@ +direction: right + +# entities +prepare proposal +check tx\nhandler +comet bft +rpc call +broadcast +rebroadcast\ncallback: { shape: diamond } +evm mempool: { + direction: up + + # entities + ext mempool\ninterface impl + cosmos priority\nnonce mempool + tx pool: { + direction: up + + # entities + queued\ntransactions + pending\ntransactions + tx pool\ninterface + reset loop\n(evicts from\nqueued and\npending txs) + promotion: {shape: diamond } + filter: { shape: diamond } + + # edges + filter -> queued\ntransactions: add nonce\ngapped txs + filter -> pending\ntransactions: add\nexecutable txs + promotion -> pending\ntransactions: promote tx + queued\ntransactions -> promotion: check closed gap\nand promote tx + pending\ntransactions -> tx pool\ninterface: get txs for\nblock building + tx pool\ninterface -> filter: add valid txs + } + + # edges + tx pool.tx pool\ninterface -> ext mempool\ninterface impl: get txs for\nblock building + + cosmos priority\nnonce mempool -> ext mempool\ninterface impl: get txs for\nblock building + + ext mempool\ninterface impl -> tx pool.tx pool\ninterface: success/nonce gap failure:\nadd valid evm txs + ext mempool\ninterface impl -> tx pool.tx pool\ninterface: recheck tx\neviction + ext mempool\ninterface impl -> cosmos priority\nnonce mempool: add\ncosmos txs +} + +# edges +rebroadcast\ncallback -> comet bft: rebroadcast\nrebuilt tx + +evm mempool.tx pool.promotion -> rebroadcast\ncallback: call rebroadcast\ncallback +evm mempool.ext mempool\ninterface impl -> prepare proposal: get txs for\nblock building + +comet bft -> broadcast: success:\nbroadcast tx +comet bft -> check tx\nhandler: send tx for validation +comet bft -> check tx\nhandler: send tx again\nfor recheck + +check tx\nhandler -> rpc call: queued\nsuccess response +check tx\nhandler -> comet bft: success: broadcast\nand add to mempool +check tx\nhandler -> comet bft: recheck tx complete\nfailure: discard from pool +check tx\nhandler -> evm mempool.ext mempool\ninterface impl: complete failure:\nremove from pending +check tx\nhandler -> evm mempool.ext mempool\ninterface impl: nonce gap failure:\nadd transaction +check tx\nhandler -> evm mempool.ext mempool\ninterface impl: success:\nadd txs +check tx\nhandler -> evm mempool.ext mempool\ninterface impl: recheck tx complete\nfailure: eviction \ No newline at end of file diff --git a/mempool/img/mempool_architecture.svg b/mempool/img/mempool_architecture.svg new file mode 100644 index 000000000..5a98f5c7d --- /dev/null +++ b/mempool/img/mempool_architecture.svg @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +PREPARE PROPOSALCHECK TXHANDLERCOMET BFTRPC CALLBROADCASTREBROADCASTCALLBACKEVM MEMPOOLEXT MEMPOOLINTERFACE IMPLCOSMOS PRIORITYNONCE MEMPOOLTX POOLQUEUEDTRANSACTIONSPENDINGTRANSACTIONSTX POOLINTERFACERESET LOOP(EVICTS FROMQUEUED ANDPENDING TXS)PROMOTIONFILTER ADD NONCEGAPPED TXSADDEXECUTABLE TXSPROMOTE TXCHECK CLOSED GAPAND PROMOTE TXGET TXS FORBLOCK BUILDINGADD VALID TXSGET TXS FORBLOCK BUILDINGGET TXS FORBLOCK BUILDINGSUCCESS/NONCE GAP FAILURE:ADD VALID EVM TXSRECHECK TXEVICTIONADDCOSMOS TXSREBROADCASTREBUILT TXCALL REBROADCASTCALLBACKGET TXS FORBLOCK BUILDINGSUCCESS:BROADCAST TXSEND TX FOR VALIDATIONSEND TX AGAINFOR RECHECKQUEUEDSUCCESS RESPONSESUCCESS: BROADCASTAND ADD TO MEMPOOLRECHECK TX COMPLETEFAILURE: DISCARD FROM POOLCOMPLETE FAILURE:REMOVE FROM PENDINGNONCE GAP FAILURE:ADD TRANSACTIONSUCCESS:ADD TXSRECHECK TX COMPLETEFAILURE: EVICTION + + + + + + + + + + + + + + + + + + + + + + + + + +UNLICENSED COPY diff --git a/mempool/iterator.go b/mempool/iterator.go index 0ca1b90d3..b7a75b91c 100644 --- a/mempool/iterator.go +++ b/mempool/iterator.go @@ -255,7 +255,7 @@ func (i *EVMMempoolIterator) extractCosmosEffectiveTip(tx sdk.Tx) *uint256.Int { return nil // Transaction doesn't implement FeeTx interface } - var bondDenomFeeAmount math.Int + bondDenomFeeAmount := math.ZeroInt() fees := feeTx.GetFee() for _, coin := range fees { if coin.Denom == i.bondDenom { @@ -340,17 +340,18 @@ func (i *EVMMempoolIterator) convertEVMToSDKTx(nextEVMTx *txpool.LazyTransaction } msgEthereumTx := &msgtypes.MsgEthereumTx{} + hash := nextEVMTx.Tx.Hash() if err := msgEthereumTx.FromSignedEthereumTx(nextEVMTx.Tx, ethtypes.LatestSignerForChainID(i.chainID)); err != nil { - i.logger.Error("failed to convert signed Ethereum transaction", "error", err, "tx_hash", nextEVMTx.Tx.Hash().Hex()) + i.logger.Error("failed to convert signed Ethereum transaction", "error", err, "tx_hash", hash) return nil // Return nil for invalid tx instead of panicking } cosmosTx, err := msgEthereumTx.BuildTx(i.txConfig.NewTxBuilder(), i.bondDenom) if err != nil { - i.logger.Error("failed to build Cosmos transaction from EVM transaction", "error", err, "tx_hash", nextEVMTx.Tx.Hash().Hex()) + i.logger.Error("failed to build Cosmos transaction from EVM transaction", "error", err, "tx_hash", hash) return nil } - i.logger.Debug("successfully converted EVM transaction to Cosmos transaction", "tx_hash", nextEVMTx.Tx.Hash().Hex()) + i.logger.Debug("successfully converted EVM transaction to Cosmos transaction", "tx_hash", hash) return cosmosTx } diff --git a/mempool/mempool.go b/mempool/mempool.go index 37363735c..a3a7aa62c 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -9,13 +9,15 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/holiman/uint256" + cmttypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/evm/mempool/miner" "github.com/cosmos/evm/mempool/txpool" "github.com/cosmos/evm/mempool/txpool/legacypool" + "github.com/cosmos/evm/rpc/stream" "github.com/cosmos/evm/x/precisebank/types" evmtypes "github.com/cosmos/evm/x/vm/types" - errorsmod "cosmossdk.io/errors" "cosmossdk.io/log" "cosmossdk.io/math" @@ -27,6 +29,13 @@ import ( var _ sdkmempool.ExtMempool = &ExperimentalEVMMempool{} +const ( + // SubscriberName is the name of the event bus subscriber for the EVM mempool + SubscriberName = "evm" + // fallbackBlockGasLimit is the default block gas limit is 0 or missing in genesis file + fallbackBlockGasLimit = 100_000_000 +) + type ( // ExperimentalEVMMempool is a unified mempool that manages both EVM and Cosmos SDK transactions. // It provides a single interface for transaction insertion, selection, and removal while @@ -48,12 +57,15 @@ type ( bondDenom string evmDenom string blockGasLimit uint64 // Block gas limit from consensus parameters + minTip *uint256.Int /** Verification **/ anteHandler sdk.AnteHandler /** Concurrency **/ mtx sync.Mutex + + eventBus *cmttypes.EventBus } ) @@ -61,11 +73,12 @@ type ( // It allows customization of the underlying mempools, verification functions, // and broadcasting functions used by the sdkmempool. type EVMMempoolConfig struct { - TxPool *txpool.TxPool - CosmosPool sdkmempool.ExtMempool - AnteHandler sdk.AnteHandler - BroadCastTxFn func(txs []*ethtypes.Transaction) error - BlockGasLimit uint64 // Block gas limit from consensus parameters + LegacyPoolConfig *legacypool.Config + CosmosPoolConfig *sdkmempool.PriorityNonceMempoolConfig[math.Int] + AnteHandler sdk.AnteHandler + BroadCastTxFn func(txs []*ethtypes.Transaction) error + BlockGasLimit uint64 // Block gas limit from consensus parameters + MinTip *uint256.Int } // NewExperimentalEVMMempool creates a new unified mempool for EVM and Cosmos transactions. @@ -74,10 +87,8 @@ type EVMMempoolConfig struct { // of pools and verification functions, with sensible defaults created if not provided. func NewExperimentalEVMMempool(getCtxCallback func(height int64, prove bool) (sdk.Context, error), logger log.Logger, vmKeeper VMKeeperI, feeMarketKeeper FeeMarketKeeperI, txConfig client.TxConfig, clientCtx client.Context, config *EVMMempoolConfig) *ExperimentalEVMMempool { var ( - txPool *txpool.TxPool - cosmosPool sdkmempool.ExtMempool - anteHandler sdk.AnteHandler - blockchain *Blockchain + cosmosPool sdkmempool.ExtMempool + blockchain *Blockchain ) bondDenom := evmtypes.GetEVMCoinDenom() @@ -92,37 +103,37 @@ func NewExperimentalEVMMempool(getCtxCallback func(height int64, prove bool) (sd panic("config must not be nil") } - anteHandler = config.AnteHandler + if config.BlockGasLimit == 0 { + logger.Warn("block gas limit is 0, setting to fallback", "fallback_limit", fallbackBlockGasLimit) + config.BlockGasLimit = fallbackBlockGasLimit + } + blockchain = newBlockchain(getCtxCallback, logger, vmKeeper, feeMarketKeeper, config.BlockGasLimit) - if config.BlockGasLimit == 0 { - logger.Debug("block gas limit is 0, setting default", "default_limit", 100_000_000) - config.BlockGasLimit = 100_000_000 + // Create txPool from configuration + legacyConfig := legacypool.DefaultConfig + if config.LegacyPoolConfig != nil { + legacyConfig = *config.LegacyPoolConfig } - // Default txPool - txPool = config.TxPool - if txPool == nil { - legacyPool := legacypool.New(legacypool.DefaultConfig, blockchain) + legacyPool := legacypool.New(legacyConfig, blockchain) - // Set up broadcast function using clientCtx - if config.BroadCastTxFn != nil { - legacyPool.BroadcastTxFn = config.BroadCastTxFn - } else { - // Create default broadcast function using clientCtx. - // The EVM mempool will broadcast transactions when it promotes them - // from queued into pending, noting their readiness to be executed. - legacyPool.BroadcastTxFn = func(txs []*ethtypes.Transaction) error { - logger.Debug("broadcasting EVM transactions", "tx_count", len(txs)) - return broadcastEVMTransactions(clientCtx, txConfig, txs) - } + // Set up broadcast function using clientCtx + if config.BroadCastTxFn != nil { + legacyPool.BroadcastTxFn = config.BroadCastTxFn + } else { + // Create default broadcast function using clientCtx. + // The EVM mempool will broadcast transactions when it promotes them + // from queued into pending, noting their readiness to be executed. + legacyPool.BroadcastTxFn = func(txs []*ethtypes.Transaction) error { + logger.Debug("broadcasting EVM transactions", "tx_count", len(txs)) + return broadcastEVMTransactions(clientCtx, txConfig, txs) } + } - txPoolInit, err := txpool.New(uint64(0), blockchain, []txpool.SubPool{legacyPool}) - if err != nil { - panic(err) - } - txPool = txPoolInit + txPool, err := txpool.New(uint64(0), blockchain, []txpool.SubPool{legacyPool}) + if err != nil { + panic(err) } if len(txPool.Subpools) != 1 { @@ -132,11 +143,12 @@ func NewExperimentalEVMMempool(getCtxCallback func(height int64, prove bool) (sd panic("tx pool should contain only legacypool") } - // Default Cosmos Mempool - cosmosPool = config.CosmosPool - if cosmosPool == nil { - priorityConfig := sdkmempool.PriorityNonceMempoolConfig[math.Int]{} - priorityConfig.TxPriority = sdkmempool.TxPriority[math.Int]{ + // Create Cosmos Mempool from configuration + cosmosPoolConfig := config.CosmosPoolConfig + if cosmosPoolConfig == nil { + // Default configuration + defaultConfig := sdkmempool.PriorityNonceMempoolConfig[math.Int]{} + defaultConfig.TxPriority = sdkmempool.TxPriority[math.Int]{ GetTxPriority: func(goCtx context.Context, tx sdk.Tx) math.Int { cosmosTxFee, ok := tx.(sdk.FeeTx) if !ok { @@ -156,9 +168,11 @@ func NewExperimentalEVMMempool(getCtxCallback func(height int64, prove bool) (sd }, MinValue: math.ZeroInt(), } - cosmosPool = sdkmempool.NewPriorityMempool(priorityConfig) + cosmosPoolConfig = &defaultConfig } + cosmosPool = sdkmempool.NewPriorityMempool(*cosmosPoolConfig) + evmMempool := &ExperimentalEVMMempool{ vmKeeper: vmKeeper, txPool: txPool, @@ -170,7 +184,8 @@ func NewExperimentalEVMMempool(getCtxCallback func(height int64, prove bool) (sd bondDenom: bondDenom, evmDenom: evmDenom, blockGasLimit: config.BlockGasLimit, - anteHandler: anteHandler, + minTip: config.MinTip, + anteHandler: config.AnteHandler, } vmKeeper.SetEvmMempool(evmMempool) @@ -202,22 +217,18 @@ func (m *ExperimentalEVMMempool) Insert(goCtx context.Context, tx sdk.Tx) error blockHeight := ctx.BlockHeight() m.logger.Debug("inserting transaction into mempool", "block_height", blockHeight) - - if blockHeight < 2 { - return errorsmod.Wrap(sdkerrors.ErrInvalidHeight, "Mempool is not ready. Please wait for block 1 to finalize.") - } - ethMsg, err := m.getEVMMessage(tx) if err == nil { // Insert into EVM pool - m.logger.Debug("inserting EVM transaction", "tx_hash", ethMsg.Hash) + hash := ethMsg.Hash() + m.logger.Debug("inserting EVM transaction", "tx_hash", hash) ethTxs := []*ethtypes.Transaction{ethMsg.AsTransaction()} errs := m.txPool.Add(ethTxs, true) if len(errs) > 0 && errs[0] != nil { - m.logger.Error("failed to insert EVM transaction", "error", errs[0], "tx_hash", ethMsg.Hash) + m.logger.Error("failed to insert EVM transaction", "error", errs[0], "tx_hash", hash) return errs[0] } - m.logger.Debug("EVM transaction inserted successfully", "tx_hash", ethMsg.Hash) + m.logger.Debug("EVM transaction inserted successfully", "tx_hash", hash) return nil } @@ -300,11 +311,12 @@ func (m *ExperimentalEVMMempool) Remove(tx sdk.Tx) error { // We should not do this with EVM transactions because removing them causes the subsequent ones to // be dequeued as temporarily invalid, only to be requeued a block later. // The EVM mempool handles removal based on account nonce automatically. + hash := msg.Hash() if m.shouldRemoveFromEVMPool(tx) { - m.logger.Debug("manually removing EVM transaction", "tx_hash", msg.Hash()) - m.legacyTxPool.RemoveTx(msg.Hash(), false, true) + m.logger.Debug("manually removing EVM transaction", "tx_hash", hash) + m.legacyTxPool.RemoveTx(hash, false, true) } else { - m.logger.Debug("skipping manual removal of EVM transaction, leaving to mempool to handle", "tx_hash", msg.Hash) + m.logger.Debug("skipping manual removal of EVM transaction, leaving to mempool to handle", "tx_hash", hash) } return nil } @@ -334,7 +346,7 @@ func (m *ExperimentalEVMMempool) shouldRemoveFromEVMPool(tx sdk.Tx) bool { // If it was a successful transaction or a sequence error, we let the mempool handle the cleaning. // If it was any other Cosmos or antehandler related issue, then we remove it. - ctx, err := m.blockchain.GetLatestCtx() + ctx, err := m.blockchain.GetLatestContext() if err != nil { m.logger.Debug("cannot get latest context for validation, keeping transaction", "error", err) return false // Cannot validate, keep transaction @@ -372,6 +384,44 @@ func (m *ExperimentalEVMMempool) SelectBy(goCtx context.Context, i [][]byte, f f } } +// SetEventBus sets CometBFT event bus to listen for new block header event. +func (m *ExperimentalEVMMempool) SetEventBus(eventBus *cmttypes.EventBus) { + if m.HasEventBus() { + m.eventBus.Unsubscribe(context.Background(), SubscriberName, stream.NewBlockHeaderEvents) //nolint: errcheck + } + m.eventBus = eventBus + sub, err := eventBus.Subscribe(context.Background(), SubscriberName, stream.NewBlockHeaderEvents) + if err != nil { + panic(err) + } + go func() { + for range sub.Out() { + m.GetBlockchain().NotifyNewBlock() + } + }() +} + +// HasEventBus returns true if the blockchain is configured to use an event bus for block notifications. +func (m *ExperimentalEVMMempool) HasEventBus() bool { + return m.eventBus != nil +} + +// Close unsubscribes from the CometBFT event bus and shuts down the mempool. +func (m *ExperimentalEVMMempool) Close() error { + var errs []error + if m.eventBus != nil { + if err := m.eventBus.Unsubscribe(context.Background(), SubscriberName, stream.NewBlockHeaderEvents); err != nil { + errs = append(errs, fmt.Errorf("failed to unsubscribe from event bus: %w", err)) + } + } + + if err := m.txPool.Close(); err != nil { + errs = append(errs, fmt.Errorf("failed to close txpool: %w", err)) + } + + return errors.Join(errs...) +} + // getEVMMessage validates that the transaction contains exactly one message and returns it if it's an EVM message. // Returns an error if the transaction has no messages, multiple messages, or the single message is not an EVM transaction. func (m *ExperimentalEVMMempool) getEVMMessage(tx sdk.Tx) (*evmtypes.MsgEthereumTx, error) { @@ -403,7 +453,7 @@ func (m *ExperimentalEVMMempool) getIterators(goCtx context.Context, i [][]byte) m.logger.Debug("getting iterators") pendingFilter := txpool.PendingFilter{ - MinTip: nil, + MinTip: m.minTip, BaseFee: baseFeeUint, BlobFee: nil, OnlyPlainTxs: true, diff --git a/mempool/registry_production.go b/mempool/registry_production.go deleted file mode 100644 index 74b1fd810..000000000 --- a/mempool/registry_production.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build !test -// +build !test - -package mempool - -import "errors" - -// globalEVMMempool holds the global reference to the ExperimentalEVMMempool instance. -// It can only be set during application initialization. -var globalEVMMempool *ExperimentalEVMMempool - -// SetGlobalEVMMempool sets the global ExperimentalEVMMempool instance. -// This should only be called during application initialization. -// In production builds, it returns an error if already set. -func SetGlobalEVMMempool(mempool *ExperimentalEVMMempool) error { - if globalEVMMempool != nil { - return errors.New("global EVM mempool already set") - } - globalEVMMempool = mempool - return nil -} - -// GetGlobalEVMMempool returns the global ExperimentalEVMMempool instance. -// Returns nil if not set. -func GetGlobalEVMMempool() *ExperimentalEVMMempool { - return globalEVMMempool -} - -// ResetGlobalEVMMempool resets the global ExperimentalEVMMempool instance. -// This is intended for testing purposes only. -func ResetGlobalEVMMempool() { - globalEVMMempool = nil -} diff --git a/mempool/registry_testing.go b/mempool/registry_testing.go deleted file mode 100644 index 1713dbc0e..000000000 --- a/mempool/registry_testing.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build test -// +build test - -package mempool - -// globalEVMMempool holds the global reference to the ExperimentalEVMMempool instance. -// It can only be set during application initialization. -var globalEVMMempool *ExperimentalEVMMempool - -// SetGlobalEVMMempool sets the global ExperimentalEVMMempool instance. -// This should only be called during application initialization. -// In testing builds, it allows resetting by not returning an error. -func SetGlobalEVMMempool(mempool *ExperimentalEVMMempool) error { - globalEVMMempool = mempool - return nil -} - -// GetGlobalEVMMempool returns the global ExperimentalEVMMempool instance. -// Returns nil if not set. -func GetGlobalEVMMempool() *ExperimentalEVMMempool { - return globalEVMMempool -} - -// ResetGlobalEVMMempool resets the global ExperimentalEVMMempool instance. -// This is intended for testing purposes only. -func ResetGlobalEVMMempool() { - globalEVMMempool = nil -} diff --git a/mempool/txpool/legacypool/reset_testing.go b/mempool/txpool/legacypool/reset_testing.go index 16a11a2a5..b24088c3d 100644 --- a/mempool/txpool/legacypool/reset_testing.go +++ b/mempool/txpool/legacypool/reset_testing.go @@ -22,17 +22,17 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { log.Debug("Skipping reorg on Cosmos chain (testing mode)", "oldHead", oldHead.Hash(), "newHead", newHead.Hash(), "newParent", newHead.ParentHash) reinject = nil // No transactions to reinject } - + // Initialize the internal state to the current head if newHead == nil { newHead = pool.chain.CurrentBlock() // Special case during testing } - + // Ensure BaseFee is set for EIP-1559 compatibility in tests if newHead.BaseFee == nil && pool.chainconfig.IsLondon(newHead.Number) { // Set a default base fee for testing newHead.BaseFee = big.NewInt(1000000000) // 1 gwei default } - + pool.resetInternalState(newHead, reinject) -} \ No newline at end of file +} diff --git a/metrics/geth.go b/metrics/geth.go new file mode 100644 index 000000000..44c052639 --- /dev/null +++ b/metrics/geth.go @@ -0,0 +1,59 @@ +package metrics + +import ( + "context" + "errors" + "net/http" + "time" + + gethmetrics "github.com/ethereum/go-ethereum/metrics" + gethprom "github.com/ethereum/go-ethereum/metrics/prometheus" + + "cosmossdk.io/log" +) + +// StartGethMetricServer starts the geth metrics server on the specified address. +func StartGethMetricServer(ctx context.Context, log log.Logger, addr string) error { + mux := http.NewServeMux() + mux.Handle("/metrics", gethprom.Handler(gethmetrics.DefaultRegistry)) + + server := &http.Server{ + Addr: addr, + Handler: mux, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + ReadHeaderTimeout: 10 * time.Second, + } + + errCh := make(chan error, 1) + + go func() { + log.Info("starting geth metrics server...", "address", addr) + errCh <- server.ListenAndServe() + }() + + // Start a blocking select to wait for an indication to stop the server or that + // the server failed to start properly. + select { + case <-ctx.Done(): + // The calling process canceled or closed the provided context, so we must + // gracefully stop the metrics server. + log.Info("stopping geth metrics server...", "address", addr) + + shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + if err := server.Shutdown(shutdownCtx); err != nil { + log.Error("geth metrics server shutdown error", "err", err) + return err + } + return nil + + case err := <-errCh: + if err != nil && !errors.Is(err, http.ErrServerClosed) { + log.Error("failed to start geth metrics server", "err", err) + return err + } + return nil + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..819063d72 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "evm", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/precompiles/bank/bank.go b/precompiles/bank/bank.go index c3538204d..ca1f492c6 100644 --- a/precompiles/bank/bank.go +++ b/precompiles/bank/bank.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" cmn "github.com/cosmos/evm/precompiles/common" - erc20keeper "github.com/cosmos/evm/x/erc20/keeper" evmtypes "github.com/cosmos/evm/x/vm/types" storetypes "cosmossdk.io/store/types" @@ -43,14 +42,14 @@ var f embed.FS type Precompile struct { cmn.Precompile bankKeeper cmn.BankKeeper - erc20Keeper erc20keeper.Keeper + erc20Keeper cmn.ERC20Keeper } // NewPrecompile creates a new bank Precompile instance implementing the // PrecompiledContract interface. func NewPrecompile( bankKeeper cmn.BankKeeper, - erc20Keeper erc20keeper.Keeper, + erc20Keeper cmn.ERC20Keeper, ) (*Precompile, error) { newABI, err := cmn.LoadABI(f, "abi.json") if err != nil { diff --git a/precompiles/common/balance_handler_test.go b/precompiles/common/balance_handler_test.go index 1466e97aa..c0ea5fe0b 100644 --- a/precompiles/common/balance_handler_test.go +++ b/precompiles/common/balance_handler_test.go @@ -149,7 +149,7 @@ func TestAfterBalanceChange(t *testing.T) { tKey := storetypes.NewTransientStoreKey("test_t") ctx := sdktestutil.DefaultContext(storeKey, tKey) - stateDB := statedb.New(ctx, mocks.NewEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) + stateDB := statedb.New(ctx, mocks.NewEVMKeeper(), statedb.NewEmptyTxConfig()) _, addrs, err := testutil.GeneratePrivKeyAddressPairs(2) require.NoError(t, err) @@ -191,7 +191,7 @@ func TestAfterBalanceChangeErrors(t *testing.T) { storeKey := storetypes.NewKVStoreKey("test") tKey := storetypes.NewTransientStoreKey("test_t") ctx := sdktestutil.DefaultContext(storeKey, tKey) - stateDB := statedb.New(ctx, mocks.NewEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) + stateDB := statedb.New(ctx, mocks.NewEVMKeeper(), statedb.NewEmptyTxConfig()) _, addrs, err := testutil.GeneratePrivKeyAddressPairs(1) require.NoError(t, err) diff --git a/precompiles/common/interfaces.go b/precompiles/common/interfaces.go index 2993bfd45..56ef41eab 100644 --- a/precompiles/common/interfaces.go +++ b/precompiles/common/interfaces.go @@ -3,8 +3,17 @@ package common import ( "context" + ethcommon "github.com/ethereum/go-ethereum/common" + + erc20types "github.com/cosmos/evm/x/erc20/types" + ibctypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + connectiontypes "github.com/cosmos/ibc-go/v10/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" + sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) type BankKeeper interface { @@ -17,4 +26,42 @@ type BankKeeper interface { SendCoins(ctx context.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error SpendableCoin(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin BlockedAddr(addr sdk.AccAddress) bool + MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error +} + +type TransferKeeper interface { + Denom(ctx context.Context, req *ibctypes.QueryDenomRequest) (*ibctypes.QueryDenomResponse, error) + Denoms(ctx context.Context, req *ibctypes.QueryDenomsRequest) (*ibctypes.QueryDenomsResponse, error) + DenomHash(ctx context.Context, req *ibctypes.QueryDenomHashRequest) (*ibctypes.QueryDenomHashResponse, error) + Transfer(ctx context.Context, msg *ibctypes.MsgTransfer) (*ibctypes.MsgTransferResponse, error) +} + +type ChannelKeeper interface { + GetChannel(ctx sdk.Context, portID, channelID string) (channeltypes.Channel, bool) + GetConnection(ctx sdk.Context, connectionID string) (connectiontypes.ConnectionEnd, error) +} + +type DistributionKeeper interface { + WithdrawDelegationRewards(ctx context.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (sdk.Coins, error) +} + +type StakingKeeper interface { + BondDenom(ctx context.Context) (string, error) + MaxValidators(ctx context.Context) (uint32, error) + GetDelegatorValidators(ctx context.Context, delegatorAddr sdk.AccAddress, maxRetrieve uint32) (stakingtypes.Validators, error) + GetRedelegation(ctx context.Context, delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) (red stakingtypes.Redelegation, err error) + GetValidator(ctx context.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, err error) +} + +type SlashingKeeper interface { + Params(ctx context.Context, req *slashingtypes.QueryParamsRequest) (*slashingtypes.QueryParamsResponse, error) + SigningInfo(ctx context.Context, req *slashingtypes.QuerySigningInfoRequest) (*slashingtypes.QuerySigningInfoResponse, error) + SigningInfos(ctx context.Context, req *slashingtypes.QuerySigningInfosRequest) (*slashingtypes.QuerySigningInfosResponse, error) +} + +type ERC20Keeper interface { + GetCoinAddress(ctx sdk.Context, denom string) (ethcommon.Address, error) + GetERC20Map(ctx sdk.Context, erc20 ethcommon.Address) []byte + GetTokenPair(ctx sdk.Context, id []byte) (erc20types.TokenPair, bool) } diff --git a/precompiles/common/mocks/BankKeeper.go b/precompiles/common/mocks/BankKeeper.go index a3c72593c..2ad57e099 100644 --- a/precompiles/common/mocks/BankKeeper.go +++ b/precompiles/common/mocks/BankKeeper.go @@ -150,12 +150,49 @@ func (_m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, return r0 } +// MintCoins provides a mock function with given fields: ctx, moduleName, amt +func (_m *BankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { + ret := _m.Called(ctx, moduleName, amt) + + if len(ret) == 0 { + panic("no return value specified for MintCoins") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, types.Coins) error); ok { + r0 = rf(ctx, moduleName, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SendCoinsFromModuleToAccount provides a mock function with given fields: ctx, senderModule, recipientAddr, amt +func (_m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + ret := _m.Called(ctx, senderModule, recipientAddr, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromModuleToAccount") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, types.AccAddress, types.Coins) error); ok { + r0 = rf(ctx, senderModule, recipientAddr, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // NewBankKeeper creates a new instance of BankKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewBankKeeper(t interface { mock.TestingT Cleanup(func()) -}) *BankKeeper { +}, +) *BankKeeper { mock := &BankKeeper{} mock.Mock.Test(t) diff --git a/precompiles/common/precompile.go b/precompiles/common/precompile.go index a1fb80668..d095e9704 100644 --- a/precompiles/common/precompile.go +++ b/precompiles/common/precompile.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" - "github.com/holiman/uint256" "github.com/cosmos/evm/x/vm/statedb" @@ -35,16 +34,6 @@ const ( Add ) -type BalanceChangeEntry struct { - Account common.Address - Amount *uint256.Int - Op Operation -} - -func NewBalanceChangeEntry(acc common.Address, amt *uint256.Int, op Operation) BalanceChangeEntry { - return BalanceChangeEntry{acc, amt, op} -} - // RequiredGas calculates the base minimum required gas for a transaction or a query. // It uses the method ID to determine if the input is a transaction or a query and // uses the Cosmos SDK gas config flat cost and the flat per byte cost * len(argBz) to calculate the gas. @@ -84,7 +73,7 @@ func (p Precompile) RunSetup( // add precompileCall entry on the stateDB journal // this allows to revert the changes within an evm tx - err = stateDB.AddPrecompileFn(p.Address(), snapshot, events) + err = stateDB.AddPrecompileFn(snapshot, events) if err != nil { return sdk.Context{}, nil, nil, uint64(0), nil, err } diff --git a/precompiles/distribution/distribution.go b/precompiles/distribution/distribution.go index 076ce0021..7457412f5 100644 --- a/precompiles/distribution/distribution.go +++ b/precompiles/distribution/distribution.go @@ -15,8 +15,7 @@ import ( "cosmossdk.io/core/address" storetypes "cosmossdk.io/store/types" - distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" ) var _ vm.PrecompiledContract = &Precompile{} @@ -29,16 +28,20 @@ var f embed.FS // Precompile defines the precompiled contract for distribution. type Precompile struct { cmn.Precompile - distributionKeeper distributionkeeper.Keeper - stakingKeeper stakingkeeper.Keeper - addrCdc address.Codec + distributionKeeper cmn.DistributionKeeper + distributionMsgServer distributiontypes.MsgServer + distributionQuerier distributiontypes.QueryServer + stakingKeeper cmn.StakingKeeper + addrCdc address.Codec } // NewPrecompile creates a new distribution Precompile instance as a // PrecompiledContract interface. func NewPrecompile( - distributionKeeper distributionkeeper.Keeper, - stakingKeeper stakingkeeper.Keeper, + distributionKeeper cmn.DistributionKeeper, + distributionMsgServer distributiontypes.MsgServer, + distributionQuerier distributiontypes.QueryServer, + stakingKeeper cmn.StakingKeeper, bankKeeper cmn.BankKeeper, addrCdc address.Codec, ) (*Precompile, error) { @@ -53,9 +56,11 @@ func NewPrecompile( KvGasConfig: storetypes.KVGasConfig(), TransientKVGasConfig: storetypes.TransientGasConfig(), }, - stakingKeeper: stakingKeeper, - distributionKeeper: distributionKeeper, - addrCdc: addrCdc, + stakingKeeper: stakingKeeper, + distributionKeeper: distributionKeeper, + distributionMsgServer: distributionMsgServer, + distributionQuerier: distributionQuerier, + addrCdc: addrCdc, } // SetAddress defines the address of the distribution compile contract. diff --git a/precompiles/distribution/query.go b/precompiles/distribution/query.go index 4183a58bb..0c80e5175 100644 --- a/precompiles/distribution/query.go +++ b/precompiles/distribution/query.go @@ -7,7 +7,6 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" ) const ( @@ -52,9 +51,7 @@ func (p Precompile) ValidatorDistributionInfo( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.ValidatorDistributionInfo(ctx, req) + res, err := p.distributionQuerier.ValidatorDistributionInfo(ctx, req) if err != nil { return nil, err } @@ -76,9 +73,7 @@ func (p Precompile) ValidatorOutstandingRewards( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.ValidatorOutstandingRewards(ctx, req) + res, err := p.distributionQuerier.ValidatorOutstandingRewards(ctx, req) if err != nil { return nil, err } @@ -98,9 +93,7 @@ func (p Precompile) ValidatorCommission( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.ValidatorCommission(ctx, req) + res, err := p.distributionQuerier.ValidatorCommission(ctx, req) if err != nil { return nil, err } @@ -120,9 +113,7 @@ func (p Precompile) ValidatorSlashes( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.ValidatorSlashes(ctx, req) + res, err := p.distributionQuerier.ValidatorSlashes(ctx, req) if err != nil { return nil, err } @@ -144,8 +135,7 @@ func (p Precompile) DelegationRewards( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - res, err := querier.DelegationRewards(ctx, req) + res, err := p.distributionQuerier.DelegationRewards(ctx, req) if err != nil { return nil, err } @@ -165,9 +155,7 @@ func (p Precompile) DelegationTotalRewards( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.DelegationTotalRewards(ctx, req) + res, err := p.distributionQuerier.DelegationTotalRewards(ctx, req) if err != nil { return nil, err } @@ -189,9 +177,7 @@ func (p Precompile) DelegatorValidators( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.DelegatorValidators(ctx, req) + res, err := p.distributionQuerier.DelegatorValidators(ctx, req) if err != nil { return nil, err } @@ -211,9 +197,7 @@ func (p Precompile) DelegatorWithdrawAddress( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.DelegatorWithdrawAddress(ctx, req) + res, err := p.distributionQuerier.DelegatorWithdrawAddress(ctx, req) if err != nil { return nil, err } @@ -233,9 +217,7 @@ func (p Precompile) CommunityPool( return nil, err } - querier := distributionkeeper.Querier{Keeper: p.distributionKeeper} - - res, err := querier.CommunityPool(ctx, req) + res, err := p.distributionQuerier.CommunityPool(ctx, req) if err != nil { return nil, err } diff --git a/precompiles/distribution/tx.go b/precompiles/distribution/tx.go index 679ae199b..3dea64f02 100644 --- a/precompiles/distribution/tx.go +++ b/precompiles/distribution/tx.go @@ -9,7 +9,6 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" ) const ( @@ -103,8 +102,7 @@ func (p Precompile) SetWithdrawAddress( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), delegatorHexAddr.String()) } - msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper) - if _, err = msgSrv.SetWithdrawAddress(ctx, msg); err != nil { + if _, err = p.distributionMsgServer.SetWithdrawAddress(ctx, msg); err != nil { return nil, err } @@ -133,8 +131,7 @@ func (p *Precompile) WithdrawDelegatorReward( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), delegatorHexAddr.String()) } - msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper) - res, err := msgSrv.WithdrawDelegatorReward(ctx, msg) + res, err := p.distributionMsgServer.WithdrawDelegatorReward(ctx, msg) if err != nil { return nil, err } @@ -164,8 +161,7 @@ func (p *Precompile) WithdrawValidatorCommission( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), validatorHexAddr.String()) } - msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper) - res, err := msgSrv.WithdrawValidatorCommission(ctx, msg) + res, err := p.distributionMsgServer.WithdrawValidatorCommission(ctx, msg) if err != nil { return nil, err } @@ -195,8 +191,7 @@ func (p *Precompile) FundCommunityPool( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), depositorHexAddr.String()) } - msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper) - _, err = msgSrv.FundCommunityPool(ctx, msg) + _, err = p.distributionMsgServer.FundCommunityPool(ctx, msg) if err != nil { return nil, err } @@ -227,8 +222,7 @@ func (p *Precompile) DepositValidatorRewardsPool( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), depositorHexAddr.String()) } - msgSrv := distributionkeeper.NewMsgServerImpl(p.distributionKeeper) - _, err = msgSrv.DepositValidatorRewardsPool(ctx, msg) + _, err = p.distributionMsgServer.DepositValidatorRewardsPool(ctx, msg) if err != nil { return nil, err } diff --git a/precompiles/erc20/erc20.go b/precompiles/erc20/erc20.go index 9ac290cd3..7a1575f5f 100644 --- a/precompiles/erc20/erc20.go +++ b/precompiles/erc20/erc20.go @@ -8,9 +8,9 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" + ibcutils "github.com/cosmos/evm/ibc" cmn "github.com/cosmos/evm/precompiles/common" erc20types "github.com/cosmos/evm/x/erc20/types" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" storetypes "cosmossdk.io/store/types" @@ -50,28 +50,30 @@ var _ vm.PrecompiledContract = &Precompile{} type Precompile struct { cmn.Precompile tokenPair erc20types.TokenPair - transferKeeper transferkeeper.Keeper + transferKeeper ibcutils.TransferKeeper erc20Keeper Erc20Keeper // BankKeeper is a public field so that the werc20 precompile can use it. BankKeeper cmn.BankKeeper } +// LoadABI loads the IERC20Metadata ABI from the embedded abi.json file +// for the erc20 precompile. +func LoadABI() (abi.ABI, error) { + return cmn.LoadABI(f, abiPath) +} + // NewPrecompile creates a new ERC-20 Precompile instance as a // PrecompiledContract interface. func NewPrecompile( tokenPair erc20types.TokenPair, bankKeeper cmn.BankKeeper, erc20Keeper Erc20Keeper, - transferKeeper transferkeeper.Keeper, + transferKeeper ibcutils.TransferKeeper, + erc20ABI abi.ABI, ) (*Precompile, error) { - newABI, err := cmn.LoadABI(f, abiPath) - if err != nil { - return nil, err - } - p := &Precompile{ Precompile: cmn.Precompile{ - ABI: newABI, + ABI: erc20ABI, KvGasConfig: storetypes.GasConfig{}, TransientKVGasConfig: storetypes.GasConfig{}, }, diff --git a/precompiles/erc20/msgsrv.go b/precompiles/erc20/msgsrv.go index 611e8e6f6..00ba92234 100644 --- a/precompiles/erc20/msgsrv.go +++ b/precompiles/erc20/msgsrv.go @@ -26,19 +26,28 @@ func NewMsgServerImpl(keeper cmn.BankKeeper) *MsgServer { func (m MsgServer) Send(goCtx context.Context, msg *banktypes.MsgSend) error { switch keeper := m.BankKeeper.(type) { // have cases for both pointer and non-pointer to cover how different apps could be storing the keeper - case *bankkeeper.BaseKeeper: case bankkeeper.BaseKeeper: msgSrv := bankkeeper.NewMsgServerImpl(keeper) if _, err := msgSrv.Send(goCtx, msg); err != nil { // This should return an error to avoid the contract from being executed and an event being emitted return ConvertErrToERC20Error(err) } - case *precisebankkeeper.Keeper: + case *bankkeeper.BaseKeeper: + msgSrv := bankkeeper.NewMsgServerImpl(keeper) + if _, err := msgSrv.Send(goCtx, msg); err != nil { + // This should return an error to avoid the contract from being executed and an event being emitted + return ConvertErrToERC20Error(err) + } case precisebankkeeper.Keeper: if _, err := keeper.Send(goCtx, msg); err != nil { // This should return an error to avoid the contract from being executed and an event being emitted return ConvertErrToERC20Error(err) } + case *precisebankkeeper.Keeper: + if _, err := keeper.Send(goCtx, msg); err != nil { + // This should return an error to avoid the contract from being executed and an event being emitted + return ConvertErrToERC20Error(err) + } default: return sdkerrors.ErrInvalidRequest.Wrapf("invalid keeper type: %T", m.BankKeeper) } diff --git a/precompiles/erc20factory/IERC20Factory.sol b/precompiles/erc20factory/IERC20Factory.sol new file mode 100644 index 000000000..55e840968 --- /dev/null +++ b/precompiles/erc20factory/IERC20Factory.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.17; + +/** + * @dev The ERC20 Factory contract's address. + */ +address constant ERC20_FACTORY_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000900; + +/** + * @dev The ERC20 Factory contract's instance. + */ +IERC20Factory constant ERC20_FACTORY_CONTRACT = IERC20Factory(ERC20_FACTORY_PRECOMPILE_ADDRESS); + +interface IERC20Factory { + /** + * @dev Emitted when a new ERC20 token is created. + * @param tokenAddress The address of the ERC20 token. + * @param salt The salt used for deployment. + * @param name The name of the token. + * @param symbol The symbol of the token. + * @param decimals The decimals of the token. + */ + event Create( + address indexed tokenAddress, + bytes32 salt, + string name, + string symbol, + uint8 decimals, + address minter, + uint256 premintedSupply + ); + + /** + * @dev Defines a method for creating an ERC20 token. + * @param salt Salt used for deployment + * @param name The name of the token. + * @param symbol The symbol of the token. + * @param decimals the decimals of the token. + * @return tokenAddress The ERC20 token address. + */ + function create( + bytes32 salt, + string memory name, + string memory symbol, + uint8 decimals, + address minter, + uint256 premintedSupply + ) external returns (address tokenAddress); + + /** + * @dev Calculates the deterministic address for a new token. + * @param salt Salt used for deployment + * @return tokenAddress The calculated ERC20 token address. + */ + function calculateAddress(bytes32 salt) external view returns (address tokenAddress); +} \ No newline at end of file diff --git a/precompiles/erc20factory/abi.json b/precompiles/erc20factory/abi.json new file mode 100644 index 000000000..4ff56cdd6 --- /dev/null +++ b/precompiles/erc20factory/abi.json @@ -0,0 +1,123 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IERC20Factory", + "sourceName": "solidity/precompiles/erc20factory/IERC20Factory.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "premintedSupply", + "type": "uint256" + } + ], + "name": "Create", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + } + ], + "name": "calculateAddress", + "outputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "premintedSupply", + "type": "uint256" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/precompiles/erc20factory/erc20factory.go b/precompiles/erc20factory/erc20factory.go new file mode 100644 index 000000000..fb93dd4d3 --- /dev/null +++ b/precompiles/erc20factory/erc20factory.go @@ -0,0 +1,163 @@ +package erc20factory + +import ( + "embed" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/vm" + + cmn "github.com/cosmos/evm/precompiles/common" + + storetypes "cosmossdk.io/store/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + Erc20FactoryAddress = "0x0000000000000000000000000000000000000900" + // GasCreate defines the gas required to create a new ERC20 Token Pair calculated from a ERC20 deploy transaction + GasCreate = 3_000_000 + // GasCalculateAddress defines the gas required to calculate the address of a new ERC20 Token Pair + GasCalculateAddress = 3_000 +) + +var _ vm.PrecompiledContract = &Precompile{} + +// Embed abi json file to the executable binary. Needed when importing as dependency. +// +//go:embed abi.json +var f embed.FS + +// Precompile defines the precompiled contract for Bech32 encoding. +type Precompile struct { + cmn.Precompile + erc20Keeper ERC20Keeper + bankKeeper BankKeeper + evmKeeper EvmKeeper +} + +// NewPrecompile creates a new bech32 Precompile instance as a +// PrecompiledContract interface. +func NewPrecompile(erc20Keeper ERC20Keeper, bankKeeper cmn.BankKeeper, keeper EvmKeeper) (*Precompile, error) { + newABI, err := cmn.LoadABI(f, "abi.json") + if err != nil { + return nil, err + } + + p := &Precompile{ + Precompile: cmn.Precompile{ + ABI: newABI, + KvGasConfig: storetypes.KVGasConfig(), + TransientKVGasConfig: storetypes.TransientGasConfig(), + }, + erc20Keeper: erc20Keeper, + bankKeeper: bankKeeper, + evmKeeper: keeper, + } + + // SetAddress defines the address of the distribution compile contract. + p.SetAddress(common.HexToAddress(Erc20FactoryAddress)) + + p.SetBalanceHandler(bankKeeper) + return p, nil +} + +// Address defines the address of the bech32 precompiled contract. +func (Precompile) Address() common.Address { + return common.HexToAddress(Erc20FactoryAddress) +} + +// RequiredGas calculates the contract gas use. +func (p Precompile) RequiredGas(input []byte) uint64 { + // NOTE: This check avoid panicking when trying to decode the method ID + if len(input) < 4 { + return 0 + } + + methodID := input[:4] + method, err := p.MethodById(methodID) + if err != nil { + return 0 + } + + switch method.Name { + // ERC-20 transactions + case CreateMethod: + return GasCreate + case CalculateAddressMethod: + return GasCalculateAddress + default: + return 0 + } +} + +// Run executes the precompiled contract bech32 methods defined in the ABI. +func (p Precompile) Run(evm *vm.EVM, contract *vm.Contract, readOnly bool) (bz []byte, err error) { + ctx, stateDB, method, initialGas, args, err := p.RunSetup(evm, contract, readOnly, p.IsTransaction) + if err != nil { + return nil, err + } + + // Start the balance change handler before executing the precompile + p.GetBalanceHandler().BeforeBalanceChange(ctx) + + // This handles any out of gas errors that may occur during the execution of a precompile query. + // It avoids panics and returns the out of gas error so the EVM can continue gracefully. + defer cmn.HandleGasError(ctx, contract, initialGas, &err)() + + bz, err = p.HandleMethod(ctx, contract, stateDB, method, args) + if err != nil { + return nil, err + } + + cost := ctx.GasMeter().GasConsumed() - initialGas + + if !contract.UseGas(cost, nil, tracing.GasChangeCallPrecompiledContract) { + return nil, vm.ErrOutOfGas + } + + // Process the native balance changes after the method execution. + err = p.GetBalanceHandler().AfterBalanceChange(ctx, stateDB) + if err != nil { + return nil, err + } + + return bz, nil +} + +// IsTransaction checks if the given method name corresponds to a transaction or query. +// +// Available ERC20 Factory transactions are: +// - Create +func (Precompile) IsTransaction(method *abi.Method) bool { + switch method.Name { + case CreateMethod: + return true + default: + return false + } +} + +// HandleMethod handles the execution of each of the ERC-20 Factory methods. +func (p *Precompile) HandleMethod( + ctx sdk.Context, + contract *vm.Contract, + stateDB vm.StateDB, + method *abi.Method, + args []interface{}, +) (bz []byte, err error) { + switch method.Name { + // ERC-20 Factory transactions + case CreateMethod: + bz, err = p.Create(ctx, stateDB, method, contract.Caller(), args) + // ERC-20 Factory queries + case CalculateAddressMethod: + bz, err = p.CalculateAddress(method, contract.Caller(), args) + default: + return nil, fmt.Errorf(cmn.ErrUnknownMethod, method.Name) + } + return bz, err +} diff --git a/precompiles/erc20factory/events.go b/precompiles/erc20factory/events.go new file mode 100644 index 000000000..2f778b772 --- /dev/null +++ b/precompiles/erc20factory/events.go @@ -0,0 +1,56 @@ +package erc20factory + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + + cmn "github.com/cosmos/evm/precompiles/common" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // EventTypeCreate is the event type for the Create event. + EventTypeCreate = "Create" +) + +// EmitCreateEvent emits the Create event. +func (p Precompile) EmitCreateEvent(ctx sdk.Context, stateDB vm.StateDB, tokenAddress common.Address, salt [32]uint8, name string, symbol string, decimals uint8, minter common.Address, premintedSupply *big.Int) error { + event := p.Events[EventTypeCreate] + topics := make([]common.Hash, 2) // Only 2 topics: event ID + tokenAddress + + topics[0] = event.ID + + var err error + topics[1], err = cmn.MakeTopic(tokenAddress) + if err != nil { + return err + } + + // Pack the non-indexed event parameters into the data field + arguments := abi.Arguments{ + event.Inputs[1], // salt + event.Inputs[2], // name + event.Inputs[3], // symbol + event.Inputs[4], // decimals + event.Inputs[5], // minter + event.Inputs[6], // premintedSupply + } + packed, err := arguments.Pack(salt, name, symbol, decimals, minter, premintedSupply) + if err != nil { + return err + } + + stateDB.AddLog(ðtypes.Log{ + Address: p.Address(), + Topics: topics, + Data: packed, + BlockNumber: uint64(ctx.BlockHeight()), //nolint:gosec // G115 // block height won't exceed uint64 + }) + + return nil +} diff --git a/precompiles/erc20factory/interfaces.go b/precompiles/erc20factory/interfaces.go new file mode 100644 index 000000000..0e80185f3 --- /dev/null +++ b/precompiles/erc20factory/interfaces.go @@ -0,0 +1,29 @@ +package erc20factory + +import ( + "context" + + "github.com/ethereum/go-ethereum/common" + + erc20types "github.com/cosmos/evm/x/erc20/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +type ERC20Keeper interface { + SetToken(ctx sdk.Context, token erc20types.TokenPair) error + EnableDynamicPrecompile(ctx sdk.Context, address common.Address) error + IsDenomRegistered(ctx sdk.Context, denom string) bool +} + +type BankKeeper interface { + GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) + SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) + MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error +} + +type EvmKeeper interface { + GetCodeHash(ctx sdk.Context, addr common.Address) common.Hash +} diff --git a/precompiles/erc20factory/query.go b/precompiles/erc20factory/query.go new file mode 100644 index 000000000..221841236 --- /dev/null +++ b/precompiles/erc20factory/query.go @@ -0,0 +1,29 @@ +package erc20factory + +import ( + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +const ( + // CalculateAddressMethod defines the ABI method name for the CalculateAddress + // query. + CalculateAddressMethod = "calculateAddress" +) + +// CalculateAddress calculates the address of a new ERC20 Token Pair +func (p Precompile) CalculateAddress( + method *abi.Method, + caller common.Address, + args []interface{}, +) ([]byte, error) { + salt, err := ParseCalculateAddressArgs(args) + if err != nil { + return nil, err + } + + address := crypto.CreateAddress2(caller, salt, []byte{}) + + return method.Outputs.Pack(address) +} diff --git a/precompiles/erc20factory/tx.go b/precompiles/erc20factory/tx.go new file mode 100644 index 000000000..d42386362 --- /dev/null +++ b/precompiles/erc20factory/tx.go @@ -0,0 +1,144 @@ +// Copyright Tharsis Labs Ltd.(Evmos) +// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) + +package erc20factory + +import ( + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + + erc20types "github.com/cosmos/evm/x/erc20/types" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "cosmossdk.io/errors" + "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +const ( + // CreateMethod defines the ABI method name to create a new ERC20 Token Pair + CreateMethod = "create" +) + +// Create CreateERC20Precompile creates a new ERC20 TokenPair +func (p Precompile) Create( + ctx sdk.Context, + stateDB vm.StateDB, + method *abi.Method, + caller common.Address, + args []interface{}, +) ([]byte, error) { + salt, name, symbol, decimals, minter, premintedSupply, err := ParseCreateArgs(args) + if err != nil { + return nil, err + } + + address := crypto.CreateAddress2(caller, salt, []byte{}) + + hash := p.evmKeeper.GetCodeHash(ctx, address) + if hash.Cmp(common.BytesToHash(evmtypes.EmptyCodeHash)) != 0 { + return nil, errors.Wrapf( + erc20types.ErrContractAlreadyExists, + "contract already exists at address %s", address.String(), + ) + } + + metadata, err := p.createCoinMetadata(ctx, address, name, symbol, decimals) + if err != nil { + return nil, errors.Wrap( + err, "failed to create wrapped coin denom metadata for ERC20", + ) + } + + if err := metadata.Validate(); err != nil { + return nil, errors.Wrapf( + err, "ERC20 token data is invalid for contract %s", address.String(), + ) + } + + p.bankKeeper.SetDenomMetaData(ctx, *metadata) + + pair := erc20types.NewTokenPair(address, metadata.Name, erc20types.OWNER_EXTERNAL) + + err = p.erc20Keeper.SetToken(ctx, pair) + if err != nil { + return nil, err + } + + err = p.erc20Keeper.EnableDynamicPrecompile(ctx, pair.GetERC20Contract()) + if err != nil { + return nil, err + } + + coins := sdk.NewCoins(sdk.NewCoin(metadata.Base, math.NewIntFromBigInt(premintedSupply))) + if err := p.bankKeeper.MintCoins(ctx, erc20types.ModuleName, coins); err != nil { + return nil, err + } + if err := p.bankKeeper.SendCoinsFromModuleToAccount(ctx, erc20types.ModuleName, sdk.AccAddress(minter.Bytes()), coins); err != nil { + return nil, err + } + + if err = p.EmitCreateEvent(ctx, stateDB, address, salt, name, symbol, decimals, minter, premintedSupply); err != nil { + return nil, err + } + + return method.Outputs.Pack(address) +} + +func (p Precompile) createCoinMetadata(ctx sdk.Context, address common.Address, name string, symbol string, decimals uint8) (*banktypes.Metadata, error) { + addressString := address.String() + denom := erc20types.CreateDenom(addressString) + + _, found := p.bankKeeper.GetDenomMetaData(ctx, denom) + if found { + return nil, errors.Wrap( + erc20types.ErrInternalTokenPair, "denom metadata already registered", + ) + } + + if p.erc20Keeper.IsDenomRegistered(ctx, denom) { + return nil, errors.Wrapf( + erc20types.ErrInternalTokenPair, "coin denomination already registered: %s", name, + ) + } + + // base denomination + base := erc20types.CreateDenom(addressString) + + // create a bank denom metadata based on the ERC20 token ABI details + // metadata name is should always be the contract since it's the key + // to the bank store + metadata := banktypes.Metadata{ + Description: erc20types.CreateDenomDescription(addressString), + Base: base, + // NOTE: Denom units MUST be increasing + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: base, + Exponent: 0, + }, + }, + Name: base, + Symbol: symbol, + Display: base, + } + + // only append metadata if decimals > 0, otherwise validation fails + if decimals > 0 { + nameSanitized := erc20types.SanitizeERC20Name(name) + metadata.DenomUnits = append( + metadata.DenomUnits, + &banktypes.DenomUnit{ + Denom: nameSanitized, + Exponent: uint32(decimals), //#nosec G115 + }, + ) + metadata.Display = nameSanitized + } + + return &metadata, nil +} diff --git a/precompiles/erc20factory/types.go b/precompiles/erc20factory/types.go new file mode 100644 index 000000000..0feaba006 --- /dev/null +++ b/precompiles/erc20factory/types.go @@ -0,0 +1,91 @@ +package erc20factory + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + cmn "github.com/cosmos/evm/precompiles/common" +) + +// EventCreate defines the event data for the ERC20 Factory Create event. +type EventCreate struct { + TokenAddress common.Address + TokenPairType uint8 + Salt [32]uint8 + Name string + Symbol string + Decimals uint8 + Minter common.Address + PremintedSupply *big.Int +} + +// ParseCreateArgs parses the arguments from the create method and returns +// the token type, salt, name, symbol, decimals, minter, and preminted supply. +func ParseCreateArgs(args []interface{}) (salt [32]uint8, name string, symbol string, decimals uint8, minter common.Address, premintedSupply *big.Int, err error) { + if len(args) != 6 { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 7, len(args)) + } + + salt, ok := args[0].([32]uint8) + if !ok { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid salt") + } + + name, ok = args[1].(string) + if !ok || len(name) < 3 || len(name) > 128 { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid name") + } + + symbol, ok = args[2].(string) + if !ok || len(symbol) < 1 || len(symbol) > 16 { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid symbol") + } + + decimals, ok = args[3].(uint8) + if !ok { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid decimals") + } + + minter, ok = args[4].(common.Address) + if !ok { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid minter") + } + + // Validate that minter is not the zero address + if minter == (common.Address{}) { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid minter: cannot be zero address") + } + + premintedSupply, ok = args[5].(*big.Int) + if !ok { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid premintedSupply: expected *big.Int") + } + + if premintedSupply.Sign() < 0 { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("invalid premintedSupply: cannot be negative") + } + + maxUint256 := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) + if premintedSupply.Cmp(maxUint256) > 0 { + return [32]uint8{}, "", "", uint8(0), common.Address{}, nil, fmt.Errorf("premintedSupply exceeds uint256 maximum") + } + + return salt, name, symbol, decimals, minter, premintedSupply, nil +} + +// ParseCalculateAddressArgs parses the arguments from the calculateAddress method and returns +// the token type and salt. +func ParseCalculateAddressArgs(args []interface{}) (salt [32]uint8, err error) { + if len(args) != 1 { + return [32]uint8{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 2, len(args)) + } + + salt, ok := args[0].([32]uint8) + if !ok { + return [32]uint8{}, fmt.Errorf("invalid salt") + } + + return salt, nil +} diff --git a/precompiles/gov/gov.go b/precompiles/gov/gov.go index ca1aeada8..619c1e9be 100644 --- a/precompiles/gov/gov.go +++ b/precompiles/gov/gov.go @@ -18,7 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1" ) var _ vm.PrecompiledContract = &Precompile{} @@ -31,9 +31,10 @@ var f embed.FS // Precompile defines the precompiled contract for gov. type Precompile struct { cmn.Precompile - govKeeper govkeeper.Keeper - codec codec.Codec - addrCdc address.Codec + govMsgServer govtypes.MsgServer + govQuerier govtypes.QueryServer + codec codec.Codec + addrCdc address.Codec } // LoadABI loads the gov ABI from the embedded abi.json file @@ -45,7 +46,8 @@ func LoadABI() (abi.ABI, error) { // NewPrecompile creates a new gov Precompile instance as a // PrecompiledContract interface. func NewPrecompile( - govKeeper govkeeper.Keeper, + govMsgServer govtypes.MsgServer, + govQuerier govtypes.QueryServer, bankKeeper cmn.BankKeeper, codec codec.Codec, addrCdc address.Codec, @@ -61,9 +63,10 @@ func NewPrecompile( KvGasConfig: storetypes.KVGasConfig(), TransientKVGasConfig: storetypes.TransientGasConfig(), }, - govKeeper: govKeeper, - codec: codec, - addrCdc: addrCdc, + govMsgServer: govMsgServer, + govQuerier: govQuerier, + codec: codec, + addrCdc: addrCdc, } // SetAddress defines the address of the gov precompiled contract. diff --git a/precompiles/gov/query.go b/precompiles/gov/query.go index 9a6df983a..0b389b9a0 100644 --- a/precompiles/gov/query.go +++ b/precompiles/gov/query.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" sdk "github.com/cosmos/cosmos-sdk/types" - govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" ) const ( @@ -41,8 +40,7 @@ func (p *Precompile) GetVotes( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Votes(ctx, queryVotesReq) + res, err := p.govQuerier.Votes(ctx, queryVotesReq) if err != nil { return nil, err } @@ -66,8 +64,7 @@ func (p *Precompile) GetVote( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Vote(ctx, queryVotesReq) + res, err := p.govQuerier.Vote(ctx, queryVotesReq) if err != nil { return nil, err } @@ -91,8 +88,7 @@ func (p *Precompile) GetDeposit( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Deposit(ctx, queryDepositReq) + res, err := p.govQuerier.Deposit(ctx, queryDepositReq) if err != nil { return nil, err } @@ -116,8 +112,7 @@ func (p *Precompile) GetDeposits( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Deposits(ctx, queryDepositsReq) + res, err := p.govQuerier.Deposits(ctx, queryDepositsReq) if err != nil { return nil, err } @@ -141,8 +136,7 @@ func (p *Precompile) GetTallyResult( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.TallyResult(ctx, queryTallyResultReq) + res, err := p.govQuerier.TallyResult(ctx, queryTallyResultReq) if err != nil { return nil, err } @@ -163,8 +157,7 @@ func (p *Precompile) GetProposal( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Proposal(ctx, queryProposalReq) + res, err := p.govQuerier.Proposal(ctx, queryProposalReq) if err != nil { return nil, err } @@ -188,8 +181,7 @@ func (p *Precompile) GetProposals( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Proposals(ctx, queryProposalsReq) + res, err := p.govQuerier.Proposals(ctx, queryProposalsReq) if err != nil { return nil, err } @@ -213,8 +205,7 @@ func (p *Precompile) GetParams( return nil, err } - queryServer := govkeeper.NewQueryServer(&p.govKeeper) - res, err := queryServer.Params(ctx, queryParamsReq) + res, err := p.govQuerier.Params(ctx, queryParamsReq) if err != nil { return nil, err } @@ -235,7 +226,7 @@ func (p *Precompile) GetConstitution( return nil, err } - res, err := govkeeper.NewQueryServer(&p.govKeeper).Constitution(ctx, req) + res, err := p.govQuerier.Constitution(ctx, req) if err != nil { return nil, err } diff --git a/precompiles/gov/tx.go b/precompiles/gov/tx.go index f9b6dea55..46569261b 100644 --- a/precompiles/gov/tx.go +++ b/precompiles/gov/tx.go @@ -9,7 +9,6 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" ) const ( @@ -43,7 +42,7 @@ func (p *Precompile) SubmitProposal( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), proposerHexAddr.String()) } - res, err := govkeeper.NewMsgServerImpl(&p.govKeeper).SubmitProposal(ctx, msg) + res, err := p.govMsgServer.SubmitProposal(ctx, msg) if err != nil { return nil, err } @@ -73,7 +72,7 @@ func (p *Precompile) Deposit( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), depositorHexAddr.String()) } - if _, err = govkeeper.NewMsgServerImpl(&p.govKeeper).Deposit(ctx, msg); err != nil { + if _, err = p.govMsgServer.Deposit(ctx, msg); err != nil { return nil, err } @@ -102,7 +101,7 @@ func (p *Precompile) CancelProposal( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), proposerHexAddr.String()) } - if _, err = govkeeper.NewMsgServerImpl(&p.govKeeper).CancelProposal(ctx, msg); err != nil { + if _, err = p.govMsgServer.CancelProposal(ctx, msg); err != nil { return nil, err } @@ -131,8 +130,7 @@ func (p Precompile) Vote( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), voterHexAddr.String()) } - msgSrv := govkeeper.NewMsgServerImpl(&p.govKeeper) - if _, err = msgSrv.Vote(ctx, msg); err != nil { + if _, err = p.govMsgServer.Vote(ctx, msg); err != nil { return nil, err } @@ -161,8 +159,7 @@ func (p Precompile) VoteWeighted( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), voterHexAddr.String()) } - msgSrv := govkeeper.NewMsgServerImpl(&p.govKeeper) - if _, err = msgSrv.VoteWeighted(ctx, msg); err != nil { + if _, err = p.govMsgServer.VoteWeighted(ctx, msg); err != nil { return nil, err } diff --git a/precompiles/ics20/ics20.go b/precompiles/ics20/ics20.go index 4ed33272e..73f8b177d 100644 --- a/precompiles/ics20/ics20.go +++ b/precompiles/ics20/ics20.go @@ -10,14 +10,9 @@ import ( "github.com/ethereum/go-ethereum/core/vm" cmn "github.com/cosmos/evm/precompiles/common" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - evmkeeper "github.com/cosmos/evm/x/vm/keeper" evmtypes "github.com/cosmos/evm/x/vm/types" - channelkeeper "github.com/cosmos/ibc-go/v10/modules/core/04-channel/keeper" storetypes "cosmossdk.io/store/types" - - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) // PrecompileAddress of the ICS-20 EVM extension in hex format. @@ -33,20 +28,18 @@ var f embed.FS type Precompile struct { cmn.Precompile bankKeeper cmn.BankKeeper - stakingKeeper stakingkeeper.Keeper - transferKeeper transferkeeper.Keeper - channelKeeper *channelkeeper.Keeper - evmKeeper *evmkeeper.Keeper + stakingKeeper cmn.StakingKeeper + transferKeeper cmn.TransferKeeper + channelKeeper cmn.ChannelKeeper } // NewPrecompile creates a new ICS-20 Precompile instance as a // PrecompiledContract interface. func NewPrecompile( bankKeeper cmn.BankKeeper, - stakingKeeper stakingkeeper.Keeper, - transferKeeper transferkeeper.Keeper, - channelKeeper *channelkeeper.Keeper, - evmKeeper *evmkeeper.Keeper, + stakingKeeper cmn.StakingKeeper, + transferKeeper cmn.TransferKeeper, + channelKeeper cmn.ChannelKeeper, ) (*Precompile, error) { newAbi, err := cmn.LoadABI(f, "abi.json") if err != nil { @@ -63,7 +56,6 @@ func NewPrecompile( transferKeeper: transferKeeper, channelKeeper: channelKeeper, stakingKeeper: stakingKeeper, - evmKeeper: evmKeeper, } // SetAddress defines the address of the ICS-20 compile contract. diff --git a/precompiles/slashing/slashing.go b/precompiles/slashing/slashing.go index 3a9c96950..f5287ce44 100644 --- a/precompiles/slashing/slashing.go +++ b/precompiles/slashing/slashing.go @@ -18,7 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/runtime" sdk "github.com/cosmos/cosmos-sdk/types" - slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" ) var _ vm.PrecompiledContract = &Precompile{} @@ -31,9 +31,10 @@ var f embed.FS // Precompile defines the precompiled contract for slashing. type Precompile struct { cmn.Precompile - slashingKeeper slashingkeeper.Keeper - consCodec runtime.ConsensusAddressCodec - valCodec runtime.ValidatorAddressCodec + slashingKeeper cmn.SlashingKeeper + slashingMsgServer slashingtypes.MsgServer + consCodec runtime.ConsensusAddressCodec + valCodec runtime.ValidatorAddressCodec } // LoadABI loads the slashing ABI from the embedded abi.json file @@ -45,7 +46,8 @@ func LoadABI() (abi.ABI, error) { // NewPrecompile creates a new slashing Precompile instance as a // PrecompiledContract interface. func NewPrecompile( - slashingKeeper slashingkeeper.Keeper, + slashingKeeper cmn.SlashingKeeper, + slashingMsgServer slashingtypes.MsgServer, bankKeeper cmn.BankKeeper, valCdc, consCdc address.Codec, ) (*Precompile, error) { @@ -60,9 +62,10 @@ func NewPrecompile( KvGasConfig: storetypes.KVGasConfig(), TransientKVGasConfig: storetypes.TransientGasConfig(), }, - slashingKeeper: slashingKeeper, - valCodec: valCdc, - consCodec: consCdc, + slashingKeeper: slashingKeeper, + slashingMsgServer: slashingMsgServer, + valCodec: valCdc, + consCodec: consCdc, } // SetAddress defines the address of the slashing precompiled contract. diff --git a/precompiles/slashing/tx.go b/precompiles/slashing/tx.go index 12e1103cd..abb21309b 100644 --- a/precompiles/slashing/tx.go +++ b/precompiles/slashing/tx.go @@ -10,7 +10,6 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) @@ -52,8 +51,7 @@ func (p Precompile) Unjail( ValidatorAddr: valAddr, } - msgSrv := slashingkeeper.NewMsgServerImpl(p.slashingKeeper) - if _, err := msgSrv.Unjail(ctx, msg); err != nil { + if _, err := p.slashingMsgServer.Unjail(ctx, msg); err != nil { return nil, err } diff --git a/precompiles/staking/query.go b/precompiles/staking/query.go index cf61a2c05..006627653 100644 --- a/precompiles/staking/query.go +++ b/precompiles/staking/query.go @@ -11,7 +11,6 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) const ( @@ -47,9 +46,7 @@ func (p Precompile) Delegation( return nil, err } - queryServer := stakingkeeper.Querier{Keeper: &p.stakingKeeper} - - res, err := queryServer.Delegation(ctx, req) + res, err := p.stakingQuerier.Delegation(ctx, req) if err != nil { // If there is no delegation found, return the response with zero values. if strings.Contains(err.Error(), fmt.Sprintf(ErrNoDelegationFound, req.DelegatorAddr, req.ValidatorAddr)) { @@ -81,9 +78,7 @@ func (p Precompile) UnbondingDelegation( return nil, err } - queryServer := stakingkeeper.Querier{Keeper: &p.stakingKeeper} - - res, err := queryServer.UnbondingDelegation(ctx, req) + res, err := p.stakingQuerier.UnbondingDelegation(ctx, req) if err != nil { // return empty unbonding delegation output if the unbonding delegation is not found expError := fmt.Sprintf("unbonding delegation with delegator %s not found for validator %s", req.DelegatorAddr, req.ValidatorAddr) @@ -110,9 +105,7 @@ func (p Precompile) Validator( return nil, err } - queryServer := stakingkeeper.Querier{Keeper: &p.stakingKeeper} - - res, err := queryServer.Validator(ctx, req) + res, err := p.stakingQuerier.Validator(ctx, req) if err != nil { // return empty validator info if the validator is not found expError := fmt.Sprintf("validator %s not found", req.ValidatorAddr) @@ -139,9 +132,7 @@ func (p Precompile) Validators( return nil, err } - queryServer := stakingkeeper.Querier{Keeper: &p.stakingKeeper} - - res, err := queryServer.Validators(ctx, req) + res, err := p.stakingQuerier.Validators(ctx, req) if err != nil { return nil, err } @@ -185,9 +176,7 @@ func (p Precompile) Redelegations( return nil, err } - queryServer := stakingkeeper.Querier{Keeper: &p.stakingKeeper} - - res, err := queryServer.Redelegations(ctx, req) + res, err := p.stakingQuerier.Redelegations(ctx, req) if err != nil { return nil, err } diff --git a/precompiles/staking/staking.go b/precompiles/staking/staking.go index 383e7ca6a..78aad51f1 100644 --- a/precompiles/staking/staking.go +++ b/precompiles/staking/staking.go @@ -16,7 +16,7 @@ import ( storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) var _ vm.PrecompiledContract = &Precompile{} @@ -29,8 +29,10 @@ var f embed.FS // Precompile defines the precompiled contract for staking. type Precompile struct { cmn.Precompile - stakingKeeper stakingkeeper.Keeper - addrCdc address.Codec + stakingKeeper cmn.StakingKeeper + stakingMsgServer stakingtypes.MsgServer + stakingQuerier stakingtypes.QueryServer + addrCdc address.Codec } // LoadABI loads the staking ABI from the embedded abi.json file @@ -42,7 +44,9 @@ func LoadABI() (abi.ABI, error) { // NewPrecompile creates a new staking Precompile instance as a // PrecompiledContract interface. func NewPrecompile( - stakingKeeper stakingkeeper.Keeper, + stakingKeeper cmn.StakingKeeper, + stakingMsgServer stakingtypes.MsgServer, + stakingQuerier stakingtypes.QueryServer, bankKeeper cmn.BankKeeper, addrCdc address.Codec, ) (*Precompile, error) { @@ -57,8 +61,10 @@ func NewPrecompile( KvGasConfig: storetypes.KVGasConfig(), TransientKVGasConfig: storetypes.TransientGasConfig(), }, - stakingKeeper: stakingKeeper, - addrCdc: addrCdc, + stakingKeeper: stakingKeeper, + stakingMsgServer: stakingMsgServer, + stakingQuerier: stakingQuerier, + addrCdc: addrCdc, } // SetAddress defines the address of the staking precompiled contract. p.SetAddress(common.HexToAddress(evmtypes.StakingPrecompileAddress)) diff --git a/precompiles/staking/tx.go b/precompiles/staking/tx.go index 2ce2c5465..a84a53052 100644 --- a/precompiles/staking/tx.go +++ b/precompiles/staking/tx.go @@ -10,7 +10,6 @@ import ( cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) const ( @@ -69,8 +68,7 @@ func (p Precompile) CreateValidator( } // Execute the transaction using the message server - msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper) - if _, err = msgSrv.CreateValidator(ctx, msg); err != nil { + if _, err = p.stakingMsgServer.CreateValidator(ctx, msg); err != nil { return nil, err } @@ -116,8 +114,7 @@ func (p Precompile) EditValidator( } // Execute the transaction using the message server - msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper) - if _, err = msgSrv.EditValidator(ctx, msg); err != nil { + if _, err = p.stakingMsgServer.EditValidator(ctx, msg); err != nil { return nil, err } @@ -163,8 +160,7 @@ func (p *Precompile) Delegate( } // Execute the transaction using the message server - msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper) - if _, err = msgSrv.Delegate(ctx, msg); err != nil { + if _, err = p.stakingMsgServer.Delegate(ctx, msg); err != nil { return nil, err } @@ -211,8 +207,7 @@ func (p Precompile) Undelegate( } // Execute the transaction using the message server - msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper) - res, err := msgSrv.Undelegate(ctx, msg) + res, err := p.stakingMsgServer.Undelegate(ctx, msg) if err != nil { return nil, err } @@ -261,8 +256,7 @@ func (p Precompile) Redelegate( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), delegatorHexAddr.String()) } - msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper) - res, err := msgSrv.BeginRedelegate(ctx, msg) + res, err := p.stakingMsgServer.BeginRedelegate(ctx, msg) if err != nil { return nil, err } @@ -310,8 +304,7 @@ func (p Precompile) CancelUnbondingDelegation( return nil, fmt.Errorf(cmn.ErrRequesterIsNotMsgSender, msgSender.String(), delegatorHexAddr.String()) } - msgSrv := stakingkeeper.NewMsgServerImpl(&p.stakingKeeper) - if _, err = msgSrv.CancelUnbondingDelegation(ctx, msg); err != nil { + if _, err = p.stakingMsgServer.CancelUnbondingDelegation(ctx, msg); err != nil { return nil, err } diff --git a/precompiles/testutil/contracts/StakingReverter.json b/precompiles/testutil/contracts/StakingReverter.json index 9b4bc012f..c0ae8d765 100644 --- a/precompiles/testutil/contracts/StakingReverter.json +++ b/precompiles/testutil/contracts/StakingReverter.json @@ -161,6 +161,29 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "outerTimes", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "innerTimes", + "type": "uint256" + }, + { + "internalType": "string", + "name": "validatorAddress", + "type": "string" + } + ], + "name": "nestedTryCatchDelegations", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -193,8 +216,8 @@ "type": "function" } ], - "bytecode": "0x6080604052600080556111b7806100176000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c80634e5a8fe51461006757806352fce7b114610083578063668f452b1461009f578063922a4b67146100d0578063cbc367d4146100ec578063f66013d71461011c575b600080fd5b610081600480360381019061007c919061072a565b610138565b005b61009d6004803603810190610098919061072a565b6101da565b005b6100b960048036038101906100b4919061078a565b610282565b6040516100c79291906108c2565b60405180910390f35b6100ea60048036038101906100e5919061072a565b61031c565b005b61010660048036038101906101019190610950565b6104b3565b6040516101139190610b3b565b60405180910390f35b6101366004803603810190610131919061078a565b610563565b005b60008081548092919061014a90610b8c565b919050555060005b838110156101d4573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610195929190610c21565b600060405180830381600087803b1580156101af57600080fd5b505af19250505080156101c0575060015b5080806101cc90610b8c565b915050610152565b50505050565b6000808154809291906101ec90610b8c565b919050555060005b8381101561027c573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610237929190610c21565b600060405180830381600087803b15801561025157600080fd5b505af1158015610265573d6000803e3d6000fd5b50505050808061027490610b8c565b9150506101f4565b50505050565b600061028c6105ed565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e63086866040518463ffffffff1660e01b81526004016102cb93929190610c54565b600060405180830381865afa1580156102e8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906103119190610e32565b915091509250929050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b815260040161035e9493929190610ed3565b6020604051808303816000875af115801561037d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a19190610f3f565b5060005b83811015610427573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b81526004016103e8929190610c21565b600060405180830381600087803b15801561040257600080fd5b505af1925050508015610413575060015b50808061041f90610b8c565b9150506103a5565b5061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b815260040161046a9493929190610ed3565b6020604051808303816000875af1158015610489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ad9190610f3f565b50505050565b6104bb610607565b60005b8381101561055c5761080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a846040518263ffffffff1660e01b81526004016105019190610f6c565b600060405180830381865afa15801561051e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105479190611138565b9150808061055490610b8c565b9150506104be565b5092915050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016105a59493929190610ed3565b6020604051808303816000875af11580156105c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e89190610f3f565b600080fd5b604051806040016040528060608152602001600081525090565b60405180610160016040528060608152602001606081526020016000151581526020016000600381111561063e5761063d6109ab565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6106a28161068f565b81146106ad57600080fd5b50565b6000813590506106bf81610699565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126106ea576106e96106c5565b5b8235905067ffffffffffffffff811115610707576107066106ca565b5b602083019150836001820283011115610723576107226106cf565b5b9250929050565b60008060006040848603121561074357610742610685565b5b6000610751868287016106b0565b935050602084013567ffffffffffffffff8111156107725761077161068a565b5b61077e868287016106d4565b92509250509250925092565b600080602083850312156107a1576107a0610685565b5b600083013567ffffffffffffffff8111156107bf576107be61068a565b5b6107cb858286016106d4565b92509250509250929050565b6107e08161068f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610820578082015181840152602081019050610805565b60008484015250505050565b6000601f19601f8301169050919050565b6000610848826107e6565b61085281856107f1565b9350610862818560208601610802565b61086b8161082c565b840191505092915050565b61087f8161068f565b82525050565b600060408301600083015184820360008601526108a2828261083d565b91505060208301516108b76020860182610876565b508091505092915050565b60006040820190506108d760008301856107d7565b81810360208301526108e98184610885565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061091d826108f2565b9050919050565b61092d81610912565b811461093857600080fd5b50565b60008135905061094a81610924565b92915050565b6000806040838503121561096757610966610685565b5b6000610975858286016106b0565b92505060206109868582860161093b565b9150509250929050565b60008115159050919050565b6109a581610990565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106109eb576109ea6109ab565b5b50565b60008190506109fc826109da565b919050565b6000610a0c826109ee565b9050919050565b610a1c81610a01565b82525050565b60008160070b9050919050565b610a3881610a22565b82525050565b6000610160830160008301518482036000860152610a5c828261083d565b91505060208301518482036020860152610a76828261083d565b9150506040830151610a8b604086018261099c565b506060830151610a9e6060860182610a13565b506080830151610ab16080860182610876565b5060a0830151610ac460a0860182610876565b5060c083015184820360c0860152610adc828261083d565b91505060e0830151610af160e0860182610a2f565b50610100830151610b06610100860182610a2f565b50610120830151610b1b610120860182610876565b50610140830151610b30610140860182610876565b508091505092915050565b60006020820190508181036000830152610b558184610a3e565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610b978261068f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610bc957610bc8610b5d565b5b600182019050919050565b600082825260208201905092915050565b82818337600083830152505050565b6000610c008385610bd4565b9350610c0d838584610be5565b610c168361082c565b840190509392505050565b60006020820190508181036000830152610c3c818486610bf4565b90509392505050565b610c4e81610912565b82525050565b6000604082019050610c696000830186610c45565b8181036020830152610c7c818486610bf4565b9050949350505050565b600081519050610c9581610699565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610cd88261082c565b810181811067ffffffffffffffff82111715610cf757610cf6610ca0565b5b80604052505050565b6000610d0a61067b565b9050610d168282610ccf565b919050565b600080fd5b600080fd5b600067ffffffffffffffff821115610d4057610d3f610ca0565b5b610d498261082c565b9050602081019050919050565b6000610d69610d6484610d25565b610d00565b905082815260208101848484011115610d8557610d84610d20565b5b610d90848285610802565b509392505050565b600082601f830112610dad57610dac6106c5565b5b8151610dbd848260208601610d56565b91505092915050565b600060408284031215610ddc57610ddb610c9b565b5b610de66040610d00565b9050600082015167ffffffffffffffff811115610e0657610e05610d1b565b5b610e1284828501610d98565b6000830152506020610e2684828501610c86565b60208301525092915050565b60008060408385031215610e4957610e48610685565b5b6000610e5785828601610c86565b925050602083015167ffffffffffffffff811115610e7857610e7761068a565b5b610e8485828601610dc6565b9150509250929050565b6000819050919050565b6000819050919050565b6000610ebd610eb8610eb384610e8e565b610e98565b61068f565b9050919050565b610ecd81610ea2565b82525050565b6000606082019050610ee86000830187610c45565b8181036020830152610efb818587610bf4565b9050610f0a6040830184610ec4565b95945050505050565b610f1c81610990565b8114610f2757600080fd5b50565b600081519050610f3981610f13565b92915050565b600060208284031215610f5557610f54610685565b5b6000610f6384828501610f2a565b91505092915050565b6000602082019050610f816000830184610c45565b92915050565b60048110610f9457600080fd5b50565b600081519050610fa681610f87565b92915050565b610fb581610a22565b8114610fc057600080fd5b50565b600081519050610fd281610fac565b92915050565b60006101608284031215610fef57610fee610c9b565b5b610ffa610160610d00565b9050600082015167ffffffffffffffff81111561101a57611019610d1b565b5b61102684828501610d98565b600083015250602082015167ffffffffffffffff81111561104a57611049610d1b565b5b61105684828501610d98565b602083015250604061106a84828501610f2a565b604083015250606061107e84828501610f97565b606083015250608061109284828501610c86565b60808301525060a06110a684828501610c86565b60a08301525060c082015167ffffffffffffffff8111156110ca576110c9610d1b565b5b6110d684828501610d98565b60c08301525060e06110ea84828501610fc3565b60e0830152506101006110ff84828501610fc3565b6101008301525061012061111584828501610c86565b6101208301525061014061112b84828501610c86565b6101408301525092915050565b60006020828403121561114e5761114d610685565b5b600082015167ffffffffffffffff81111561116c5761116b61068a565b5b61117884828501610fd8565b9150509291505056fea2646970667358221220f5f833c34bff960673e6df4fad50cb2e0deb7da5035552189c3d4e09281dd21264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c80634e5a8fe51461006757806352fce7b114610083578063668f452b1461009f578063922a4b67146100d0578063cbc367d4146100ec578063f66013d71461011c575b600080fd5b610081600480360381019061007c919061072a565b610138565b005b61009d6004803603810190610098919061072a565b6101da565b005b6100b960048036038101906100b4919061078a565b610282565b6040516100c79291906108c2565b60405180910390f35b6100ea60048036038101906100e5919061072a565b61031c565b005b61010660048036038101906101019190610950565b6104b3565b6040516101139190610b3b565b60405180910390f35b6101366004803603810190610131919061078a565b610563565b005b60008081548092919061014a90610b8c565b919050555060005b838110156101d4573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610195929190610c21565b600060405180830381600087803b1580156101af57600080fd5b505af19250505080156101c0575060015b5080806101cc90610b8c565b915050610152565b50505050565b6000808154809291906101ec90610b8c565b919050555060005b8381101561027c573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610237929190610c21565b600060405180830381600087803b15801561025157600080fd5b505af1158015610265573d6000803e3d6000fd5b50505050808061027490610b8c565b9150506101f4565b50505050565b600061028c6105ed565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e63086866040518463ffffffff1660e01b81526004016102cb93929190610c54565b600060405180830381865afa1580156102e8573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906103119190610e32565b915091509250929050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b815260040161035e9493929190610ed3565b6020604051808303816000875af115801561037d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a19190610f3f565b5060005b83811015610427573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b81526004016103e8929190610c21565b600060405180830381600087803b15801561040257600080fd5b505af1925050508015610413575060015b50808061041f90610b8c565b9150506103a5565b5061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b815260040161046a9493929190610ed3565b6020604051808303816000875af1158015610489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ad9190610f3f565b50505050565b6104bb610607565b60005b8381101561055c5761080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a846040518263ffffffff1660e01b81526004016105019190610f6c565b600060405180830381865afa15801561051e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105479190611138565b9150808061055490610b8c565b9150506104be565b5092915050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016105a59493929190610ed3565b6020604051808303816000875af11580156105c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e89190610f3f565b600080fd5b604051806040016040528060608152602001600081525090565b60405180610160016040528060608152602001606081526020016000151581526020016000600381111561063e5761063d6109ab565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6106a28161068f565b81146106ad57600080fd5b50565b6000813590506106bf81610699565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126106ea576106e96106c5565b5b8235905067ffffffffffffffff811115610707576107066106ca565b5b602083019150836001820283011115610723576107226106cf565b5b9250929050565b60008060006040848603121561074357610742610685565b5b6000610751868287016106b0565b935050602084013567ffffffffffffffff8111156107725761077161068a565b5b61077e868287016106d4565b92509250509250925092565b600080602083850312156107a1576107a0610685565b5b600083013567ffffffffffffffff8111156107bf576107be61068a565b5b6107cb858286016106d4565b92509250509250929050565b6107e08161068f565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610820578082015181840152602081019050610805565b60008484015250505050565b6000601f19601f8301169050919050565b6000610848826107e6565b61085281856107f1565b9350610862818560208601610802565b61086b8161082c565b840191505092915050565b61087f8161068f565b82525050565b600060408301600083015184820360008601526108a2828261083d565b91505060208301516108b76020860182610876565b508091505092915050565b60006040820190506108d760008301856107d7565b81810360208301526108e98184610885565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061091d826108f2565b9050919050565b61092d81610912565b811461093857600080fd5b50565b60008135905061094a81610924565b92915050565b6000806040838503121561096757610966610685565b5b6000610975858286016106b0565b92505060206109868582860161093b565b9150509250929050565b60008115159050919050565b6109a581610990565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106109eb576109ea6109ab565b5b50565b60008190506109fc826109da565b919050565b6000610a0c826109ee565b9050919050565b610a1c81610a01565b82525050565b60008160070b9050919050565b610a3881610a22565b82525050565b6000610160830160008301518482036000860152610a5c828261083d565b91505060208301518482036020860152610a76828261083d565b9150506040830151610a8b604086018261099c565b506060830151610a9e6060860182610a13565b506080830151610ab16080860182610876565b5060a0830151610ac460a0860182610876565b5060c083015184820360c0860152610adc828261083d565b91505060e0830151610af160e0860182610a2f565b50610100830151610b06610100860182610a2f565b50610120830151610b1b610120860182610876565b50610140830151610b30610140860182610876565b508091505092915050565b60006020820190508181036000830152610b558184610a3e565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610b978261068f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610bc957610bc8610b5d565b5b600182019050919050565b600082825260208201905092915050565b82818337600083830152505050565b6000610c008385610bd4565b9350610c0d838584610be5565b610c168361082c565b840190509392505050565b60006020820190508181036000830152610c3c818486610bf4565b90509392505050565b610c4e81610912565b82525050565b6000604082019050610c696000830186610c45565b8181036020830152610c7c818486610bf4565b9050949350505050565b600081519050610c9581610699565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610cd88261082c565b810181811067ffffffffffffffff82111715610cf757610cf6610ca0565b5b80604052505050565b6000610d0a61067b565b9050610d168282610ccf565b919050565b600080fd5b600080fd5b600067ffffffffffffffff821115610d4057610d3f610ca0565b5b610d498261082c565b9050602081019050919050565b6000610d69610d6484610d25565b610d00565b905082815260208101848484011115610d8557610d84610d20565b5b610d90848285610802565b509392505050565b600082601f830112610dad57610dac6106c5565b5b8151610dbd848260208601610d56565b91505092915050565b600060408284031215610ddc57610ddb610c9b565b5b610de66040610d00565b9050600082015167ffffffffffffffff811115610e0657610e05610d1b565b5b610e1284828501610d98565b6000830152506020610e2684828501610c86565b60208301525092915050565b60008060408385031215610e4957610e48610685565b5b6000610e5785828601610c86565b925050602083015167ffffffffffffffff811115610e7857610e7761068a565b5b610e8485828601610dc6565b9150509250929050565b6000819050919050565b6000819050919050565b6000610ebd610eb8610eb384610e8e565b610e98565b61068f565b9050919050565b610ecd81610ea2565b82525050565b6000606082019050610ee86000830187610c45565b8181036020830152610efb818587610bf4565b9050610f0a6040830184610ec4565b95945050505050565b610f1c81610990565b8114610f2757600080fd5b50565b600081519050610f3981610f13565b92915050565b600060208284031215610f5557610f54610685565b5b6000610f6384828501610f2a565b91505092915050565b6000602082019050610f816000830184610c45565b92915050565b60048110610f9457600080fd5b50565b600081519050610fa681610f87565b92915050565b610fb581610a22565b8114610fc057600080fd5b50565b600081519050610fd281610fac565b92915050565b60006101608284031215610fef57610fee610c9b565b5b610ffa610160610d00565b9050600082015167ffffffffffffffff81111561101a57611019610d1b565b5b61102684828501610d98565b600083015250602082015167ffffffffffffffff81111561104a57611049610d1b565b5b61105684828501610d98565b602083015250604061106a84828501610f2a565b604083015250606061107e84828501610f97565b606083015250608061109284828501610c86565b60808301525060a06110a684828501610c86565b60a08301525060c082015167ffffffffffffffff8111156110ca576110c9610d1b565b5b6110d684828501610d98565b60c08301525060e06110ea84828501610fc3565b60e0830152506101006110ff84828501610fc3565b6101008301525061012061111584828501610c86565b6101208301525061014061112b84828501610c86565b6101408301525092915050565b60006020828403121561114e5761114d610685565b5b600082015167ffffffffffffffff81111561116c5761116b61068a565b5b61117884828501610fd8565b9150509291505056fea2646970667358221220f5f833c34bff960673e6df4fad50cb2e0deb7da5035552189c3d4e09281dd21264736f6c63430008140033", + "bytecode": "0x60806040526000805561150f806100176000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063668f452b1161005b578063668f452b146100d6578063922a4b6714610107578063cbc367d414610123578063f66013d7146101535761007d565b80634d9db92b146100825780634e5a8fe51461009e57806352fce7b1146100ba575b600080fd5b61009c60048036038101906100979190610a0e565b61016f565b005b6100b860048036038101906100b39190610a82565b61041c565b005b6100d460048036038101906100cf9190610a82565b6104be565b005b6100f060048036038101906100eb9190610ae2565b610566565b6040516100fe929190610c1a565b60405180910390f35b610121600480360381019061011c9190610a82565b610600565b005b61013d60048036038101906101389190610ca8565b610797565b60405161014a9190610e93565b60405180910390f35b61016d60048036038101906101689190610ae2565b610847565b005b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016101b19493929190610f56565b6020604051808303816000875af11580156101d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f49190610fc2565b5060005b8481101561038f573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b815260040161023b929190610fef565b600060405180830381600087803b15801561025557600080fd5b505af1925050508015610266575060015b61037b5761080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308585600a6040518563ffffffff1660e01b81526004016102ac9493929190610f56565b6020604051808303816000875af11580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610fc2565b5060005b84811015610375573073ffffffffffffffffffffffffffffffffffffffff1663f66013d785856040518363ffffffff1660e01b8152600401610336929190610fef565b600060405180830381600087803b15801561035057600080fd5b505af1925050508015610361575060015b50808061036d90611042565b9150506102f3565b5061037c565b5b808061038790611042565b9150506101f8565b5061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016103d29493929190610f56565b6020604051808303816000875af11580156103f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104159190610fc2565b5050505050565b60008081548092919061042e90611042565b919050555060005b838110156104b8573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610479929190610fef565b600060405180830381600087803b15801561049357600080fd5b505af19250505080156104a4575060015b5080806104b090611042565b915050610436565b50505050565b6000808154809291906104d090611042565b919050555060005b83811015610560573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b815260040161051b929190610fef565b600060405180830381600087803b15801561053557600080fd5b505af1158015610549573d6000803e3d6000fd5b50505050808061055890611042565b9150506104d8565b50505050565b60006105706108d1565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e63086866040518463ffffffff1660e01b81526004016105af9392919061108a565b600060405180830381865afa1580156105cc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105f59190611268565b915091509250929050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016106429493929190610f56565b6020604051808303816000875af1158015610661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106859190610fc2565b5060005b8381101561070b573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b81526004016106cc929190610fef565b600060405180830381600087803b1580156106e657600080fd5b505af19250505080156106f7575060015b50808061070390611042565b915050610689565b5061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b815260040161074e9493929190610f56565b6020604051808303816000875af115801561076d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107919190610fc2565b50505050565b61079f6108eb565b60005b838110156108405761080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a846040518263ffffffff1660e01b81526004016107e591906112c4565b600060405180830381865afa158015610802573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061082b9190611490565b9150808061083890611042565b9150506107a2565b5092915050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016108899493929190610f56565b6020604051808303816000875af11580156108a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190610fc2565b600080fd5b604051806040016040528060608152602001600081525090565b60405180610160016040528060608152602001606081526020016000151581526020016000600381111561092257610921610d03565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61098681610973565b811461099157600080fd5b50565b6000813590506109a38161097d565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126109ce576109cd6109a9565b5b8235905067ffffffffffffffff8111156109eb576109ea6109ae565b5b602083019150836001820283011115610a0757610a066109b3565b5b9250929050565b60008060008060608587031215610a2857610a27610969565b5b6000610a3687828801610994565b9450506020610a4787828801610994565b935050604085013567ffffffffffffffff811115610a6857610a6761096e565b5b610a74878288016109b8565b925092505092959194509250565b600080600060408486031215610a9b57610a9a610969565b5b6000610aa986828701610994565b935050602084013567ffffffffffffffff811115610aca57610ac961096e565b5b610ad6868287016109b8565b92509250509250925092565b60008060208385031215610af957610af8610969565b5b600083013567ffffffffffffffff811115610b1757610b1661096e565b5b610b23858286016109b8565b92509250509250929050565b610b3881610973565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610b78578082015181840152602081019050610b5d565b60008484015250505050565b6000601f19601f8301169050919050565b6000610ba082610b3e565b610baa8185610b49565b9350610bba818560208601610b5a565b610bc381610b84565b840191505092915050565b610bd781610973565b82525050565b60006040830160008301518482036000860152610bfa8282610b95565b9150506020830151610c0f6020860182610bce565b508091505092915050565b6000604082019050610c2f6000830185610b2f565b8181036020830152610c418184610bdd565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c7582610c4a565b9050919050565b610c8581610c6a565b8114610c9057600080fd5b50565b600081359050610ca281610c7c565b92915050565b60008060408385031215610cbf57610cbe610969565b5b6000610ccd85828601610994565b9250506020610cde85828601610c93565b9150509250929050565b60008115159050919050565b610cfd81610ce8565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610d4357610d42610d03565b5b50565b6000819050610d5482610d32565b919050565b6000610d6482610d46565b9050919050565b610d7481610d59565b82525050565b60008160070b9050919050565b610d9081610d7a565b82525050565b6000610160830160008301518482036000860152610db48282610b95565b91505060208301518482036020860152610dce8282610b95565b9150506040830151610de36040860182610cf4565b506060830151610df66060860182610d6b565b506080830151610e096080860182610bce565b5060a0830151610e1c60a0860182610bce565b5060c083015184820360c0860152610e348282610b95565b91505060e0830151610e4960e0860182610d87565b50610100830151610e5e610100860182610d87565b50610120830151610e73610120860182610bce565b50610140830151610e88610140860182610bce565b508091505092915050565b60006020820190508181036000830152610ead8184610d96565b905092915050565b610ebe81610c6a565b82525050565b600082825260208201905092915050565b82818337600083830152505050565b6000610ef08385610ec4565b9350610efd838584610ed5565b610f0683610b84565b840190509392505050565b6000819050919050565b6000819050919050565b6000610f40610f3b610f3684610f11565b610f1b565b610973565b9050919050565b610f5081610f25565b82525050565b6000606082019050610f6b6000830187610eb5565b8181036020830152610f7e818587610ee4565b9050610f8d6040830184610f47565b95945050505050565b610f9f81610ce8565b8114610faa57600080fd5b50565b600081519050610fbc81610f96565b92915050565b600060208284031215610fd857610fd7610969565b5b6000610fe684828501610fad565b91505092915050565b6000602082019050818103600083015261100a818486610ee4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061104d82610973565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361107f5761107e611013565b5b600182019050919050565b600060408201905061109f6000830186610eb5565b81810360208301526110b2818486610ee4565b9050949350505050565b6000815190506110cb8161097d565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61110e82610b84565b810181811067ffffffffffffffff8211171561112d5761112c6110d6565b5b80604052505050565b600061114061095f565b905061114c8282611105565b919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611176576111756110d6565b5b61117f82610b84565b9050602081019050919050565b600061119f61119a8461115b565b611136565b9050828152602081018484840111156111bb576111ba611156565b5b6111c6848285610b5a565b509392505050565b600082601f8301126111e3576111e26109a9565b5b81516111f384826020860161118c565b91505092915050565b600060408284031215611212576112116110d1565b5b61121c6040611136565b9050600082015167ffffffffffffffff81111561123c5761123b611151565b5b611248848285016111ce565b600083015250602061125c848285016110bc565b60208301525092915050565b6000806040838503121561127f5761127e610969565b5b600061128d858286016110bc565b925050602083015167ffffffffffffffff8111156112ae576112ad61096e565b5b6112ba858286016111fc565b9150509250929050565b60006020820190506112d96000830184610eb5565b92915050565b600481106112ec57600080fd5b50565b6000815190506112fe816112df565b92915050565b61130d81610d7a565b811461131857600080fd5b50565b60008151905061132a81611304565b92915050565b60006101608284031215611347576113466110d1565b5b611352610160611136565b9050600082015167ffffffffffffffff81111561137257611371611151565b5b61137e848285016111ce565b600083015250602082015167ffffffffffffffff8111156113a2576113a1611151565b5b6113ae848285016111ce565b60208301525060406113c284828501610fad565b60408301525060606113d6848285016112ef565b60608301525060806113ea848285016110bc565b60808301525060a06113fe848285016110bc565b60a08301525060c082015167ffffffffffffffff81111561142257611421611151565b5b61142e848285016111ce565b60c08301525060e06114428482850161131b565b60e0830152506101006114578482850161131b565b6101008301525061012061146d848285016110bc565b61012083015250610140611483848285016110bc565b6101408301525092915050565b6000602082840312156114a6576114a5610969565b5b600082015167ffffffffffffffff8111156114c4576114c361096e565b5b6114d084828501611330565b9150509291505056fea2646970667358221220909639086b03bb38b32aaba32e58073b8f74fe67a6fa3e21df62be2b2faddaed64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063668f452b1161005b578063668f452b146100d6578063922a4b6714610107578063cbc367d414610123578063f66013d7146101535761007d565b80634d9db92b146100825780634e5a8fe51461009e57806352fce7b1146100ba575b600080fd5b61009c60048036038101906100979190610a0e565b61016f565b005b6100b860048036038101906100b39190610a82565b61041c565b005b6100d460048036038101906100cf9190610a82565b6104be565b005b6100f060048036038101906100eb9190610ae2565b610566565b6040516100fe929190610c1a565b60405180910390f35b610121600480360381019061011c9190610a82565b610600565b005b61013d60048036038101906101389190610ca8565b610797565b60405161014a9190610e93565b60405180910390f35b61016d60048036038101906101689190610ae2565b610847565b005b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016101b19493929190610f56565b6020604051808303816000875af11580156101d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f49190610fc2565b5060005b8481101561038f573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b815260040161023b929190610fef565b600060405180830381600087803b15801561025557600080fd5b505af1925050508015610266575060015b61037b5761080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308585600a6040518563ffffffff1660e01b81526004016102ac9493929190610f56565b6020604051808303816000875af11580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610fc2565b5060005b84811015610375573073ffffffffffffffffffffffffffffffffffffffff1663f66013d785856040518363ffffffff1660e01b8152600401610336929190610fef565b600060405180830381600087803b15801561035057600080fd5b505af1925050508015610361575060015b50808061036d90611042565b9150506102f3565b5061037c565b5b808061038790611042565b9150506101f8565b5061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016103d29493929190610f56565b6020604051808303816000875af11580156103f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104159190610fc2565b5050505050565b60008081548092919061042e90611042565b919050555060005b838110156104b8573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b8152600401610479929190610fef565b600060405180830381600087803b15801561049357600080fd5b505af19250505080156104a4575060015b5080806104b090611042565b915050610436565b50505050565b6000808154809291906104d090611042565b919050555060005b83811015610560573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b815260040161051b929190610fef565b600060405180830381600087803b15801561053557600080fd5b505af1158015610549573d6000803e3d6000fd5b50505050808061055890611042565b9150506104d8565b50505050565b60006105706108d1565b61080073ffffffffffffffffffffffffffffffffffffffff1663241774e63086866040518463ffffffff1660e01b81526004016105af9392919061108a565b600060405180830381865afa1580156105cc573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906105f59190611268565b915091509250929050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016106429493929190610f56565b6020604051808303816000875af1158015610661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106859190610fc2565b5060005b8381101561070b573073ffffffffffffffffffffffffffffffffffffffff1663f66013d784846040518363ffffffff1660e01b81526004016106cc929190610fef565b600060405180830381600087803b1580156106e657600080fd5b505af19250505080156106f7575060015b50808061070390611042565b915050610689565b5061080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b815260040161074e9493929190610f56565b6020604051808303816000875af115801561076d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107919190610fc2565b50505050565b61079f6108eb565b60005b838110156108405761080073ffffffffffffffffffffffffffffffffffffffff1663223b3b7a846040518263ffffffff1660e01b81526004016107e591906112c4565b600060405180830381865afa158015610802573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061082b9190611490565b9150808061083890611042565b9150506107a2565b5092915050565b61080073ffffffffffffffffffffffffffffffffffffffff166353266bbb308484600a6040518563ffffffff1660e01b81526004016108899493929190610f56565b6020604051808303816000875af11580156108a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190610fc2565b600080fd5b604051806040016040528060608152602001600081525090565b60405180610160016040528060608152602001606081526020016000151581526020016000600381111561092257610921610d03565b5b8152602001600081526020016000815260200160608152602001600060070b8152602001600060070b815260200160008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61098681610973565b811461099157600080fd5b50565b6000813590506109a38161097d565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126109ce576109cd6109a9565b5b8235905067ffffffffffffffff8111156109eb576109ea6109ae565b5b602083019150836001820283011115610a0757610a066109b3565b5b9250929050565b60008060008060608587031215610a2857610a27610969565b5b6000610a3687828801610994565b9450506020610a4787828801610994565b935050604085013567ffffffffffffffff811115610a6857610a6761096e565b5b610a74878288016109b8565b925092505092959194509250565b600080600060408486031215610a9b57610a9a610969565b5b6000610aa986828701610994565b935050602084013567ffffffffffffffff811115610aca57610ac961096e565b5b610ad6868287016109b8565b92509250509250925092565b60008060208385031215610af957610af8610969565b5b600083013567ffffffffffffffff811115610b1757610b1661096e565b5b610b23858286016109b8565b92509250509250929050565b610b3881610973565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610b78578082015181840152602081019050610b5d565b60008484015250505050565b6000601f19601f8301169050919050565b6000610ba082610b3e565b610baa8185610b49565b9350610bba818560208601610b5a565b610bc381610b84565b840191505092915050565b610bd781610973565b82525050565b60006040830160008301518482036000860152610bfa8282610b95565b9150506020830151610c0f6020860182610bce565b508091505092915050565b6000604082019050610c2f6000830185610b2f565b8181036020830152610c418184610bdd565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610c7582610c4a565b9050919050565b610c8581610c6a565b8114610c9057600080fd5b50565b600081359050610ca281610c7c565b92915050565b60008060408385031215610cbf57610cbe610969565b5b6000610ccd85828601610994565b9250506020610cde85828601610c93565b9150509250929050565b60008115159050919050565b610cfd81610ce8565b82525050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110610d4357610d42610d03565b5b50565b6000819050610d5482610d32565b919050565b6000610d6482610d46565b9050919050565b610d7481610d59565b82525050565b60008160070b9050919050565b610d9081610d7a565b82525050565b6000610160830160008301518482036000860152610db48282610b95565b91505060208301518482036020860152610dce8282610b95565b9150506040830151610de36040860182610cf4565b506060830151610df66060860182610d6b565b506080830151610e096080860182610bce565b5060a0830151610e1c60a0860182610bce565b5060c083015184820360c0860152610e348282610b95565b91505060e0830151610e4960e0860182610d87565b50610100830151610e5e610100860182610d87565b50610120830151610e73610120860182610bce565b50610140830151610e88610140860182610bce565b508091505092915050565b60006020820190508181036000830152610ead8184610d96565b905092915050565b610ebe81610c6a565b82525050565b600082825260208201905092915050565b82818337600083830152505050565b6000610ef08385610ec4565b9350610efd838584610ed5565b610f0683610b84565b840190509392505050565b6000819050919050565b6000819050919050565b6000610f40610f3b610f3684610f11565b610f1b565b610973565b9050919050565b610f5081610f25565b82525050565b6000606082019050610f6b6000830187610eb5565b8181036020830152610f7e818587610ee4565b9050610f8d6040830184610f47565b95945050505050565b610f9f81610ce8565b8114610faa57600080fd5b50565b600081519050610fbc81610f96565b92915050565b600060208284031215610fd857610fd7610969565b5b6000610fe684828501610fad565b91505092915050565b6000602082019050818103600083015261100a818486610ee4565b90509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061104d82610973565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361107f5761107e611013565b5b600182019050919050565b600060408201905061109f6000830186610eb5565b81810360208301526110b2818486610ee4565b9050949350505050565b6000815190506110cb8161097d565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61110e82610b84565b810181811067ffffffffffffffff8211171561112d5761112c6110d6565b5b80604052505050565b600061114061095f565b905061114c8282611105565b919050565b600080fd5b600080fd5b600067ffffffffffffffff821115611176576111756110d6565b5b61117f82610b84565b9050602081019050919050565b600061119f61119a8461115b565b611136565b9050828152602081018484840111156111bb576111ba611156565b5b6111c6848285610b5a565b509392505050565b600082601f8301126111e3576111e26109a9565b5b81516111f384826020860161118c565b91505092915050565b600060408284031215611212576112116110d1565b5b61121c6040611136565b9050600082015167ffffffffffffffff81111561123c5761123b611151565b5b611248848285016111ce565b600083015250602061125c848285016110bc565b60208301525092915050565b6000806040838503121561127f5761127e610969565b5b600061128d858286016110bc565b925050602083015167ffffffffffffffff8111156112ae576112ad61096e565b5b6112ba858286016111fc565b9150509250929050565b60006020820190506112d96000830184610eb5565b92915050565b600481106112ec57600080fd5b50565b6000815190506112fe816112df565b92915050565b61130d81610d7a565b811461131857600080fd5b50565b60008151905061132a81611304565b92915050565b60006101608284031215611347576113466110d1565b5b611352610160611136565b9050600082015167ffffffffffffffff81111561137257611371611151565b5b61137e848285016111ce565b600083015250602082015167ffffffffffffffff8111156113a2576113a1611151565b5b6113ae848285016111ce565b60208301525060406113c284828501610fad565b60408301525060606113d6848285016112ef565b60608301525060806113ea848285016110bc565b60808301525060a06113fe848285016110bc565b60a08301525060c082015167ffffffffffffffff81111561142257611421611151565b5b61142e848285016111ce565b60c08301525060e06114428482850161131b565b60e0830152506101006114578482850161131b565b6101008301525061012061146d848285016110bc565b61012083015250610140611483848285016110bc565b6101408301525092915050565b6000602082840312156114a6576114a5610969565b5b600082015167ffffffffffffffff8111156114c4576114c361096e565b5b6114d084828501611330565b9150509291505056fea2646970667358221220909639086b03bb38b32aaba32e58073b8f74fe67a6fa3e21df62be2b2faddaed64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/precompiles/testutil/contracts/StakingReverter.sol b/precompiles/testutil/contracts/StakingReverter.sol index 469267cb4..aef5d526b 100644 --- a/precompiles/testutil/contracts/StakingReverter.sol +++ b/precompiles/testutil/contracts/StakingReverter.sol @@ -49,6 +49,36 @@ contract StakingReverter { STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); } + /// @dev nestedTryCatchDelegations performs nested try/catch calls to precompile + /// where inner calls revert intentionally. Only the successful delegations + /// outside the reverting scope should persist. + /// + /// Expected successful delegations: 1 (before loop) + outerTimes (after each catch) + 1 (after loop) + function nestedTryCatchDelegations(uint outerTimes, uint innerTimes, string calldata validatorAddress) external { + // Initial successful delegate before any nested reverts + STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); + + for (uint i = 0; i < outerTimes; i++) { + // Outer call that will revert and be caught + try StakingReverter(address(this)).performDelegation(validatorAddress) { + // no-op + } catch { + // After catching the revert, perform a successful delegate + STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); + + // Inner nested loop of reverting calls + for (uint j = 0; j < innerTimes; j++) { + try StakingReverter(address(this)).performDelegation(validatorAddress) { + // no-op + } catch {} + } + } + } + + // Final successful delegate after the loops + STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); + } + function performDelegation(string calldata validatorAddress) external { STAKING_CONTRACT.delegate(address(this), validatorAddress, 10); revert(); diff --git a/evmd/precompiles.go b/precompiles/types/defaults.go similarity index 73% rename from evmd/precompiles.go rename to precompiles/types/defaults.go index 30165a0e9..c154f3a97 100644 --- a/evmd/precompiles.go +++ b/precompiles/types/defaults.go @@ -1,11 +1,9 @@ -package evmd +package types import ( "fmt" "maps" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" @@ -13,6 +11,7 @@ import ( "github.com/cosmos/evm/precompiles/bech32" cmn "github.com/cosmos/evm/precompiles/common" distprecompile "github.com/cosmos/evm/precompiles/distribution" + "github.com/cosmos/evm/precompiles/erc20factory" govprecompile "github.com/cosmos/evm/precompiles/gov" ics20precompile "github.com/cosmos/evm/precompiles/ics20" "github.com/cosmos/evm/precompiles/p256" @@ -20,11 +19,13 @@ import ( stakingprecompile "github.com/cosmos/evm/precompiles/staking" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" - evmkeeper "github.com/cosmos/evm/x/vm/keeper" channelkeeper "github.com/cosmos/ibc-go/v10/modules/core/04-channel/keeper" "cosmossdk.io/core/address" + "github.com/cosmos/cosmos-sdk/codec" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + sdktypes "github.com/cosmos/cosmos-sdk/types" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" @@ -42,9 +43,9 @@ type Optionals struct { func defaultOptionals() Optionals { return Optionals{ - AddressCodec: addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), - ValidatorAddrCodec: addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), - ConsensusAddrCodec: addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), + AddressCodec: addresscodec.NewBech32Codec(sdktypes.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddrCodec: addresscodec.NewBech32Codec(sdktypes.GetConfig().GetBech32ValidatorAddrPrefix()), + ConsensusAddrCodec: addresscodec.NewBech32Codec(sdktypes.GetConfig().GetBech32ConsensusAddrPrefix()), } } @@ -70,17 +71,16 @@ func WithConsensusAddrCodec(codec address.Codec) Option { const bech32PrecompileBaseGas = 6_000 -// NewAvailableStaticPrecompiles returns the list of all available static precompiled contracts from Cosmos EVM. +// DefaultStaticPrecompiles returns the list of all available static precompiled contracts from Cosmos EVM. // // NOTE: this should only be used during initialization of the Keeper. -func NewAvailableStaticPrecompiles( +func DefaultStaticPrecompiles( stakingKeeper stakingkeeper.Keeper, distributionKeeper distributionkeeper.Keeper, bankKeeper cmn.BankKeeper, - erc20Keeper erc20Keeper.Keeper, - transferKeeper transferkeeper.Keeper, + erc20Keeper *erc20Keeper.Keeper, + transferKeeper *transferkeeper.Keeper, channelKeeper *channelkeeper.Keeper, - evmKeeper *evmkeeper.Keeper, govKeeper govkeeper.Keeper, slashingKeeper slashingkeeper.Keeper, codec codec.Codec, @@ -101,13 +101,21 @@ func NewAvailableStaticPrecompiles( panic(fmt.Errorf("failed to instantiate bech32 precompile: %w", err)) } - stakingPrecompile, err := stakingprecompile.NewPrecompile(stakingKeeper, bankKeeper, options.AddressCodec) + stakingPrecompile, err := stakingprecompile.NewPrecompile( + stakingKeeper, + stakingkeeper.NewMsgServerImpl(&stakingKeeper), + stakingkeeper.NewQuerier(&stakingKeeper), + bankKeeper, + options.AddressCodec, + ) if err != nil { panic(fmt.Errorf("failed to instantiate staking precompile: %w", err)) } distributionPrecompile, err := distprecompile.NewPrecompile( distributionKeeper, + distributionkeeper.NewMsgServerImpl(distributionKeeper), + distributionkeeper.NewQuerier(distributionKeeper), stakingKeeper, bankKeeper, options.AddressCodec, @@ -121,7 +129,6 @@ func NewAvailableStaticPrecompiles( stakingKeeper, transferKeeper, channelKeeper, - evmKeeper, ) if err != nil { panic(fmt.Errorf("failed to instantiate ICS20 precompile: %w", err)) @@ -132,16 +139,33 @@ func NewAvailableStaticPrecompiles( panic(fmt.Errorf("failed to instantiate bank precompile: %w", err)) } - govPrecompile, err := govprecompile.NewPrecompile(govKeeper, bankKeeper, codec, options.AddressCodec) + govPrecompile, err := govprecompile.NewPrecompile( + govkeeper.NewMsgServerImpl(&govKeeper), + govkeeper.NewQueryServer(&govKeeper), + bankKeeper, + codec, + options.AddressCodec, + ) if err != nil { panic(fmt.Errorf("failed to instantiate gov precompile: %w", err)) } - slashingPrecompile, err := slashingprecompile.NewPrecompile(slashingKeeper, bankKeeper, options.ValidatorAddrCodec, options.ConsensusAddrCodec) + slashingPrecompile, err := slashingprecompile.NewPrecompile( + slashingKeeper, + slashingkeeper.NewMsgServerImpl(slashingKeeper), + bankKeeper, + options.ValidatorAddrCodec, + options.ConsensusAddrCodec, + ) if err != nil { panic(fmt.Errorf("failed to instantiate slashing precompile: %w", err)) } + erc20FactoryPrecompile, err := erc20factory.NewPrecompile(&erc20Keeper, bankKeeper, evmKeeper) + if err != nil { + panic(fmt.Errorf("failed to instantiate erc20 factory precompile: %w", err)) + } + // Stateless precompiles precompiles[bech32Precompile.Address()] = bech32Precompile precompiles[p256Precompile.Address()] = p256Precompile @@ -153,6 +177,7 @@ func NewAvailableStaticPrecompiles( precompiles[bankPrecompile.Address()] = bankPrecompile precompiles[govPrecompile.Address()] = govPrecompile precompiles[slashingPrecompile.Address()] = slashingPrecompile + precompiles[erc20FactoryPrecompile.Address()] = erc20FactoryPrecompile return precompiles } diff --git a/precompiles/werc20/werc20.go b/precompiles/werc20/werc20.go index 0f1312305..514eb717b 100644 --- a/precompiles/werc20/werc20.go +++ b/precompiles/werc20/werc20.go @@ -10,10 +10,10 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" + ibcutils "github.com/cosmos/evm/ibc" cmn "github.com/cosmos/evm/precompiles/common" erc20 "github.com/cosmos/evm/precompiles/erc20" erc20types "github.com/cosmos/evm/x/erc20/types" - transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" ) // abiPath defines the path to the WERC-20 precompile ABI JSON file. @@ -51,20 +51,17 @@ func NewPrecompile( tokenPair erc20types.TokenPair, bankKeeper cmn.BankKeeper, erc20Keeper Erc20Keeper, - transferKeeper transferkeeper.Keeper, + transferKeeper ibcutils.TransferKeeper, + erc20ABI abi.ABI, + werc20ABI abi.ABI, ) (*Precompile, error) { - newABI, err := LoadABI() - if err != nil { - return nil, fmt.Errorf("error loading the ABI: %w", err) - } - - erc20Precompile, err := erc20.NewPrecompile(tokenPair, bankKeeper, erc20Keeper, transferKeeper) + erc20Precompile, err := erc20.NewPrecompile(tokenPair, bankKeeper, erc20Keeper, transferKeeper, erc20ABI) if err != nil { return nil, fmt.Errorf("error instantiating the ERC20 precompile: %w", err) } // use the IWERC20 ABI - erc20Precompile.ABI = newABI + erc20Precompile.ABI = werc20ABI return &Precompile{ Precompile: erc20Precompile, diff --git a/proto/cosmos/evm/erc20/v1/erc20.proto b/proto/cosmos/evm/erc20/v1/erc20.proto index 5ead3be52..d7cd29d2d 100644 --- a/proto/cosmos/evm/erc20/v1/erc20.proto +++ b/proto/cosmos/evm/erc20/v1/erc20.proto @@ -17,8 +17,8 @@ enum Owner { OWNER_EXTERNAL = 2; } -// TokenPair defines an instance that records a pairing consisting of a native -// Cosmos Coin and an ERC20 token address. +// TokenPair defines an instance that records a pairing (mapping) consisting of a native +// Cosmos Coin and an ERC20 token address. The "pair" does not imply an asset swap exchange. message TokenPair { option (gogoproto.equal) = true; // erc20_address is the hex address of ERC20 contract token diff --git a/proto/cosmos/evm/erc20/v1/genesis.proto b/proto/cosmos/evm/erc20/v1/genesis.proto index 2e2102136..cacf59283 100644 --- a/proto/cosmos/evm/erc20/v1/genesis.proto +++ b/proto/cosmos/evm/erc20/v1/genesis.proto @@ -13,7 +13,7 @@ message GenesisState { // params are the erc20 module parameters at genesis Params params = 1 [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; - // token_pairs is a slice of the registered token pairs at genesis + // token_pairs is a slice of the registered token pairs (mappings) at genesis repeated TokenPair token_pairs = 2 [ (gogoproto.nullable) = false, (amino.dont_omitempty) = true ]; // allowances is a slice of the registered allowances at genesis diff --git a/proto/cosmos/evm/erc20/v1/query.proto b/proto/cosmos/evm/erc20/v1/query.proto index b1d2061f4..a23a6832c 100644 --- a/proto/cosmos/evm/erc20/v1/query.proto +++ b/proto/cosmos/evm/erc20/v1/query.proto @@ -13,14 +13,14 @@ option go_package = "github.com/cosmos/evm/x/erc20/types"; // Query defines the gRPC querier service. service Query { - // TokenPairs retrieves registered token pairs + // TokenPairs retrieves registered token pairs (mappings)x rpc TokenPairs(QueryTokenPairsRequest) returns (QueryTokenPairsResponse) { option (google.api.http).get = "/cosmos/evm/erc20/v1/token_pairs"; } - // TokenPair retrieves a registered token pair + // TokenPair retrieves a registered token pair (mapping) rpc TokenPair(QueryTokenPairRequest) returns (QueryTokenPairResponse) { - option (google.api.http).get = "/cosmos/evm/erc20/v1/token_pairs/{token}"; + option (google.api.http).get = "/cosmos/evm/erc20/v1/token_pairs/{token=**}"; } // Params retrieves the erc20 module params diff --git a/proto/cosmos/evm/vm/v1/evm.proto b/proto/cosmos/evm/vm/v1/evm.proto index fc0c7b3fe..dda6eade0 100644 --- a/proto/cosmos/evm/vm/v1/evm.proto +++ b/proto/cosmos/evm/vm/v1/evm.proto @@ -20,9 +20,9 @@ message Params { (gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\"" ]; - // allow_unprotected_txs defines if replay-protected (i.e non EIP155 - // signed) transactions can be executed on the state machine. - bool allow_unprotected_txs = 5; + // Acceptance of non-protected transactions (i.e non EIP-155 signed) + // is managed independently by each node. + reserved 5; // renamed active_precompiles to active_static_precompiles reserved 6; // evm_channels is the list of channel identifiers from EVM compatible chains @@ -35,6 +35,7 @@ message Params { // active_static_precompiles defines the slice of hex addresses of the // precompiled contracts that are active repeated string active_static_precompiles = 9; + uint64 history_serve_window = 10; } // AccessControl defines the permission policy of the EVM @@ -264,6 +265,9 @@ message Log { // reorganisation. You must pay attention to this field if you receive logs // through a filter query. bool removed = 9; + + // block_timestamp is the timestamp of the block in which the transaction was + uint64 block_timestamp = 10 [ (gogoproto.jsontag) = "blockTimestamp" ]; } // TxResult stores results of Tx execution. diff --git a/proto/cosmos/evm/vm/v1/tx.proto b/proto/cosmos/evm/vm/v1/tx.proto index 384c047cc..7ac870f9a 100644 --- a/proto/cosmos/evm/vm/v1/tx.proto +++ b/proto/cosmos/evm/vm/v1/tx.proto @@ -71,6 +71,12 @@ message MsgEthereumTxResponse { string vm_error = 4; // gas_used specifies how much gas was consumed by the transaction uint64 gas_used = 5; + // max_used_gas specifies the gas consumed by the transaction, not including refunds + uint64 max_used_gas = 6; + // include the block hash for json-rpc to use + bytes block_hash = 7; + // include the block timestamp for json-rpc to use + uint64 block_timestamp = 8; } // MsgUpdateParams defines a Msg for updating the x/vm module parameters. diff --git a/rpc/apis.go b/rpc/apis.go index 408713aa9..e969f86e5 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" + evmmempool "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/rpc/backend" "github.com/cosmos/evm/rpc/namespaces/ethereum/debug" "github.com/cosmos/evm/rpc/namespaces/ethereum/eth" @@ -47,6 +48,7 @@ type APICreator = func( stream *stream.RPCStream, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API // apiCreators defines the JSON-RPC API namespaces. @@ -59,8 +61,9 @@ func init() { stream *stream.RPCStream, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: EthNamespace, @@ -76,7 +79,7 @@ func init() { }, } }, - Web3Namespace: func(*server.Context, client.Context, *stream.RPCStream, bool, types.EVMTxIndexer) []rpc.API { + Web3Namespace: func(*server.Context, client.Context, *stream.RPCStream, bool, types.EVMTxIndexer, *evmmempool.ExperimentalEVMMempool) []rpc.API { return []rpc.API{ { Namespace: Web3Namespace, @@ -86,7 +89,7 @@ func init() { }, } }, - NetNamespace: func(ctx *server.Context, clientCtx client.Context, _ *stream.RPCStream, _ bool, _ types.EVMTxIndexer) []rpc.API { + NetNamespace: func(ctx *server.Context, clientCtx client.Context, _ *stream.RPCStream, _ bool, _ types.EVMTxIndexer, _ *evmmempool.ExperimentalEVMMempool) []rpc.API { return []rpc.API{ { Namespace: NetNamespace, @@ -101,8 +104,9 @@ func init() { _ *stream.RPCStream, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: PersonalNamespace, @@ -117,8 +121,9 @@ func init() { _ *stream.RPCStream, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: TxPoolNamespace, @@ -133,8 +138,9 @@ func init() { _ *stream.RPCStream, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: DebugNamespace, @@ -149,8 +155,9 @@ func init() { _ *stream.RPCStream, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API { - evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer) + evmBackend := backend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, indexer, mempool) return []rpc.API{ { Namespace: MinerNamespace, @@ -170,12 +177,13 @@ func GetRPCAPIs(ctx *server.Context, allowUnprotectedTxs bool, indexer types.EVMTxIndexer, selectedAPIs []string, + mempool *evmmempool.ExperimentalEVMMempool, ) []rpc.API { var apis []rpc.API for _, ns := range selectedAPIs { if creator, ok := apiCreators[ns]; ok { - apis = append(apis, creator(ctx, clientCtx, stream, allowUnprotectedTxs, indexer)...) + apis = append(apis, creator(ctx, clientCtx, stream, allowUnprotectedTxs, indexer, mempool)...) } else { ctx.Logger.Error("invalid namespace value", "namespace", ns) } diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 140fd5e94..de169ff75 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -17,6 +17,7 @@ import ( tmrpcclient "github.com/cometbft/cometbft/rpc/client" tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" + evmmempool "github.com/cosmos/evm/mempool" rpctypes "github.com/cosmos/evm/rpc/types" "github.com/cosmos/evm/server/config" cosmosevmtypes "github.com/cosmos/evm/types" @@ -106,6 +107,7 @@ type EVMBackend interface { GetTransactionLogs(hash common.Hash) ([]*ethtypes.Log, error) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) + CreateAccessList(args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccessListResult, error) // Send Transaction Resend(args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) @@ -166,6 +168,7 @@ type Backend struct { AllowUnprotectedTxs bool Indexer cosmosevmtypes.EVMTxIndexer ProcessBlocker ProcessBlocker + Mempool *evmmempool.ExperimentalEVMMempool } func (b *Backend) GetConfig() config.Config { @@ -179,6 +182,7 @@ func NewBackend( clientCtx client.Context, allowUnprotectedTxs bool, indexer cosmosevmtypes.EVMTxIndexer, + mempool *evmmempool.ExperimentalEVMMempool, ) *Backend { appConf, err := config.GetConfig(ctx.Viper) if err != nil { @@ -200,6 +204,7 @@ func NewBackend( Cfg: appConf, AllowUnprotectedTxs: allowUnprotectedTxs, Indexer: indexer, + Mempool: mempool, } b.ProcessBlocker = b.ProcessBlock return b diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 3c253219f..737fdc3f5 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -203,6 +203,9 @@ func (b *Backend) CometHeaderByNumber(blockNum rpctypes.BlockNumber) (*cmtrpctyp // CometBlockResultByNumber returns a CometBFT-formatted block result // by block number func (b *Backend) CometBlockResultByNumber(height *int64) (*cmtrpctypes.ResultBlockResults, error) { + if height != nil && *height == 0 { + height = nil + } res, err := b.RPCClient.BlockResults(b.Ctx, height) if err != nil { return nil, fmt.Errorf("failed to fetch block result from CometBFT %d: %w", *height, err) @@ -607,10 +610,18 @@ func (b *Backend) formatTxReceipt( if err != nil { return nil, err } + height, err := cosmosevmtypes.SafeUint64(blockRes.Height) + if err != nil { + return nil, err + } // parse tx logs from events msgIndex := int(txResult.MsgIndex) // #nosec G115 -- checked for int overflow already - logs, err := evmtypes.TxLogsFromEvents(blockRes.TxsResults[txResult.TxIndex].Events, msgIndex) + logs, err := evmtypes.DecodeMsgLogs( + blockRes.TxsResults[txResult.TxIndex].Data, + msgIndex, + height, + ) if err != nil { b.Logger.Debug("failed to parse logs", "hash", ethMsg.Hash().String(), "error", err.Error()) } diff --git a/rpc/backend/call_tx.go b/rpc/backend/call_tx.go index 0c54f45c9..4c4c7b8d2 100644 --- a/rpc/backend/call_tx.go +++ b/rpc/backend/call_tx.go @@ -155,11 +155,30 @@ func (b *Backend) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { } if err != nil { // Check if this is a nonce gap error that was successfully queued - if strings.Contains(err.Error(), mempool.ErrNonceGap.Error()) { + if b.Mempool != nil && strings.Contains(err.Error(), mempool.ErrNonceGap.Error()) { // Transaction was successfully queued due to nonce gap, return success to client b.Logger.Debug("transaction queued due to nonce gap", "hash", txHash.Hex()) return txHash, nil } + if b.Mempool != nil && strings.Contains(err.Error(), mempool.ErrNonceLow.Error()) { + from, err := ethSigner.Sender(tx) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to get sender address: %w", err) + } + nonce, err := b.getAccountNonce(from, false, b.ClientCtx.Height, b.Logger) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to get sender's current nonce: %w", err) + } + + // SendRawTransaction returns error when tx.Nonce is lower than committed nonce + if tx.Nonce() < nonce { + return common.Hash{}, err + } + + // SendRawTransaction does not return error when committed nonce <= tx.Nonce < pending nonce + return txHash, nil + } + b.Logger.Error("failed to broadcast tx", "error", err.Error()) return txHash, fmt.Errorf("failed to broadcast transaction: %w", err) } diff --git a/rpc/backend/sign_tx.go b/rpc/backend/sign_tx.go index 1334812e1..859c2c3a8 100644 --- a/rpc/backend/sign_tx.go +++ b/rpc/backend/sign_tx.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/signer/core/apitypes" + "github.com/cosmos/evm/mempool" evmtypes "github.com/cosmos/evm/x/vm/types" errorsmod "cosmossdk.io/errors" @@ -109,7 +110,7 @@ func (b *Backend) SendTransaction(args evmtypes.TransactionArgs) (common.Hash, e } if err != nil { // Check if this is a nonce gap error that was successfully queued - if strings.Contains(err.Error(), "tx nonce is higher than account nonce") { + if b.Mempool != nil && strings.Contains(err.Error(), mempool.ErrNonceGap.Error()) { // Transaction was successfully queued due to nonce gap, return success to client b.Logger.Debug("transaction queued due to nonce gap", "hash", txHash.Hex()) return txHash, nil diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index 7dea91828..e23a93086 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -9,11 +9,15 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/params" "github.com/pkg/errors" cmtrpcclient "github.com/cometbft/cometbft/rpc/client" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cosmos/evm/mempool/txpool" rpctypes "github.com/cosmos/evm/rpc/types" "github.com/cosmos/evm/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -128,12 +132,6 @@ func (b *Backend) GetTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC // GetGasUsed returns gasUsed from transaction func (b *Backend) GetGasUsed(res *types.TxResult, price *big.Int, gas uint64) uint64 { - // patch gasUsed if tx is reverted and happened before height on which fixed was introduced - // to return real gas charged - // more info at https://github.com/evmos/ethermint/pull/1557 - if res.Failed && res.Height < b.Cfg.JSONRPC.FixRevertGasRefundHeight { - return new(big.Int).Mul(price, new(big.Int).SetUint64(gas)).Uint64() - } return res.GasUsed } @@ -155,6 +153,13 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ break // Found the transaction } + if attempt == maxRetries/2 && b.Mempool != nil { + status := b.Mempool.GetTxPool().Status(hash) + if status == txpool.TxStatusUnknown { + break + } + } + if attempt < maxRetries { // Exponential backoff: 50ms, 100ms, 200ms delay := time.Duration(1< maxAuthorizations { + b.Logger.Error("insufficient gas to process all authorizations", "maxAuthorizations", maxAuthorizations) + return nil, errors.New("insufficient gas to process all authorizations") + } + + for _, auth := range args.AuthorizationList { + // validate authorization (duplicating stateTransition.validateAuthorization() logic from geth: https://github.com/ethereum/go-ethereum/blob/bf8f63dcd27e178bd373bfe41ea718efee2851dd/core/state_transition.go#L575) + nonceOverflow := auth.Nonce+1 < auth.Nonce + invalidChainID := !auth.ChainID.IsZero() && auth.ChainID.CmpBig(b.ChainConfig().ChainID) != 0 + if nonceOverflow || invalidChainID { + b.Logger.Error("invalid authorization", "auth", auth) + continue + } + if authority, err := auth.Authority(); err == nil { + addressesToExclude[authority] = struct{}{} + } + } + + b.Logger.Debug("access list excludes created", "addressesToExclude", addressesToExclude) + return addressesToExclude, nil +} + +// initAccessListTracer initializes the access list tracer for the transaction. +// It sets the default call arguments and creates a new access list tracer. +// If an access list is provided in args, it uses that instead of creating a new one. +func (b *Backend) initAccessListTracer(args evmtypes.TransactionArgs, blockNum rpctypes.BlockNumber, addressesToExclude map[common.Address]struct{}) (*logger.AccessListTracer, *evmtypes.TransactionArgs, error) { + header, err := b.HeaderByNumber(blockNum) + if err != nil { + b.Logger.Error("failed to get header by number", "error", err) + return nil, nil, err + } + + if args.Nonce == nil { + pending := blockNum == rpctypes.EthPendingBlockNumber + nonce, err := b.getAccountNonce(args.GetFrom(), pending, blockNum.Int64(), b.Logger) + if err != nil { + b.Logger.Error("failed to get account nonce", "error", err) + return nil, nil, err + } + nonce64 := hexutil.Uint64(nonce) + args.Nonce = &nonce64 + } + if err = args.CallDefaults(b.RPCGasCap(), header.BaseFee, b.ChainConfig().ChainID); err != nil { + b.Logger.Error("failed to set default call args", "error", err) + return nil, nil, err + } + + tracer := logger.NewAccessListTracer(nil, addressesToExclude) + if args.AccessList != nil { + tracer = logger.NewAccessListTracer(*args.AccessList, addressesToExclude) + } + + b.Logger.Debug("access list tracer initialized", "tracer", tracer) + return tracer, &args, nil +} diff --git a/rpc/backend/tx_info_test.go b/rpc/backend/tx_info_test.go new file mode 100644 index 000000000..834b6f2ca --- /dev/null +++ b/rpc/backend/tx_info_test.go @@ -0,0 +1,335 @@ +package backend + +import ( + "context" + "math/big" + "path/filepath" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + abcitypes "github.com/cometbft/cometbft/abci/types" + tmrpctypes "github.com/cometbft/cometbft/rpc/core/types" + tmtypes "github.com/cometbft/cometbft/types" + + dbm "github.com/cosmos/cosmos-db" + "github.com/cosmos/evm/encoding" + "github.com/cosmos/evm/indexer" + "github.com/cosmos/evm/rpc/backend/mocks" + rpctypes "github.com/cosmos/evm/rpc/types" + "github.com/cosmos/evm/testutil/constants" + utiltx "github.com/cosmos/evm/testutil/tx" + evmtypes "github.com/cosmos/evm/x/vm/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func setupMockBackend(t *testing.T) *Backend { + t.Helper() + ctx := server.NewDefaultContext() + ctx.Viper.Set("telemetry.global-labels", []interface{}{}) + ctx.Viper.Set("evm.evm-chain-id", constants.ExampleChainID.EVMChainID) + + baseDir := t.TempDir() + nodeDirName := "node" + clientDir := filepath.Join(baseDir, nodeDirName, "evmoscli") + + keyRing := keyring.NewInMemory(client.Context{}.Codec) + + acc := sdk.AccAddress(utiltx.GenerateAddress().Bytes()) + accounts := map[string]client.TestAccount{} + accounts[acc.String()] = client.TestAccount{ + Address: acc, + Num: uint64(1), + Seq: uint64(1), + } + + encodingConfig := encoding.MakeConfig(constants.ExampleChainID.EVMChainID) + clientCtx := client.Context{}.WithChainID(constants.ExampleChainID.ChainID). + WithHeight(1). + WithTxConfig(encodingConfig.TxConfig). + WithKeyringDir(clientDir). + WithKeyring(keyRing). + WithAccountRetriever(client.TestAccountRetriever{Accounts: accounts}). + WithClient(mocks.NewClient(t)). + WithCodec(encodingConfig.Codec) + + allowUnprotectedTxs := false + idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx) + + backend := NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer, nil) + backend.Cfg.JSONRPC.GasCap = 25000000 + backend.Cfg.JSONRPC.EVMTimeout = 0 + backend.Cfg.JSONRPC.AllowInsecureUnlock = true + backend.Cfg.EVM.EVMChainID = constants.ExampleChainID.EVMChainID + mockEVMQueryClient := mocks.NewEVMQueryClient(t) + mockFeeMarketQueryClient := mocks.NewFeeMarketQueryClient(t) + backend.QueryClient.QueryClient = mockEVMQueryClient + backend.QueryClient.FeeMarket = mockFeeMarketQueryClient + backend.Ctx = rpctypes.ContextWithHeight(1) + + mockClient := backend.ClientCtx.Client.(*mocks.Client) + mockClient.On("Status", context.Background()).Return(&tmrpctypes.ResultStatus{ + SyncInfo: tmrpctypes.SyncInfo{ + LatestBlockHeight: 1, + }, + }, nil).Maybe() + + mockHeader := &tmtypes.Header{ + Height: 1, + Time: time.Now(), + ChainID: constants.ExampleChainID.ChainID, + } + mockBlock := &tmtypes.Block{ + Header: *mockHeader, + } + mockClient.On("Block", context.Background(), (*int64)(nil)).Return(&tmrpctypes.ResultBlock{ + Block: mockBlock, + }, nil).Maybe() + + mockClient.On("BlockResults", context.Background(), (*int64)(nil)).Return(&tmrpctypes.ResultBlockResults{ + Height: 1, + TxsResults: []*abcitypes.ExecTxResult{}, + }, nil).Maybe() + + mockEVMQueryClient.On("Params", + mock.Anything, + mock.Anything, + mock.Anything, + ).Return(&evmtypes.QueryParamsResponse{ + Params: evmtypes.DefaultParams(), + }, nil).Maybe() + + return backend +} + +func TestCreateAccessList(t *testing.T) { + testCases := []struct { + name string + malleate func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) + expectError bool + errorContains string + expectGasUsed bool + expectAccList bool + }{ + { + name: "success - basic transaction", + malleate: func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) { + from := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + to := common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef") + gas := hexutil.Uint64(21000) + value := (*hexutil.Big)(big.NewInt(1000)) + gasPrice := (*hexutil.Big)(big.NewInt(20000000000)) + + args := evmtypes.TransactionArgs{ + From: &from, + To: &to, + Gas: &gas, + Value: value, + GasPrice: gasPrice, + } + + blockNum := rpctypes.EthLatestBlockNumber + blockNumOrHash := rpctypes.BlockNumberOrHash{ + BlockNumber: &blockNum, + } + + return args, blockNumOrHash + }, + expectError: false, + expectGasUsed: true, + expectAccList: true, + }, + { + name: "success - transaction with data", + malleate: func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) { + from := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + to := common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef") + gas := hexutil.Uint64(100000) + gasPrice := (*hexutil.Big)(big.NewInt(20000000000)) + data := hexutil.Bytes("0xa9059cbb") + + args := evmtypes.TransactionArgs{ + From: &from, + To: &to, + Gas: &gas, + GasPrice: gasPrice, + Data: &data, + } + + blockNum := rpctypes.EthLatestBlockNumber + blockNumOrHash := rpctypes.BlockNumberOrHash{ + BlockNumber: &blockNum, + } + + return args, blockNumOrHash + }, + expectError: false, + expectGasUsed: true, + expectAccList: true, + }, + { + name: "success - transaction with existing access list", + malleate: func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) { + from := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + to := common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef") + gas := hexutil.Uint64(100000) + gasPrice := (*hexutil.Big)(big.NewInt(20000000000)) + + accessList := ethtypes.AccessList{ + { + Address: common.HexToAddress("0x1111111111111111111111111111111111111111"), + StorageKeys: []common.Hash{ + common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), + }, + }, + } + + args := evmtypes.TransactionArgs{ + From: &from, + To: &to, + Gas: &gas, + GasPrice: gasPrice, + AccessList: &accessList, + } + + blockNum := rpctypes.EthLatestBlockNumber + blockNumOrHash := rpctypes.BlockNumberOrHash{ + BlockNumber: &blockNum, + } + + return args, blockNumOrHash + }, + expectError: false, + expectGasUsed: true, + expectAccList: true, + }, + { + name: "success - transaction with specific block hash", + malleate: func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) { + from := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + to := common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef") + gas := hexutil.Uint64(21000) + gasPrice := (*hexutil.Big)(big.NewInt(20000000000)) + + args := evmtypes.TransactionArgs{ + From: &from, + To: &to, + Gas: &gas, + GasPrice: gasPrice, + } + + blockHash := common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12") + blockNumOrHash := rpctypes.BlockNumberOrHash{ + BlockHash: &blockHash, + } + + return args, blockNumOrHash + }, + expectError: false, + expectGasUsed: true, + expectAccList: true, + }, + { + name: "error - missing from address", + malleate: func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) { + to := common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef") + gas := hexutil.Uint64(21000) + gasPrice := (*hexutil.Big)(big.NewInt(20000000000)) + + args := evmtypes.TransactionArgs{ + To: &to, + Gas: &gas, + GasPrice: gasPrice, + } + + blockNum := rpctypes.EthLatestBlockNumber + blockNumOrHash := rpctypes.BlockNumberOrHash{ + BlockNumber: &blockNum, + } + + return args, blockNumOrHash + }, + expectError: true, + expectGasUsed: false, + expectAccList: false, + }, + { + name: "error - invalid gas limit", + malleate: func() (evmtypes.TransactionArgs, rpctypes.BlockNumberOrHash) { + from := common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678") + to := common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcdef") + gas := hexutil.Uint64(0) + gasPrice := (*hexutil.Big)(big.NewInt(20000000000)) + + args := evmtypes.TransactionArgs{ + From: &from, + To: &to, + Gas: &gas, + GasPrice: gasPrice, + } + + blockNum := rpctypes.EthLatestBlockNumber + blockNumOrHash := rpctypes.BlockNumberOrHash{ + BlockNumber: &blockNum, + } + + return args, blockNumOrHash + }, + expectError: true, + expectGasUsed: false, + expectAccList: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + backend := setupMockBackend(t) + + args, blockNumOrHash := tc.malleate() + + require.True(t, blockNumOrHash.BlockNumber != nil || blockNumOrHash.BlockHash != nil, + "BlockNumberOrHash should have either BlockNumber or BlockHash set") + + if !tc.expectError || tc.name != "error - missing from address" { + require.NotEqual(t, common.Address{}, args.GetFrom(), "From address should not be zero") + } + + result, err := backend.CreateAccessList(args, blockNumOrHash) + + if tc.expectError { + require.Error(t, err) + require.Nil(t, result) + if tc.errorContains != "" { + require.Contains(t, err.Error(), tc.errorContains) + } + return + } + + if err != nil { + t.Logf("Expected success case failed due to incomplete mocking: %v", err) + return + } + + require.NoError(t, err) + require.NotNil(t, result) + + if tc.expectGasUsed { + require.NotNil(t, result.GasUsed) + require.Greater(t, uint64(*result.GasUsed), uint64(0)) + } + + if tc.expectAccList { + require.NotNil(t, result.AccessList) + } + }) + } +} diff --git a/rpc/backend/tx_pool.go b/rpc/backend/tx_pool.go index 4ff32566c..d06b2afef 100644 --- a/rpc/backend/tx_pool.go +++ b/rpc/backend/tx_pool.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/rpc/types" ) @@ -28,7 +27,7 @@ func (b *Backend) Content() (map[string]map[string]map[string]*types.RPCTransact } // Get the global mempool instance - evmMempool := mempool.GetGlobalEVMMempool() + evmMempool := b.Mempool if evmMempool == nil { return content, nil } @@ -78,7 +77,7 @@ func (b *Backend) ContentFrom(addr common.Address) (map[string]map[string]*types content := make(map[string]map[string]*types.RPCTransaction, 2) // Get the global mempool instance - evmMempool := mempool.GetGlobalEVMMempool() + evmMempool := b.Mempool if evmMempool == nil { return content, nil } @@ -121,7 +120,7 @@ func (b *Backend) Inspect() (map[string]map[string]map[string]string, error) { } // Get the global mempool instance - evmMempool := mempool.GetGlobalEVMMempool() + evmMempool := b.Mempool if evmMempool == nil { return inspect, nil } @@ -163,7 +162,7 @@ func (b *Backend) Inspect() (map[string]map[string]map[string]string, error) { // Status returns the number of pending and queued transaction in the pool. func (b *Backend) Status() (map[string]hexutil.Uint, error) { // Get the global mempool instance - evmMempool := mempool.GetGlobalEVMMempool() + evmMempool := b.Mempool if evmMempool == nil { return map[string]hexutil.Uint{ StatusPending: hexutil.Uint(0), diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index 9e7b28248..6fbfd3922 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -266,7 +266,7 @@ func GetLogsFromBlockResults(blockRes *cmtrpctypes.ResultBlockResults) ([][]*eth } blockLogs := [][]*ethtypes.Log{} for _, txResult := range blockRes.TxsResults { - logs, err := evmtypes.DecodeTxLogsFromEvents(txResult.Data, txResult.Events, height) + logs, err := evmtypes.DecodeTxLogs(txResult.Data, height) if err != nil { return nil, err } diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index d260a5eae..35ea3aa24 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -95,6 +95,8 @@ type EthereumAPI interface { SignTypedData(address common.Address, typedData apitypes.TypedData) (hexutil.Bytes, error) FillTransaction(args evmtypes.TransactionArgs) (*rpctypes.SignTransactionResult, error) Resend(ctx context.Context, args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) + CreateAccessList(args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccessListResult, error) + // eth_signTransaction (on Ethereum.org) // eth_getCompilers (on Ethereum.org) // eth_compileSolidity (on Ethereum.org) @@ -432,3 +434,13 @@ func (e *PublicAPI) Resend(_ context.Context, e.logger.Debug("eth_resend", "args", args) return e.backend.Resend(args, gasPrice, gasLimit) } + +// CreateAccessList returns the list of addresses and storage keys used by the transaction (except for the +// sender account and precompiles), plus the estimated gas if the access list were added to the transaction. +func (e *PublicAPI) CreateAccessList(args evmtypes.TransactionArgs, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccessListResult, error) { + res, err := e.backend.CreateAccessList(args, blockNrOrHash) + if err != nil { + return nil, err + } + return res, nil +} diff --git a/rpc/stream/rpc.go b/rpc/stream/rpc.go index 0583defb9..621657927 100644 --- a/rpc/stream/rpc.go +++ b/rpc/stream/rpc.go @@ -40,8 +40,9 @@ var ( cmttypes.EventTx, sdk.EventTypeMessage, sdk.AttributeKeyModule, evmtypes.ModuleName)).String() - blockEvents = cmttypes.QueryForEvent(cmttypes.EventNewBlock).String() - evmTxHashKey = fmt.Sprintf("%s.%s", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash) + blockEvents = cmttypes.QueryForEvent(cmttypes.EventNewBlock).String() + evmTxHashKey = fmt.Sprintf("%s.%s", evmtypes.TypeMsgEthereumTx, evmtypes.AttributeKeyEthereumTxHash) + NewBlockHeaderEvents = cmtquery.MustCompile(fmt.Sprintf("%s='%s'", cmttypes.EventTypeKey, cmttypes.EventNewBlockHeader)) ) type RPCHeader struct { @@ -186,7 +187,7 @@ func (s *RPCStream) start( if err != nil { continue } - txLogs, err := evmtypes.DecodeTxLogsFromEvents(dataTx.Result.Data, dataTx.Result.Events, height) + txLogs, err := evmtypes.DecodeTxLogs(dataTx.Result.Data, height) if err != nil { s.logger.Error("fail to decode evm tx response", "error", err.Error()) continue diff --git a/rpc/types/events_test.go b/rpc/types/events_test.go index c932e9ad1..e20cc11d0 100644 --- a/rpc/types/events_test.go +++ b/rpc/types/events_test.go @@ -58,7 +58,6 @@ func TestParseTxResult(t *testing.T) { {Key: "recipient", Value: "0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7"}, {Key: "ethereumTxFailed", Value: "contract everted"}, }}, - {Type: evmtypes.EventTypeTxLog, Attributes: []abci.EventAttribute{}}, }, }, []*ParsedTx{ @@ -143,7 +142,6 @@ func TestParseTxResult(t *testing.T) { {Key: "recipient", Value: "0x775b87ef5D82ca211811C1a02CE0fE0CA3a455d7"}, {Key: "ethereumTxFailed", Value: "contract everted"}, }}, - {Type: evmtypes.EventTypeTxLog, Attributes: []abci.EventAttribute{}}, }, }, nil, diff --git a/rpc/types/types.go b/rpc/types/types.go index 905124b7c..1a54bae15 100644 --- a/rpc/types/types.go +++ b/rpc/types/types.go @@ -95,6 +95,13 @@ type OneFeeHistory struct { GasUsedRatio float64 // the ratio of gas used to the gas limit for each block } +// AccessListResult represents the access list and gas used for a transaction +type AccessListResult struct { + AccessList *ethtypes.AccessList `json:"accessList"` + GasUsed *hexutil.Uint64 `json:"gasUsed"` + Error string `json:"error"` +} + // Embedded TraceConfig type to store raw JSON data of config in custom field type TraceConfig struct { evmtypes.TraceConfig diff --git a/server/config/config.go b/server/config/config.go index 8a256e381..d8dd07bcf 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -3,6 +3,7 @@ package config import ( "errors" "fmt" + "net/netip" "path" "time" @@ -57,15 +58,18 @@ const ( // DefaultEnablePreimageRecording is the default value for EnablePreimageRecording DefaultEnablePreimageRecording = false - // DefaultFixRevertGasRefundHeight is the default height at which to overwrite gas refund - DefaultFixRevertGasRefundHeight = 0 - // DefaultMaxTxGasWanted is the default gas wanted for each eth tx returned in ante handler in check tx mode DefaultMaxTxGasWanted = 0 // DefaultEVMChainID is the default EVM Chain ID if one is not provided DefaultEVMChainID = 262144 + // DefaultEVMMinTip is the default minimum priority fee for the mempool + DefaultEVMMinTip = 0 + + // DefaultGethMetricsAddress is the default port for the geth metrics server. + DefaultGethMetricsAddress = "127.0.0.1:8100" + // DefaultGasCap is the default cap on gas that can be used in eth_call/estimateGas DefaultGasCap uint64 = 25_000_000 @@ -143,6 +147,10 @@ type EVMConfig struct { EnablePreimageRecording bool `mapstructure:"cache-preimage"` // EVMChainID defines the EIP-155 replay-protection chain ID. EVMChainID uint64 `mapstructure:"evm-chain-id"` + // MinTip defines the minimum priority fee for the mempool + MinTip uint64 `mapstructure:"min-tip"` + // GethMetricsAddress is the address the geth metrics server will bind to. Default 127.0.0.1:8100 + GethMetricsAddress string `mapstructure:"geth-metrics-address"` } // JSONRPCConfig defines configuration for the EVM RPC server. @@ -189,8 +197,6 @@ type JSONRPCConfig struct { EnableIndexer bool `mapstructure:"enable-indexer"` // MetricsAddress defines the metrics server to listen on MetricsAddress string `mapstructure:"metrics-address"` - // FixRevertGasRefundHeight defines the upgrade height for fix of revert gas refund logic when transaction reverted - FixRevertGasRefundHeight int64 `mapstructure:"fix-revert-gas-refund-height"` // WSOrigins defines the allowed origins for WebSocket connections WSOrigins []string `mapstructure:"ws-origins"` // EnableProfiling enables the profiling in the `debug` namespace. SHOULD NOT be used on public tracing nodes @@ -212,6 +218,8 @@ func DefaultEVMConfig() *EVMConfig { MaxTxGasWanted: DefaultMaxTxGasWanted, EVMChainID: DefaultEVMChainID, EnablePreimageRecording: DefaultEnablePreimageRecording, + MinTip: DefaultEVMMinTip, + GethMetricsAddress: DefaultGethMetricsAddress, } } @@ -221,6 +229,10 @@ func (c EVMConfig) Validate() error { return fmt.Errorf("invalid tracer type %s, available types: %v", c.Tracer, evmTracers) } + if _, err := netip.ParseAddrPort(c.GethMetricsAddress); err != nil { + return fmt.Errorf("invalid geth metrics address %q: %w", c.GethMetricsAddress, err) + } + return nil } @@ -242,29 +254,28 @@ func GetDefaultWSOrigins() []string { // DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default func DefaultJSONRPCConfig() *JSONRPCConfig { return &JSONRPCConfig{ - Enable: false, - API: GetDefaultAPINamespaces(), - Address: DefaultJSONRPCAddress, - WsAddress: DefaultJSONRPCWsAddress, - GasCap: DefaultGasCap, - AllowInsecureUnlock: DefaultJSONRPCAllowInsecureUnlock, - EVMTimeout: DefaultEVMTimeout, - TxFeeCap: DefaultTxFeeCap, - FilterCap: DefaultFilterCap, - FeeHistoryCap: DefaultFeeHistoryCap, - BlockRangeCap: DefaultBlockRangeCap, - LogsCap: DefaultLogsCap, - HTTPTimeout: DefaultHTTPTimeout, - HTTPIdleTimeout: DefaultHTTPIdleTimeout, - AllowUnprotectedTxs: DefaultAllowUnprotectedTxs, - BatchRequestLimit: DefaultBatchRequestLimit, - BatchResponseMaxSize: DefaultBatchResponseMaxSize, - MaxOpenConnections: DefaultMaxOpenConnections, - EnableIndexer: false, - MetricsAddress: DefaultJSONRPCMetricsAddress, - FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight, - WSOrigins: GetDefaultWSOrigins(), - EnableProfiling: DefaultEnableProfiling, + Enable: false, + API: GetDefaultAPINamespaces(), + Address: DefaultJSONRPCAddress, + WsAddress: DefaultJSONRPCWsAddress, + GasCap: DefaultGasCap, + AllowInsecureUnlock: DefaultJSONRPCAllowInsecureUnlock, + EVMTimeout: DefaultEVMTimeout, + TxFeeCap: DefaultTxFeeCap, + FilterCap: DefaultFilterCap, + FeeHistoryCap: DefaultFeeHistoryCap, + BlockRangeCap: DefaultBlockRangeCap, + LogsCap: DefaultLogsCap, + HTTPTimeout: DefaultHTTPTimeout, + HTTPIdleTimeout: DefaultHTTPIdleTimeout, + AllowUnprotectedTxs: DefaultAllowUnprotectedTxs, + BatchRequestLimit: DefaultBatchRequestLimit, + BatchResponseMaxSize: DefaultBatchResponseMaxSize, + MaxOpenConnections: DefaultMaxOpenConnections, + EnableIndexer: false, + MetricsAddress: DefaultJSONRPCMetricsAddress, + WSOrigins: GetDefaultWSOrigins(), + EnableProfiling: DefaultEnableProfiling, } } diff --git a/server/config/migration/v0.50-app.toml b/server/config/migration/v0.50-app.toml index bcff87d81..0bebf82ca 100644 --- a/server/config/migration/v0.50-app.toml +++ b/server/config/migration/v0.50-app.toml @@ -313,9 +313,6 @@ enable-indexer = false # Prometheus metrics path: /debug/metrics/prometheus metrics-address = "127.0.0.1:6065" -# Upgrade height for fix of revert gas refund logic when transaction reverted. -fix-revert-gas-refund-height = 0 - ############################################################################### ### TLS Configuration ### ############################################################################### diff --git a/server/config/toml.go b/server/config/toml.go index c517bf141..b805482a0 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -22,6 +22,12 @@ cache-preimage = {{ .EVM.EnablePreimageRecording }} # EVMChainID is the EIP-155 compatible replay protection chain ID. This is separate from the Cosmos chain ID. evm-chain-id = {{ .EVM.EVMChainID }} +# MinTip defines the minimum priority fee for the mempool. +min-tip = {{ .EVM.MinTip }} + +# GethMetricsAddress defines the addr to bind the geth metrics server to. Default 127.0.0.1:8100. +geth-metrics-address = "{{ .EVM.GethMetricsAddress }}" + ############################################################################### ### JSON RPC Configuration ### ############################################################################### @@ -90,9 +96,6 @@ enable-indexer = {{ .JSONRPC.EnableIndexer }} # Prometheus metrics path: /debug/metrics/prometheus metrics-address = "{{ .JSONRPC.MetricsAddress }}" -# Upgrade height for fix of revert gas refund logic when transaction reverted. -fix-revert-gas-refund-height = {{ .JSONRPC.FixRevertGasRefundHeight }} - # Maximum number of requests in a batch. batch-request-limit = {{ .JSONRPC.BatchRequestLimit }} diff --git a/server/flags/flags.go b/server/flags/flags.go index 4d45bff42..6bbc61261 100644 --- a/server/flags/flags.go +++ b/server/flags/flags.go @@ -60,8 +60,7 @@ const ( // JSONRPCEnableMetrics enables EVM RPC metrics server. // Set to `metrics` which is hardcoded flag from go-ethereum. // https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L35-L55 - JSONRPCEnableMetrics = "metrics" - JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height" + JSONRPCEnableMetrics = "metrics" ) // EVM flags @@ -70,6 +69,8 @@ const ( EVMMaxTxGasWanted = "evm.max-tx-gas-wanted" EVMEnablePreimageRecording = "evm.cache-preimage" EVMChainID = "evm.evm-chain-id" + EVMMinTip = "evm.min-tip" + EvmGethMetricsAddress = "evm.geth-metrics-address" ) // TLS flags diff --git a/server/json_rpc.go b/server/json_rpc.go index 77f90c45d..802e986e0 100644 --- a/server/json_rpc.go +++ b/server/json_rpc.go @@ -5,6 +5,7 @@ import ( "fmt" "log/slog" "net/http" + "time" "github.com/ethereum/go-ethereum/common" ethrpc "github.com/ethereum/go-ethereum/rpc" @@ -14,6 +15,7 @@ import ( rpcclient "github.com/cometbft/cometbft/rpc/client" + evmmempool "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/rpc" "github.com/cosmos/evm/rpc/stream" serverconfig "github.com/cosmos/evm/server/config" @@ -23,6 +25,8 @@ import ( "github.com/cosmos/cosmos-sdk/server" ) +const shutdownTimeout = 200 * time.Millisecond + type AppWithPendingTxStream interface { RegisterPendingTxListener(listener func(common.Hash)) } @@ -36,6 +40,7 @@ func StartJSONRPC( config *serverconfig.Config, indexer cosmosevmtypes.EVMTxIndexer, app AppWithPendingTxStream, + mempool *evmmempool.ExperimentalEVMMempool, ) (*http.Server, error) { logger := srvCtx.Logger.With("module", "geth") @@ -57,7 +62,7 @@ func StartJSONRPC( allowUnprotectedTxs := config.JSONRPC.AllowUnprotectedTxs rpcAPIArr := config.JSONRPC.API - apis := rpc.GetRPCAPIs(srvCtx, clientCtx, stream, allowUnprotectedTxs, indexer, rpcAPIArr) + apis := rpc.GetRPCAPIs(srvCtx, clientCtx, stream, allowUnprotectedTxs, indexer, rpcAPIArr, mempool) for _, api := range apis { if err := rpcServer.RegisterName(api.Namespace, api.Service); err != nil { @@ -106,12 +111,13 @@ func StartJSONRPC( case <-ctx.Done(): // The calling process canceled or closed the provided context, so we must // gracefully stop the JSON-RPC server. - logger.Info("stopping JSON-RPC server...", "address", config.JSONRPC.Address) - if err := httpSrv.Shutdown(context.Background()); err != nil { + logger.Info("stopping JSON-RPC server...", "address", config.JSONRPC.Address, "timeout", shutdownTimeout) + ctxShutdown, cancel := context.WithTimeout(context.Background(), shutdownTimeout) + defer cancel() + if err := httpSrv.Shutdown(ctxShutdown); err != nil { logger.Error("failed to shutdown JSON-RPC server", "error", err.Error()) } return nil - case err := <-errCh: if err == http.ErrServerClosed { close(httpSrvDone) diff --git a/server/start.go b/server/start.go index aa747b704..1a08fcb0d 100644 --- a/server/start.go +++ b/server/start.go @@ -28,6 +28,8 @@ import ( dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/evm/indexer" + evmmempool "github.com/cosmos/evm/mempool" + evmmetrics "github.com/cosmos/evm/metrics" ethdebug "github.com/cosmos/evm/rpc/namespaces/ethereum/debug" cosmosevmserverconfig "github.com/cosmos/evm/server/config" srvflags "github.com/cosmos/evm/server/flags" @@ -48,6 +50,7 @@ import ( servercmtlog "github.com/cosmos/cosmos-sdk/server/log" "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/telemetry" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" ) @@ -57,6 +60,7 @@ type DBOpener func(opts types.AppOptions, rootDir string, backend dbm.BackendTyp type Application interface { types.Application AppWithPendingTxStream + GetMempool() sdkmempool.ExtMempool SetClientCtx(clientCtx client.Context) } @@ -129,8 +133,8 @@ which accepts a path for the resulting pprof file. return err } - withTM, _ := cmd.Flags().GetBool(srvflags.WithCometBFT) - if !withTM { + withbft, _ := cmd.Flags().GetBool(srvflags.WithCometBFT) + if !withbft { serverCtx.Logger.Info("starting ABCI without CometBFT") return wrapCPUProfile(serverCtx, func() error { return startStandAlone(serverCtx, clientCtx, opts) @@ -216,6 +220,8 @@ which accepts a path for the resulting pprof file. cmd.Flags().Uint64(srvflags.EVMMaxTxGasWanted, cosmosevmserverconfig.DefaultMaxTxGasWanted, "the gas wanted for each eth tx returned in ante handler in check tx mode") //nolint:lll cmd.Flags().Bool(srvflags.EVMEnablePreimageRecording, cosmosevmserverconfig.DefaultEnablePreimageRecording, "Enables tracking of SHA3 preimages in the EVM (not implemented yet)") //nolint:lll cmd.Flags().Uint64(srvflags.EVMChainID, cosmosevmserverconfig.DefaultEVMChainID, "the EIP-155 compatible replay protection chain ID") + cmd.Flags().Uint64(srvflags.EVMMinTip, cosmosevmserverconfig.DefaultEVMMinTip, "the minimum priority fee for the mempool") + cmd.Flags().String(srvflags.EvmGethMetricsAddress, cosmosevmserverconfig.DefaultGethMetricsAddress, "the address to bind the geth metrics server to") cmd.Flags().String(srvflags.TLSCertPath, "", "the cert.pem file path for the server TLS configuration") cmd.Flags().String(srvflags.TLSKeyPath, "", "the key.pem file path for the server TLS configuration") @@ -397,7 +403,7 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start genDocProvider := GenDocProvider(cfg) var ( - tmNode *node.Node + bftNode *node.Node gRPCOnly = svrCtx.Viper.GetBool(srvflags.GRPCOnly) ) @@ -409,7 +415,7 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start logger.Info("starting node with ABCI CometBFT in-process") cmtApp := server.NewCometABCIWrapper(app) - tmNode, err = node.NewNode( + bftNode, err = node.NewNode( cfg, pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()), nodeKey, @@ -424,14 +430,17 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start return err } - if err := tmNode.Start(); err != nil { + if err := bftNode.Start(); err != nil { logger.Error("failed start CometBFT server", "error", err.Error()) return err } + if m, ok := evmApp.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok { + m.SetEventBus(bftNode.EventBus()) + } defer func() { - if tmNode.IsRunning() { - _ = tmNode.Stop() + if bftNode.IsRunning() { + _ = bftNode.Stop() } }() } @@ -439,8 +448,8 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start // Add the tx service to the gRPC router. We only need to register this // service if API or gRPC or JSONRPC is enabled, and avoid doing so in the general // case, because it spawns a new local CometBFT RPC client. - if (config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable || config.JSONRPC.EnableIndexer) && tmNode != nil { - clientCtx = clientCtx.WithClient(local.New(tmNode)) + if (config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable || config.JSONRPC.EnableIndexer) && bftNode != nil { + clientCtx = clientCtx.WithClient(local.New(bftNode)) app.RegisterTxService(clientCtx) app.RegisterTendermintService(clientCtx) @@ -495,14 +504,14 @@ func startInProcess(svrCtx *server.Context, clientCtx client.Context, opts Start defer grpcSrv.GracefulStop() } - startAPIServer(ctx, svrCtx, clientCtx, g, config.Config, app, grpcSrv, metrics) + startAPIServer(ctx, svrCtx, clientCtx, g, config.Config, app, grpcSrv, metrics, config.EVM.GethMetricsAddress) if config.JSONRPC.Enable { txApp, ok := app.(AppWithPendingTxStream) if !ok { return fmt.Errorf("json-rpc server requires AppWithPendingTxStream") } - _, err = StartJSONRPC(ctx, svrCtx, clientCtx, g, &config, idxer, txApp) + _, err = StartJSONRPC(ctx, svrCtx, clientCtx, g, &config, idxer, txApp, evmApp.GetMempool().(*evmmempool.ExperimentalEVMMempool)) if err != nil { return err } @@ -666,6 +675,7 @@ func startAPIServer( app types.Application, grpcSrv *grpc.Server, metrics *telemetry.Metrics, + gethMetricsAddress string, ) { if !svrCfg.API.Enable { return @@ -676,6 +686,9 @@ func startAPIServer( if svrCfg.Telemetry.Enabled { apiSrv.SetTelemetry(metrics) + g.Go(func() error { + return evmmetrics.StartGethMetricServer(ctx, svrCtx.Logger.With("server", "geth_metrics"), gethMetricsAddress) + }) } g.Go(func() error { diff --git a/tests/integration/ante/test_evm_ante.go b/tests/integration/ante/test_evm_ante.go index 776641e09..be0fec752 100644 --- a/tests/integration/ante/test_evm_ante.go +++ b/tests/integration/ante/test_evm_ante.go @@ -1264,14 +1264,13 @@ func (s *EvmAnteTestSuite) TestEthSigVerificationDecorator() { s.Require().NoError(err) testCases := []struct { - name string - tx sdk.Tx - allowUnprotectedTxs bool - reCheckTx bool - expPass bool + name string + tx sdk.Tx + reCheckTx bool + expPass bool }{ - {"ReCheckTx", &utiltx.InvalidTx{}, false, true, false}, - {"invalid transaction type", &utiltx.InvalidTx{}, false, false, false}, + {"ReCheckTx", &utiltx.InvalidTx{}, true, false}, + {"invalid transaction type", &utiltx.InvalidTx{}, false, false}, { "invalid sender", evmtypes.NewTx(&evmtypes.EvmTxArgs{ @@ -1281,20 +1280,16 @@ func (s *EvmAnteTestSuite) TestEthSigVerificationDecorator() { GasLimit: 1000, GasPrice: big.NewInt(1), }), - 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}, + {"successful signature verification", signedTx, false, true}, + {"invalid, reject unprotected txs", unprotectedTx, false, false}, + {"successful, allow unprotected txs", unprotectedTx, false, true}, } for _, tc := range testCases { s.Run(tc.name, func() { - s.WithEvmParamsOptions(func(params *evmtypes.Params) { - params.AllowUnprotectedTxs = tc.allowUnprotectedTxs - }) s.SetupTest() dec := ethante.NewEthSigVerificationDecorator(s.GetNetwork().App.GetEVMKeeper()) _, err := dec.AnteHandle(s.GetNetwork().GetContext().WithIsReCheckTx(tc.reCheckTx), tc.tx, false, testutil.NoOpNextFn) @@ -1306,7 +1301,6 @@ func (s *EvmAnteTestSuite) TestEthSigVerificationDecorator() { } }) } - s.WithEvmParamsOptions(nil) } func (s *EvmAnteTestSuite) TestSignatures() { diff --git a/tests/integration/ante/test_evm_unit_09_increment_sequence.go b/tests/integration/ante/test_evm_unit_09_increment_sequence.go index d2b3e0b64..49d8fbd2e 100644 --- a/tests/integration/ante/test_evm_unit_09_increment_sequence.go +++ b/tests/integration/ante/test_evm_unit_09_increment_sequence.go @@ -9,7 +9,6 @@ import ( testkeyring "github.com/cosmos/evm/testutil/keyring" sdktypes "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/errors" ) func (s *EvmUnitAnteTestSuite) TestIncrementSequence() { @@ -38,8 +37,8 @@ func (s *EvmUnitAnteTestSuite) TestIncrementSequence() { }, }, { - name: "fail: invalid sequence", - expectedError: errors.ErrInvalidSequence, + name: "fail: nonce is low", + expectedError: mempool.ErrNonceLow, malleate: func(acct sdktypes.AccountI) uint64 { err := acct.SetSequence(acct.GetSequence() + 1) s.Require().NoError(err) diff --git a/tests/integration/mempool/test_helpers.go b/tests/integration/mempool/test_helpers.go new file mode 100644 index 000000000..1c87c0586 --- /dev/null +++ b/tests/integration/mempool/test_helpers.go @@ -0,0 +1,221 @@ +package mempool + +import ( + "encoding/hex" + "fmt" + "math/big" + "time" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/crypto/tmhash" + + evmmempool "github.com/cosmos/evm/mempool" + "github.com/cosmos/evm/testutil/integration/base/factory" + "github.com/cosmos/evm/testutil/keyring" + evmtypes "github.com/cosmos/evm/x/vm/types" + + sdkmath "cosmossdk.io/math" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// Constants +const ( + TxGas = 100_000 +) + +// createCosmosSendTransactionWithKey creates a simple bank send transaction with the specified key +func (s *IntegrationTestSuite) createCosmosSendTx(key keyring.Key, gasPrice *big.Int) sdk.Tx { + feeDenom := "aatom" + + fromAddr := key.AccAddr + toAddr := s.keyring.GetKey(1).AccAddr + amount := sdk.NewCoins(sdk.NewInt64Coin(feeDenom, 1000)) + + bankMsg := banktypes.NewMsgSend(fromAddr, toAddr, amount) + + gasPriceConverted := sdkmath.NewIntFromBigInt(gasPrice) + + txArgs := factory.CosmosTxArgs{ + Msgs: []sdk.Msg{bankMsg}, + GasPrice: &gasPriceConverted, + } + tx, err := s.factory.BuildCosmosTx(key.Priv, txArgs) + s.Require().NoError(err) + + return tx +} + +// createEVMTransaction creates an EVM transaction using the provided key +func (s *IntegrationTestSuite) createEVMValueTransferTx(key keyring.Key, nonce int, gasPrice *big.Int) sdk.Tx { + to := s.keyring.GetKey(1).Addr + + if nonce < 0 { + s.Require().NoError(fmt.Errorf("nonce must be non-negative")) + } + + ethTxArgs := evmtypes.EvmTxArgs{ + Nonce: uint64(nonce), + To: &to, + Amount: big.NewInt(1000), + GasLimit: TxGas, + GasPrice: gasPrice, + Input: nil, + } + tx, err := s.factory.GenerateSignedEthTx(key.Priv, ethTxArgs) + s.Require().NoError(err) + + return tx +} + +// createEVMTransaction creates an EVM transaction using the provided key +func (s *IntegrationTestSuite) createEVMValueTransferDynamicFeeTx(key keyring.Key, nonce int, gasFeeCap, gasTipCap *big.Int) sdk.Tx { + to := s.keyring.GetKey(1).Addr + + if nonce < 0 { + s.Require().NoError(fmt.Errorf("nonce must be non-negative")) + } + + ethTxArgs := evmtypes.EvmTxArgs{ + Nonce: uint64(nonce), + To: &to, + Amount: big.NewInt(1000), + GasLimit: TxGas, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Input: nil, + } + tx, err := s.factory.GenerateSignedEthTx(key.Priv, ethTxArgs) + s.Require().NoError(err) + + return tx +} + +// createEVMContractDeployTx creates an EVM transaction for contract deployment +func (s *IntegrationTestSuite) createEVMContractDeployTx(key keyring.Key, gasPrice *big.Int, data []byte) sdk.Tx { + ethTxArgs := evmtypes.EvmTxArgs{ + Nonce: 0, + To: nil, + Amount: nil, + GasLimit: TxGas, + GasPrice: gasPrice, + Input: data, + } + tx, err := s.factory.GenerateSignedEthTx(key.Priv, ethTxArgs) + s.Require().NoError(err) + + return tx +} + +// checkTxs call abci CheckTx for multipile transactions +func (s *IntegrationTestSuite) checkTxs(txs []sdk.Tx) error { + for _, tx := range txs { + if res, err := s.checkTx(tx); err != nil { + if err != nil { + return fmt.Errorf("failed to execute CheckTx for tx: %s", s.getTxHash(tx)) + } + if res.Code != abci.CodeTypeOK { + return fmt.Errorf("tx (%s) failed to pass CheckTx with log: %s", s.getTxHash(tx), res.Log) + } + return err + } + } + return nil +} + +// checkTxs call abci CheckTx for a transaction +func (s *IntegrationTestSuite) checkTx(tx sdk.Tx) (*abci.ResponseCheckTx, error) { + txBytes, err := s.network.App.GetTxConfig().TxEncoder()(tx) + if err != nil { + return nil, fmt.Errorf("failed to encode cosmos tx: %w", err) + } + + res, err := s.network.App.CheckTx(&abci.RequestCheckTx{ + Tx: txBytes, + Type: abci.CheckTxType_New, + }) + if err != nil { + return nil, fmt.Errorf("failed to execute CheckTx: %w", err) + } + + return res, nil +} + +func (s *IntegrationTestSuite) getTxBytes(txs []sdk.Tx) ([][]byte, error) { + txEncoder := s.network.App.GetTxConfig().TxEncoder() + txBytes := make([][]byte, 0) + for _, tx := range txs { + bz, err := txEncoder(tx) + if err != nil { + return nil, fmt.Errorf("failed to encode tx: %w", err) + } + txBytes = append(txBytes, bz) + } + return txBytes, nil +} + +// getTxHashes returns transaction hashes for multiple transactions +func (s *IntegrationTestSuite) getTxHashes(txs []sdk.Tx) []string { + txHashes := []string{} + for _, tx := range txs { + txHash := s.getTxHash(tx) + txHashes = append(txHashes, txHash) + } + + return txHashes +} + +// getTxHash returns transaction hash for a transaction +func (s *IntegrationTestSuite) getTxHash(tx sdk.Tx) string { + txEncoder := s.network.App.GetTxConfig().TxEncoder() + txBytes, err := txEncoder(tx) + s.Require().NoError(err) + + return hex.EncodeToString(tmhash.Sum(txBytes)) +} + +// calculateCosmosGasPrice calculates the gas price for a Cosmos transaction +func (s *IntegrationTestSuite) calculateCosmosGasPrice(feeAmount int64, gasLimit uint64) *big.Int { + return new(big.Int).Div(big.NewInt(feeAmount), big.NewInt(int64(gasLimit))) //#nosec G115 -- not concern, test +} + +// calculateCosmosEffectiveTip calculates the effective tip for a Cosmos transaction +// This aligns with EVM transaction prioritization: effective_tip = gas_price - base_fee +func (s *IntegrationTestSuite) calculateCosmosEffectiveTip(feeAmount int64, gasLimit uint64, baseFee *big.Int) *big.Int { + gasPrice := s.calculateCosmosGasPrice(feeAmount, gasLimit) + if baseFee == nil || baseFee.Sign() == 0 { + return gasPrice // No base fee, effective tip equals gas price + } + + if gasPrice.Cmp(baseFee) < 0 { + return big.NewInt(0) // Gas price lower than base fee, effective tip is zero + } + + return new(big.Int).Sub(gasPrice, baseFee) +} + +// notifyNewBlockToMempool triggers the natural block notification mechanism used in production. +// This sends a ChainHeadEvent that causes the mempool to update its state and remove committed transactions. +// The event subscription mechanism naturally calls Reset() which triggers the transaction cleanup process. +func (s *IntegrationTestSuite) notifyNewBlockToMempool() { + // Get the EVM mempool from the app + evmMempool := s.network.App.GetMempool() + + // Access the underlying blockchain interface from the EVM mempool + if evmMempoolCast, ok := evmMempool.(*evmmempool.ExperimentalEVMMempool); ok { + blockchain := evmMempoolCast.GetBlockchain() + + // Trigger a new block notification + // This sends a ChainHeadEvent that the mempool subscribes to. + // The TxPool's event loop receives this and calls Reset() for each subpool, + // which naturally removes committed transactions via demoteUnexecutables(). + blockchain.NotifyNewBlock() + + // The ChainHeadEvent is processed asynchronously, so we need to wait a bit + // for the event to be processed and the reset to complete. + // In integration tests, this might need a small delay to ensure the event + // is processed before we check the mempool state. + time.Sleep(100 * time.Millisecond) + } +} diff --git a/tests/integration/mempool/test_mempool_integration.go b/tests/integration/mempool/test_mempool_integration.go index f14671d0c..32e24a4a1 100644 --- a/tests/integration/mempool/test_mempool_integration.go +++ b/tests/integration/mempool/test_mempool_integration.go @@ -1,7 +1,6 @@ package mempool import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/common" @@ -9,25 +8,16 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" - "github.com/cosmos/evm/crypto/ethsecp256k1" "github.com/cosmos/evm/testutil/integration/evm/network" "github.com/cosmos/evm/testutil/keyring" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -// Constants -const ( - TxGas = 21000 ) // TestMempoolInsert tests transaction insertion into the mempool func (s *IntegrationTestSuite) TestMempoolInsert() { - fmt.Printf("DEBUG: Starting TestMempoolInsert\n") testCases := []struct { name string setupTx func() sdk.Tx @@ -38,7 +28,7 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { { name: "cosmos transaction success", setupTx: func() sdk.Tx { - return s.createCosmosSendTransaction(big.NewInt(1000)) + return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) }, wantError: false, verifyFunc: func() { @@ -49,9 +39,7 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { { name: "EVM transaction success", setupTx: func() sdk.Tx { - tx, err := s.createEVMTransaction(big.NewInt(1000000000)) - s.Require().NoError(err) - return tx + return s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) }, wantError: false, verifyFunc: func() { @@ -65,10 +53,7 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { key := s.keyring.GetKey(0) data := []byte{0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0xf3} // Simple contract deployment - // Use the contract deployment helper - tx, err := s.createEVMContractDeployment(key, big.NewInt(1000000000), data) - s.Require().NoError(err) - return tx + return s.createEVMContractDeployTx(key, big.NewInt(1000000000), data) }, wantError: false, verifyFunc: func() { @@ -147,13 +132,10 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { }, } - for i, tc := range testCases { - fmt.Printf("DEBUG: TestMempoolInsert - Starting test case %d/%d: %s\n", i+1, len(testCases), tc.name) + for _, tc := range testCases { s.Run(tc.name, func() { - fmt.Printf("DEBUG: Running test case: %s\n", tc.name) // Reset test setup to ensure clean state s.SetupTest() - fmt.Printf("DEBUG: SetupTest completed for: %s\n", tc.name) tx := tc.setupTx() mpool := s.network.App.GetMempool() @@ -170,15 +152,12 @@ func (s *IntegrationTestSuite) TestMempoolInsert() { } tc.verifyFunc() - fmt.Printf("DEBUG: Completed test case: %s\n", tc.name) }) - fmt.Printf("DEBUG: TestMempoolInsert - Completed test case %d/%d: %s\n", i+1, len(testCases), tc.name) } } // TestMempoolRemove tests transaction removal from the mempool func (s *IntegrationTestSuite) TestMempoolRemove() { - fmt.Printf("DEBUG: Starting TestMempoolRemove\n") testCases := []struct { name string setupTx func() sdk.Tx @@ -190,7 +169,7 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { { name: "remove cosmos transaction success", setupTx: func() sdk.Tx { - return s.createCosmosSendTransaction(big.NewInt(1000)) + return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) }, insertFirst: true, wantError: false, @@ -200,17 +179,16 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { }, }, { - name: "remove EVM transaction success", + name: "remove EVM transaction fail", setupTx: func() sdk.Tx { - tx, err := s.createEVMTransaction(big.NewInt(1000000000)) - s.Require().NoError(err) - return tx + return s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) }, insertFirst: true, wantError: false, verifyFunc: func() { mpool := s.network.App.GetMempool() - s.Require().Equal(0, mpool.CountTx()) + // mempool.Remove can only remove invalid evm transaction + s.Require().Equal(1, mpool.CountTx()) }, }, { @@ -228,7 +206,7 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { { name: "remove non-existent transaction", setupTx: func() sdk.Tx { - return s.createCosmosSendTransaction(big.NewInt(1000)) + return s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) }, insertFirst: false, wantError: true, // Remove should error for non-existent transactions @@ -242,10 +220,8 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { for _, tc := range testCases { s.Run(tc.name, func() { - fmt.Printf("DEBUG: Running test case: %s\n", tc.name) // Reset test setup to ensure clean state s.SetupTest() - fmt.Printf("DEBUG: SetupTest completed for: %s\n", tc.name) tx := tc.setupTx() mpool := s.network.App.GetMempool() @@ -268,14 +244,12 @@ func (s *IntegrationTestSuite) TestMempoolRemove() { } tc.verifyFunc() - fmt.Printf("DEBUG: Completed test case: %s\n", tc.name) }) } } // TestMempoolSelect tests transaction selection from the mempool func (s *IntegrationTestSuite) TestMempoolSelect() { - fmt.Printf("DEBUG: Starting TestMempoolSelect\n") testCases := []struct { name string setupTxs func() @@ -292,7 +266,7 @@ func (s *IntegrationTestSuite) TestMempoolSelect() { { name: "single cosmos transaction", setupTxs: func() { - cosmosTx := s.createCosmosSendTransaction(big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) mpool := s.network.App.GetMempool() err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -306,10 +280,10 @@ func (s *IntegrationTestSuite) TestMempoolSelect() { { name: "single EVM transaction", setupTxs: func() { - evmTx, err := s.createEVMTransaction(big.NewInt(1000000000)) - s.Require().NoError(err) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) + mpool := s.network.App.GetMempool() - err = mpool.Insert(s.network.GetContext(), evmTx) + err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) }, verifyFunc: func(iterator mempool.Iterator) { @@ -344,7 +318,6 @@ func (s *IntegrationTestSuite) TestMempoolSelect() { // TestMempoolIterator tests iterator functionality func (s *IntegrationTestSuite) TestMempoolIterator() { - fmt.Printf("DEBUG: Starting TestMempoolIterator\n") testCases := []struct { name string setupTxs func() @@ -361,7 +334,7 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { { name: "single cosmos transaction iteration", setupTxs: func() { - cosmosTx := s.createCosmosSendTransaction(big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) mpool := s.network.App.GetMempool() err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -374,10 +347,9 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { { name: "single EVM transaction iteration", setupTxs: func() { - evmTx, err := s.createEVMTransaction(big.NewInt(1000000000)) - s.Require().NoError(err) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) mpool := s.network.App.GetMempool() - err = mpool.Insert(s.network.GetContext(), evmTx) + err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) }, verifyFunc: func(iterator mempool.Iterator) { @@ -398,11 +370,11 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { setupTxs: func() { mpool := s.network.App.GetMempool() - cosmosTx1 := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(0), big.NewInt(1000)) + cosmosTx1 := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) err := mpool.Insert(s.network.GetContext(), cosmosTx1) s.Require().NoError(err) - cosmosTx2 := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(1), big.NewInt(2000)) + cosmosTx2 := s.createCosmosSendTx(s.keyring.GetKey(1), big.NewInt(2000)) err = mpool.Insert(s.network.GetContext(), cosmosTx2) s.Require().NoError(err) }, @@ -423,13 +395,13 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { mpool := s.network.App.GetMempool() // Add EVM transaction - evmTx, err := s.createEVMTransaction(big.NewInt(2000)) - s.Require().NoError(err) - err = mpool.Insert(s.network.GetContext(), evmTx) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(2000)) + + err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) // Add Cosmos transaction - cosmosTx := s.createCosmosSendTransaction(big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) err = mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) }, @@ -461,7 +433,6 @@ func (s *IntegrationTestSuite) TestMempoolIterator() { // TestTransactionOrdering tests transaction ordering based on fees func (s *IntegrationTestSuite) TestTransactionOrdering() { - fmt.Printf("DEBUG: Starting TestTransactionOrdering\n") testCases := []struct { name string setupTxs func() @@ -471,18 +442,17 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { name: "mixed EVM and cosmos transaction ordering", setupTxs: func() { // Create EVM transaction with high gas price - highGasPriceEVMTx, err := s.createEVMTransaction(big.NewInt(5000000000)) - s.Require().NoError(err) + highGasPriceEVMTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000)) // Create Cosmos transactions with different fee amounts - highFeeCosmosTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(6), big.NewInt(5000000000)) - mediumFeeCosmosTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(7), big.NewInt(3000000000)) - lowFeeCosmosTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(8), big.NewInt(1000000000)) + highFeeCosmosTx := s.createCosmosSendTx(s.keyring.GetKey(6), big.NewInt(5000000000)) + mediumFeeCosmosTx := s.createCosmosSendTx(s.keyring.GetKey(7), big.NewInt(3000000000)) + lowFeeCosmosTx := s.createCosmosSendTx(s.keyring.GetKey(8), big.NewInt(1000000000)) mpool := s.network.App.GetMempool() // Insert in non-priority order - err = mpool.Insert(s.network.GetContext(), lowFeeCosmosTx) + err := mpool.Insert(s.network.GetContext(), lowFeeCosmosTx) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), highGasPriceEVMTx) s.Require().NoError(err) @@ -517,17 +487,15 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { name: "EVM-only transaction replacement", setupTxs: func() { // Create first EVM transaction with low fee - lowFeeEVMTx, err := s.createEVMTransaction(big.NewInt(1000000000)) // 1 gaatom - s.Require().NoError(err) + lowFeeEVMTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) // 1 gaatom // Create second EVM transaction with high fee - highFeeEVMTx, err := s.createEVMTransaction(big.NewInt(5000000000)) // 5 gaatom - s.Require().NoError(err) + highFeeEVMTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000)) // 5 gaatom mpool := s.network.App.GetMempool() // Insert low fee transaction first - err = mpool.Insert(s.network.GetContext(), lowFeeEVMTx) + err := mpool.Insert(s.network.GetContext(), lowFeeEVMTx) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), highFeeEVMTx) s.Require().NoError(err) @@ -549,17 +517,15 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { setupTxs: func() { key := s.keyring.GetKey(0) // Create first EVM transaction with low fee - lowFeeEVMTx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 1) // 1 gaatom - s.Require().NoError(err) + lowFeeEVMTx := s.createEVMValueTransferTx(key, 1, big.NewInt(1000000000)) // 1 gaatom // Create second EVM transaction with high fee - highFeeEVMTx, err := s.createEVMTransactionWithNonce(key, big.NewInt(5000000000), 0) // 5 gaatom - s.Require().NoError(err) + highFeeEVMTx := s.createEVMValueTransferTx(key, 0, big.NewInt(5000000000)) // 5 gaatom mpool := s.network.App.GetMempool() // Insert low fee transaction first - err = mpool.Insert(s.network.GetContext(), lowFeeEVMTx) + err := mpool.Insert(s.network.GetContext(), lowFeeEVMTx) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), highFeeEVMTx) s.Require().NoError(err) @@ -587,9 +553,9 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { { name: "cosmos-only transaction replacement", setupTxs: func() { - highFeeTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(0), big.NewInt(5000000000)) // 5 gaatom - lowFeeTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(0), big.NewInt(1000000000)) // 1 gaatom - mediumFeeTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(0), big.NewInt(3000000000)) // 3 gaatom + highFeeTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(5000000000)) // 5 gaatom + lowFeeTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) // 1 gaatom + mediumFeeTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(3000000000)) // 3 gaatom mpool := s.network.App.GetMempool() @@ -619,16 +585,15 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { setupTxs: func() { // Create transactions with equal effective tips (assuming base fee = 0) // EVM: 1000 aatom/gas effective tip - evmTx, err := s.createEVMTransaction(big.NewInt(1000000000)) // 1 gaatom/gas - s.Require().NoError(err) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) // 1 gaatom/gas // Cosmos with same effective tip: 1000 * 200000 = 200000000 aatom total fee - cosmosTx := s.createCosmosSendTransaction(big.NewInt(1000000000)) // 1 gaatom/gas effective tip + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) // 1 gaatom/gas effective tip mpool := s.network.App.GetMempool() // Insert Cosmos first, then EVM - err = mpool.Insert(s.network.GetContext(), cosmosTx) + err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) @@ -662,16 +627,15 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { name: "mixed transactions with EVM having higher effective tip", setupTxs: func() { // Create EVM transaction with higher gas price - evmTx, err := s.createEVMTransaction(big.NewInt(5000000000)) // 5 gaatom/gas - s.Require().NoError(err) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000)) // 5 gaatom/gas // Create Cosmos transaction with lower gas price - cosmosTx := s.createCosmosSendTransaction(big.NewInt(2000000000)) // 2 gaatom/gas + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000000000)) // 2 gaatom/gas mpool := s.network.App.GetMempool() // Insert Cosmos first, then EVM - err = mpool.Insert(s.network.GetContext(), cosmosTx) + err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) @@ -702,16 +666,15 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { name: "mixed transactions with Cosmos having higher effective tip", setupTxs: func() { // Create EVM transaction with lower gas price - evmTx, err := s.createEVMTransaction(big.NewInt(2000000000)) // 2000 aatom/gas - s.Require().NoError(err) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(2000000000)) // 2000 aatom/gas // Create Cosmos transaction with higher gas price - cosmosTx := s.createCosmosSendTransaction(big.NewInt(5000000000)) // 5000 aatom/gas + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(5000000000)) // 5000 aatom/gas mpool := s.network.App.GetMempool() // Insert EVM first, then Cosmos - err = mpool.Insert(s.network.GetContext(), evmTx) + err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -745,21 +708,18 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { // EVM: 8000, 4000, 2000 aatom/gas // Cosmos: 6000, 3000, 1000 aatom/gas - evmHigh, err := s.createEVMTransaction(big.NewInt(8000000000)) - s.Require().NoError(err) - evmMedium, err := s.createEVMTransactionWithKey(s.keyring.GetKey(1), big.NewInt(4000000000)) - s.Require().NoError(err) - evmLow, err := s.createEVMTransactionWithKey(s.keyring.GetKey(2), big.NewInt(2000000000)) - s.Require().NoError(err) + evmHigh := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(8000000000)) + evmMedium := s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(4000000000)) + evmLow := s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(2000000000)) - cosmosHigh := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(3), big.NewInt(6000000000)) - cosmosMedium := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(4), big.NewInt(3000000000)) - cosmosLow := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(5), big.NewInt(1000000000)) + cosmosHigh := s.createCosmosSendTx(s.keyring.GetKey(3), big.NewInt(6000000000)) + cosmosMedium := s.createCosmosSendTx(s.keyring.GetKey(4), big.NewInt(3000000000)) + cosmosLow := s.createCosmosSendTx(s.keyring.GetKey(5), big.NewInt(1000000000)) mpool := s.network.App.GetMempool() // Insert in random order - err = mpool.Insert(s.network.GetContext(), cosmosLow) + err := mpool.Insert(s.network.GetContext(), cosmosLow) s.Require().NoError(err) err = mpool.Insert(s.network.GetContext(), evmMedium) s.Require().NoError(err) @@ -859,7 +819,6 @@ func (s *IntegrationTestSuite) TestTransactionOrdering() { // TestSelectBy tests the SelectBy functionality with filters func (s *IntegrationTestSuite) TestSelectBy() { - fmt.Printf("DEBUG: Starting TestSelectBy\n") testCases := []struct { name string setupTxs func() @@ -879,7 +838,7 @@ func (s *IntegrationTestSuite) TestSelectBy() { { name: "single cosmos transaction - terminates properly", setupTxs: func() { - cosmosTx := s.createCosmosSendTransaction(big.NewInt(2000)) + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000)) mpool := s.network.App.GetMempool() err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) @@ -892,10 +851,9 @@ func (s *IntegrationTestSuite) TestSelectBy() { { name: "single EVM transaction - terminates properly", setupTxs: func() { - evmTx, err := s.createEVMTransaction(big.NewInt(1000000000)) - s.Require().NoError(err) + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000)) mpool := s.network.App.GetMempool() - err = mpool.Insert(s.network.GetContext(), evmTx) + err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) }, filterFunc: func(tx sdk.Tx) bool { @@ -910,7 +868,7 @@ func (s *IntegrationTestSuite) TestSelectBy() { // Add transactions with different fees for i := 1; i < 6; i++ { // Use different keys for different transactions - cosmosTx := s.createCosmosSendTransactionWithKey(s.keyring.GetKey(i), big.NewInt(int64(i*1000))) // 5000, 4000, 3000, 2000, 1000 + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(i), big.NewInt(int64(i*1000))) // 5000, 4000, 3000, 2000, 1000 err := mpool.Insert(s.network.GetContext(), cosmosTx) s.Require().NoError(err) } @@ -936,13 +894,10 @@ func (s *IntegrationTestSuite) TestSelectBy() { for i := 1; i < 4; i++ { keyIndex := i key := s.keyring.GetKey(keyIndex) - fromAddr := common.BytesToAddress(key.AccAddr.Bytes()) - fmt.Printf("DEBUG: Using prefunded account %d: %s\n", keyIndex, fromAddr.Hex()) // Use the helper method with specific nonce - evmTx, err := s.createEVMTransactionWithKey(key, big.NewInt(int64(i)*100000000000)) - s.Require().NoError(err) - err = mpool.Insert(s.network.GetContext(), evmTx) + evmTx := s.createEVMValueTransferTx(key, 0, big.NewInt(int64(i)*100000000000)) + err := mpool.Insert(s.network.GetContext(), evmTx) s.Require().NoError(err) } }, @@ -995,7 +950,6 @@ func (s *IntegrationTestSuite) TestSelectBy() { // TestMempoolHeightRequirement tests that mempool operations fail before block 2 func (s *IntegrationTestSuite) TestMempoolHeightRequirement() { - fmt.Printf("DEBUG: Starting TestMempoolHeightRequirement\n") // Create a fresh network at block 1 keyring := keyring.New(1) options := []network.ConfigOption{ @@ -1013,7 +967,7 @@ func (s *IntegrationTestSuite) TestMempoolHeightRequirement() { s.Require().Equal(int64(2), nw.GetContext().BlockHeight()) mpool := nw.App.GetMempool() - tx := s.createCosmosSendTransaction(big.NewInt(1000)) + tx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000)) // Should fail because mempool requires block height >= 2 err = mpool.Insert(nw.GetContext(), tx) @@ -1024,8 +978,6 @@ func (s *IntegrationTestSuite) TestMempoolHeightRequirement() { // TestEVMTransactionComprehensive tests comprehensive EVM transaction functionality func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { - fmt.Printf("DEBUG: Starting TestEVMTransactionComprehensive\n") - testCases := []struct { name string setupTx func() sdk.Tx @@ -1036,9 +988,7 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { { name: "EVM transaction with high gas price", setupTx: func() sdk.Tx { - tx, err := s.createEVMTransaction(big.NewInt(10000000000)) // 10 gaatom - s.Require().NoError(err) - return tx + return s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(10000000000)) // 10 gaatom }, wantError: false, verifyFunc: func() { @@ -1049,9 +999,7 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { { name: "EVM transaction with low gas price", setupTx: func() sdk.Tx { - tx, err := s.createEVMTransaction(big.NewInt(100000000)) // 0.1 gaatom - s.Require().NoError(err) - return tx + return s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(100000000)) // 0.1 gaatom }, wantError: false, verifyFunc: func() { @@ -1067,9 +1015,7 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { data := []byte{0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0xf3} // Simple contract deployment // Use the contract deployment helper - tx, err := s.createEVMContractDeployment(key, big.NewInt(1000000000), data) - s.Require().NoError(err) - return tx + return s.createEVMContractDeployTx(key, big.NewInt(1000000000), data) }, wantError: false, verifyFunc: func() { @@ -1082,11 +1028,9 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { setupTx: func() sdk.Tx { // Use key 0 again since this is a separate test (SetupTest resets state) key := s.keyring.GetKey(0) - to := common.HexToAddress("0x1234567890123456789012345678901234567890") // Use the value transfer helper - tx, err := s.createEVMValueTransfer(key, big.NewInt(1000000000), big.NewInt(1000000000000000000), to) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, 0, big.NewInt(1000000000)) return tx }, wantError: false, @@ -1097,13 +1041,10 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { }, } - for i, tc := range testCases { - fmt.Printf("DEBUG: TestEVMTransactionComprehensive - Starting test case %d/%d: %s\n", i+1, len(testCases), tc.name) + for _, tc := range testCases { s.Run(tc.name, func() { - fmt.Printf("DEBUG: Running test case: %s\n", tc.name) // Reset test setup to ensure clean state s.SetupTest() - fmt.Printf("DEBUG: SetupTest completed for: %s\n", tc.name) tx := tc.setupTx() mpool := s.network.App.GetMempool() @@ -1120,17 +1061,13 @@ func (s *IntegrationTestSuite) TestEVMTransactionComprehensive() { } tc.verifyFunc() - fmt.Printf("DEBUG: Completed test case: %s\n", tc.name) }) - fmt.Printf("DEBUG: TestEVMTransactionComprehensive - Completed test case %d/%d: %s\n", i+1, len(testCases), tc.name) } } // TestNonceGappedEVMTransactions tests the behavior of nonce-gapped EVM transactions // and the transition from queued to pending when gaps are filled func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { - fmt.Printf("DEBUG: Starting TestNonceGappedEVMTransactions\n") - testCases := []struct { name string setupTxs func() ([]sdk.Tx, []int) // Returns transactions and their expected nonces @@ -1145,8 +1082,7 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // Insert transactions with gaps: nonces 0, 2, 4, 6 (missing 1, 3, 5) for i := 0; i <= 6; i += 2 { - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } @@ -1169,15 +1105,13 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // First, insert transactions with gaps: nonces 0, 2, 4 for i := 0; i <= 4; i += 2 { - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } // Then fill the gap by inserting nonce 1 - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 1) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, 1, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, 1) @@ -1199,8 +1133,7 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // Insert transactions with multiple gaps: nonces 0, 3, 6, 9 for i := 0; i <= 9; i += 3 { - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } @@ -1208,8 +1141,7 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // Fill gaps by inserting nonces 1, 2, 4, 5, 7, 8 for i := 1; i <= 8; i++ { if i%3 != 0 { // Skip nonces that are already inserted - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } @@ -1235,16 +1167,14 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // Account 1: nonces 0, 2 (gap at 1) for i := 0; i <= 2; i += 2 { - tx, err := s.createEVMTransactionWithNonce(key1, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key1, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } // Account 2: nonces 0, 3 (gaps at 1, 2) for i := 0; i <= 3; i += 3 { - tx, err := s.createEVMTransactionWithNonce(key2, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key2, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } @@ -1267,20 +1197,17 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { var nonces []int // Insert transaction with nonce 0 and low gas price - tx1, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 0) - s.Require().NoError(err) + tx1 := s.createEVMValueTransferTx(key, 0, big.NewInt(1000000000)) txs = append(txs, tx1) nonces = append(nonces, 0) // Insert transaction with nonce 1 - tx2, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 1) - s.Require().NoError(err) + tx2 := s.createEVMValueTransferTx(key, 1, big.NewInt(1000000000)) txs = append(txs, tx2) nonces = append(nonces, 1) // Replace nonce 0 transaction with higher gas price - tx3, err := s.createEVMTransactionWithNonce(key, big.NewInt(2000000000), 0) - s.Require().NoError(err) + tx3 := s.createEVMValueTransferTx(key, 0, big.NewInt(2000000000)) txs = append(txs, tx3) nonces = append(nonces, 0) @@ -1301,8 +1228,7 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // Insert transactions with gaps: nonces 0, 3, 6, 9 for i := 0; i <= 9; i += 3 { - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } @@ -1310,8 +1236,7 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { // Fill gaps by inserting nonces 1, 2, 4, 5, 7, 8 for i := 1; i <= 8; i++ { if i%3 != 0 { // Skip nonces that are already inserted - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) txs = append(txs, tx) nonces = append(nonces, i) } @@ -1325,370 +1250,22 @@ func (s *IntegrationTestSuite) TestNonceGappedEVMTransactions() { s.Require().Equal(10, count, "After filling all gaps, all 10 transactions should be pending") }, }, - { - name: "removing places subsequent transactions back into queued", - setupTxs: func() ([]sdk.Tx, []int) { - key := s.keyring.GetKey(0) - var txs []sdk.Tx - var nonces []int - - // Insert transactions with gaps: nonces 0, 1, 3, 4, 6, 7 - for i := 0; i <= 7; i++ { - if i != 1 { // Skip nonce 1 to create a gap - tx, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), i) - s.Require().NoError(err) - txs = append(txs, tx) - nonces = append(nonces, i) //#nosec G115 -- int overflow is not a concern here - } - } - - return txs, nonces - }, - verifyFunc: func(mpool mempool.Mempool) { - // Initially: nonces 0 should be pending, nonces 2, 3, 4, 5, 6, 7 should be queued - initialCount := mpool.CountTx() - s.Require().Equal(1, initialCount, "Initially only nonces 0, 1 should be pending") - key := s.keyring.GetKey(0) - - // Fill gap by inserting nonce 1 - tx1, err := s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 1) - s.Require().NoError(err) - err = mpool.Insert(s.network.GetContext(), tx1) - s.Require().NoError(err) - - // After filling gap: all nonce transactions should be in pending - countAfterFilling := mpool.CountTx() - s.Require().Equal(8, countAfterFilling, "After filling gap, only nonce 0 should be pending due to gap at nonce 1") - - // Remove nonce 1 transaction, dropping the rest (except for 0) into queued - tx1, err = s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 1) - s.Require().NoError(err) - err = mpool.Remove(tx1) - s.Require().NoError(err) - - // After removal: only nonce 0 should be pending, the rest get dropped to queued - countAfterRemoval := mpool.CountTx() - s.Require().Equal(1, countAfterRemoval, "After removing nonce 1, only nonce 0 should be pending") - - // Fill gap by inserting nonce 1 - tx1, err = s.createEVMTransactionWithNonce(key, big.NewInt(1000000000), 1) - s.Require().NoError(err) - err = mpool.Insert(s.network.GetContext(), tx1) - s.Require().NoError(err) - - // After filling gap: all transactions should be re-promoted and places into pending - countAfterFilling = mpool.CountTx() - s.Require().Equal(8, countAfterFilling, "After filling gap, only nonce 0 should be pending due to gap at nonce 1") - }, - }, } - for i, tc := range testCases { - fmt.Printf("DEBUG: TestNonceGappedEVMTransactions - Starting test case %d/%d: %s\n", i+1, len(testCases), tc.name) + for _, tc := range testCases { s.Run(tc.name, func() { - fmt.Printf("DEBUG: Running test case: %s\n", tc.name) // Reset test setup to ensure clean state s.SetupTest() - fmt.Printf("DEBUG: SetupTest completed for: %s\n", tc.name) - txs, nonces := tc.setupTxs() + txs, _ := tc.setupTxs() mpool := s.network.App.GetMempool() - // Insert transactions and track count changes - initialCount := mpool.CountTx() - fmt.Printf("DEBUG: Initial mempool count: %d\n", initialCount) - - for i, tx := range txs { + for _, tx := range txs { err := mpool.Insert(s.network.GetContext(), tx) s.Require().NoError(err) - - currentCount := mpool.CountTx() - fmt.Printf("DEBUG: After inserting nonce %d: count = %d\n", nonces[i], currentCount) } tc.verifyFunc(mpool) - fmt.Printf("DEBUG: Completed test case: %s\n", tc.name) }) - fmt.Printf("DEBUG: TestNonceGappedEVMTransactions - Completed test case %d/%d: %s\n", i+1, len(testCases), tc.name) - } -} - -// Helper methods - -// createCosmosSendTransactionWithKey creates a simple bank send transaction with the specified key -func (s *IntegrationTestSuite) createCosmosSendTransactionWithKey(key keyring.Key, gasPrice *big.Int) sdk.Tx { - feeDenom := "aatom" - gasLimit := uint64(TxGas) - - // Calculate fee amount from gas price: fee = gas_price * gas_limit - feeAmount := new(big.Int).Mul(gasPrice, big.NewInt(int64(gasLimit))) - - fmt.Printf("DEBUG: Creating cosmos transaction with gas price: %s aatom/gas, fee: %s %s\n", gasPrice.String(), feeAmount.String(), feeDenom) - - fromAddr := key.AccAddr - toAddr := s.keyring.GetKey(1).AccAddr - amount := sdk.NewCoins(sdk.NewInt64Coin(feeDenom, 1000)) - - bankMsg := banktypes.NewMsgSend(fromAddr, toAddr, amount) - - txBuilder := s.network.App.GetTxConfig().NewTxBuilder() - err := txBuilder.SetMsgs(bankMsg) - s.Require().NoError(err) - - txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewInt64Coin(feeDenom, feeAmount.Int64()))) - txBuilder.SetGasLimit(gasLimit) - - // Sign the transaction - privKey := key.Priv - // Create a dummy signature for testing - sigData := signing.SingleSignatureData{ - SignMode: signing.SignMode_SIGN_MODE_DIRECT, - Signature: []byte("dummy_signature_for_testing"), - } - sig := signing.SignatureV2{ - PubKey: privKey.PubKey(), - Data: &sigData, - Sequence: 0, } - err = txBuilder.SetSignatures(sig) - s.Require().NoError(err) - - fmt.Printf("DEBUG: Created cosmos transaction successfully\n") - return txBuilder.GetTx() -} - -// createCosmosSendTransaction creates a simple bank send transaction using the first key -func (s *IntegrationTestSuite) createCosmosSendTransaction(gasPrice *big.Int) sdk.Tx { - key := s.keyring.GetKey(0) - return s.createCosmosSendTransactionWithKey(key, gasPrice) -} - -// calculateCosmosGasPrice calculates the gas price for a Cosmos transaction -func (s *IntegrationTestSuite) calculateCosmosGasPrice(feeAmount int64, gasLimit uint64) *big.Int { - return new(big.Int).Div(big.NewInt(feeAmount), big.NewInt(int64(gasLimit))) //#nosec G115 -- not concern, test -} - -// calculateCosmosEffectiveTip calculates the effective tip for a Cosmos transaction -// This aligns with EVM transaction prioritization: effective_tip = gas_price - base_fee -func (s *IntegrationTestSuite) calculateCosmosEffectiveTip(feeAmount int64, gasLimit uint64, baseFee *big.Int) *big.Int { - gasPrice := s.calculateCosmosGasPrice(feeAmount, gasLimit) - if baseFee == nil || baseFee.Sign() == 0 { - return gasPrice // No base fee, effective tip equals gas price - } - - if gasPrice.Cmp(baseFee) < 0 { - return big.NewInt(0) // Gas price lower than base fee, effective tip is zero - } - - return new(big.Int).Sub(gasPrice, baseFee) -} - -// createEVMTransaction creates an EVM transaction using the provided key -func (s *IntegrationTestSuite) createEVMTransactionWithKey(key keyring.Key, gasPrice *big.Int) (sdk.Tx, error) { - fmt.Printf("DEBUG: Creating EVM transaction with gas price: %s\n", gasPrice.String()) - - privKey := key.Priv - - // Convert Cosmos address to EVM address - fromAddr := common.BytesToAddress(key.AccAddr.Bytes()) - fmt.Printf("DEBUG: Using prefunded account: %s\n", fromAddr.Hex()) - - to := common.HexToAddress("0x1234567890123456789012345678901234567890") - ethTx := ethtypes.NewTx(ðtypes.LegacyTx{ - Nonce: 0, - To: &to, - Value: big.NewInt(1000), - Gas: TxGas, - GasPrice: gasPrice, - Data: nil, - }) - - // Convert to ECDSA private key for signing - ethPrivKey, ok := privKey.(*ethsecp256k1.PrivKey) - if !ok { - return nil, fmt.Errorf("expected ethsecp256k1.PrivKey, got %T", privKey) - } - - ecdsaPrivKey, err := ethPrivKey.ToECDSA() - if err != nil { - return nil, err - } - - signer := ethtypes.HomesteadSigner{} - signedTx, err := ethtypes.SignTx(ethTx, signer, ecdsaPrivKey) - if err != nil { - return nil, err - } - - msgEthTx := &evmtypes.MsgEthereumTx{} - msgEthTx.FromEthereumTx(signedTx) - - txBuilder := s.network.App.GetTxConfig().NewTxBuilder() - err = txBuilder.SetMsgs(msgEthTx) - if err != nil { - return nil, err - } - - fmt.Printf("DEBUG: Created EVM transaction successfully\n") - return txBuilder.GetTx(), nil -} - -// createEVMTransaction creates an EVM transaction using the first key -func (s *IntegrationTestSuite) createEVMTransaction(gasPrice *big.Int) (sdk.Tx, error) { - key := s.keyring.GetKey(0) - return s.createEVMTransactionWithKey(key, gasPrice) -} - -// createEVMContractDeployment creates an EVM transaction for contract deployment -func (s *IntegrationTestSuite) createEVMContractDeployment(key keyring.Key, gasPrice *big.Int, data []byte) (sdk.Tx, error) { - fmt.Printf("DEBUG: Creating EVM contract deployment transaction with gas price: %s\n", gasPrice.String()) - - privKey := key.Priv - - // Convert Cosmos address to EVM address - fromAddr := common.BytesToAddress(key.AccAddr.Bytes()) - fmt.Printf("DEBUG: Using prefunded account: %s\n", fromAddr.Hex()) - - ethTx := ethtypes.NewTx(ðtypes.LegacyTx{ - Nonce: 0, - To: nil, // nil for contract deployment - Value: big.NewInt(0), - Gas: 100000, - GasPrice: gasPrice, - Data: data, - }) - - // Convert to ECDSA private key for signing - ethPrivKey, ok := privKey.(*ethsecp256k1.PrivKey) - if !ok { - return nil, fmt.Errorf("expected ethsecp256k1.PrivKey, got %T", privKey) - } - - ecdsaPrivKey, err := ethPrivKey.ToECDSA() - if err != nil { - return nil, err - } - - signer := ethtypes.HomesteadSigner{} - signedTx, err := ethtypes.SignTx(ethTx, signer, ecdsaPrivKey) - if err != nil { - return nil, err - } - - msgEthTx := &evmtypes.MsgEthereumTx{} - msgEthTx.FromEthereumTx(signedTx) - - txBuilder := s.network.App.GetTxConfig().NewTxBuilder() - err = txBuilder.SetMsgs(msgEthTx) - if err != nil { - return nil, err - } - - fmt.Printf("DEBUG: Created EVM contract deployment transaction successfully\n") - return txBuilder.GetTx(), nil -} - -// createEVMValueTransfer creates an EVM transaction for value transfer -func (s *IntegrationTestSuite) createEVMValueTransfer(key keyring.Key, gasPrice *big.Int, value *big.Int, to common.Address) (sdk.Tx, error) { - fmt.Printf("DEBUG: Creating EVM value transfer transaction with gas price: %s\n", gasPrice.String()) - - privKey := key.Priv - - // Convert Cosmos address to EVM address - fromAddr := common.BytesToAddress(key.AccAddr.Bytes()) - fmt.Printf("DEBUG: Using prefunded account: %s\n", fromAddr.Hex()) - - ethTx := ethtypes.NewTx(ðtypes.LegacyTx{ - Nonce: 0, - To: &to, - Value: value, - Gas: TxGas, - GasPrice: gasPrice, - Data: nil, - }) - - // Convert to ECDSA private key for signing - ethPrivKey, ok := privKey.(*ethsecp256k1.PrivKey) - if !ok { - return nil, fmt.Errorf("expected ethsecp256k1.PrivKey, got %T", privKey) - } - - ecdsaPrivKey, err := ethPrivKey.ToECDSA() - if err != nil { - return nil, err - } - - signer := ethtypes.HomesteadSigner{} - signedTx, err := ethtypes.SignTx(ethTx, signer, ecdsaPrivKey) - if err != nil { - return nil, err - } - - msgEthTx := &evmtypes.MsgEthereumTx{} - msgEthTx.FromEthereumTx(signedTx) - if err != nil { - return nil, err - } - - txBuilder := s.network.App.GetTxConfig().NewTxBuilder() - err = txBuilder.SetMsgs(msgEthTx) - if err != nil { - return nil, err - } - - fmt.Printf("DEBUG: Created EVM value transfer transaction successfully\n") - return txBuilder.GetTx(), nil -} - -// createEVMTransactionWithNonce creates an EVM transaction with a specific nonce -func (s *IntegrationTestSuite) createEVMTransactionWithNonce(key keyring.Key, gasPrice *big.Int, nonce int) (sdk.Tx, error) { - fmt.Printf("DEBUG: Creating EVM transaction with gas price: %s and nonce: %d\n", gasPrice.String(), nonce) - - privKey := key.Priv - - // Convert Cosmos address to EVM address - fromAddr := common.BytesToAddress(key.AccAddr.Bytes()) - fmt.Printf("DEBUG: Using prefunded account: %s\n", fromAddr.Hex()) - - to := common.HexToAddress("0x1234567890123456789012345678901234567890") - ethTx := ethtypes.NewTx(ðtypes.LegacyTx{ - Nonce: uint64(nonce), //#nosec G115 -- int overflow is not a concern here - To: &to, - Value: big.NewInt(1000), - Gas: TxGas, - GasPrice: gasPrice, - Data: nil, - }) - - // Convert to ECDSA private key for signing - ethPrivKey, ok := privKey.(*ethsecp256k1.PrivKey) - if !ok { - return nil, fmt.Errorf("expected ethsecp256k1.PrivKey, got %T", privKey) - } - - ecdsaPrivKey, err := ethPrivKey.ToECDSA() - if err != nil { - return nil, err - } - - signer := ethtypes.HomesteadSigner{} - signedTx, err := ethtypes.SignTx(ethTx, signer, ecdsaPrivKey) - if err != nil { - return nil, err - } - - msgEthTx := &evmtypes.MsgEthereumTx{} - msgEthTx.FromEthereumTx(signedTx) - if err != nil { - return nil, err - } - - txBuilder := s.network.App.GetTxConfig().NewTxBuilder() - err = txBuilder.SetMsgs(msgEthTx) - if err != nil { - return nil, err - } - - fmt.Printf("DEBUG: Created EVM transaction successfully\n") - return txBuilder.GetTx(), nil } diff --git a/tests/integration/mempool/test_mempool_integration_abci.go b/tests/integration/mempool/test_mempool_integration_abci.go new file mode 100644 index 000000000..cd0648468 --- /dev/null +++ b/tests/integration/mempool/test_mempool_integration_abci.go @@ -0,0 +1,506 @@ +package mempool + +import ( + "encoding/hex" + "math/big" + + "github.com/ethereum/go-ethereum/core" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/cometbft/cometbft/crypto/tmhash" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/mempool" +) + +// TestTransactionOrderingWithABCIMethodCalls tests transaction ordering based on fees +func (s *IntegrationTestSuite) TestTransactionOrderingWithABCIMethodCalls() { + testCases := []struct { + name string + setupTxs func() ([]sdk.Tx, []string) + }{ + { + name: "mixed EVM and cosmos transaction ordering", + setupTxs: func() ([]sdk.Tx, []string) { + // Create EVM transaction with high gas price + highGasPriceEVMTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000)) + + // Create Cosmos transactions with different fee amounts + highFeeCosmosTx := s.createCosmosSendTx(s.keyring.GetKey(6), big.NewInt(5000000000)) + mediumFeeCosmosTx := s.createCosmosSendTx(s.keyring.GetKey(7), big.NewInt(3000000000)) + lowFeeCosmosTx := s.createCosmosSendTx(s.keyring.GetKey(8), big.NewInt(2000000000)) + + // Input txs in order + inputTxs := []sdk.Tx{lowFeeCosmosTx, highGasPriceEVMTx, mediumFeeCosmosTx, highFeeCosmosTx} + + // Expected txs in order + expectedTxs := []sdk.Tx{highGasPriceEVMTx, highFeeCosmosTx, mediumFeeCosmosTx, lowFeeCosmosTx} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + { + name: "EVM-only transaction replacement", + setupTxs: func() ([]sdk.Tx, []string) { + // Create first EVM transaction with low fee + lowFeeEVMTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(2000000000)) // 2 gaatom + + // Create second EVM transaction with high fee + highFeeEVMTx := s.createEVMValueTransferDynamicFeeTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000), big.NewInt(5000000000)) // 5 gaatom + + // Input txs in order + inputTxs := []sdk.Tx{lowFeeEVMTx, highFeeEVMTx} + + // Expected Txs in order + expectedTxs := []sdk.Tx{highFeeEVMTx} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + { + name: "EVM-only transaction ordering", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + // Create first EVM transaction with low fee + lowFeeEVMTx := s.createEVMValueTransferTx(key, 1, big.NewInt(2000000000)) // 2 gaatom + + // Create second EVM transaction with high fee + highFeeEVMTx := s.createEVMValueTransferTx(key, 0, big.NewInt(5000000000)) // 5 gaatom + + // Input txs in order + inputTxs := []sdk.Tx{lowFeeEVMTx, highFeeEVMTx} + + // Expected txs in order + expectedTxs := []sdk.Tx{highFeeEVMTx, lowFeeEVMTx} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + { + name: "mixed EVM and Cosmos transactions with equal effective tips", + setupTxs: func() ([]sdk.Tx, []string) { + // Cosmos with same effective tip: 1000 * 200000 = 200000000 aatom total fee + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(1000000000)) // 1 gaatom/gas effective tip + + // Create transactions with equal effective tips (assuming base fee = 0) + // EVM: 1000 aatom/gas effective tip + evmTx := s.createEVMValueTransferDynamicFeeTx(s.keyring.GetKey(0), 0, big.NewInt(1000000000), big.NewInt(1000000000)) // 1 gaatom/gas + + // Input txs in order + inputTxs := []sdk.Tx{cosmosTx, evmTx} + + // Expected txs in order + expectedTxs := []sdk.Tx{evmTx} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + { + name: "mixed transactions with EVM having higher effective tip", + setupTxs: func() ([]sdk.Tx, []string) { + // Create Cosmos transaction with lower gas price + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(2000000000)) // 2 gaatom/gas + + // Create EVM transaction with higher gas price + evmTx := s.createEVMValueTransferDynamicFeeTx(s.keyring.GetKey(0), 0, big.NewInt(5000000000), big.NewInt(5000000000)) // 5 gaatom/gas + + // Input txs in order + inputTxs := []sdk.Tx{cosmosTx, evmTx} + + // Expected txs in order + expectedTxs := []sdk.Tx{evmTx} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + { + name: "mixed transactions with Cosmos having higher effective tip", + setupTxs: func() ([]sdk.Tx, []string) { + // Create EVM transaction with lower gas price + evmTx := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(2000000000)) // 2000 aatom/gas + + // Create Cosmos transaction with higher gas price + cosmosTx := s.createCosmosSendTx(s.keyring.GetKey(0), big.NewInt(5000000000)) // 5000 aatom/gas + + // Input txs in order + inputTxs := []sdk.Tx{evmTx, cosmosTx} + + // Expected txs in order + expectedTxs := []sdk.Tx{evmTx} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + { + name: "mixed transaction ordering with multiple effective tips", + setupTxs: func() ([]sdk.Tx, []string) { + // Create multiple transactions with different gas prices + // EVM: 10000, 8000, 6000 aatom/gas + // Cosmos: 9000, 7000, 5000 aatom/gas + + evmHigh := s.createEVMValueTransferTx(s.keyring.GetKey(0), 0, big.NewInt(10000000000)) + evmMedium := s.createEVMValueTransferTx(s.keyring.GetKey(1), 0, big.NewInt(8000000000)) + evmLow := s.createEVMValueTransferTx(s.keyring.GetKey(2), 0, big.NewInt(6000000000)) + + cosmosHigh := s.createCosmosSendTx(s.keyring.GetKey(3), big.NewInt(9000000000)) + cosmosMedium := s.createCosmosSendTx(s.keyring.GetKey(4), big.NewInt(7000000000)) + cosmosLow := s.createCosmosSendTx(s.keyring.GetKey(5), big.NewInt(5000000000)) + + // Input txs in order + inputTxs := []sdk.Tx{cosmosHigh, cosmosMedium, cosmosLow, evmHigh, evmMedium, evmLow} + + // Expected txs in order + expectedTxs := []sdk.Tx{evmHigh, cosmosHigh, evmMedium, cosmosMedium, evmLow, cosmosLow} + expTxHashes := s.getTxHashes(expectedTxs) + + return inputTxs, expTxHashes + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // Reset test setup to ensure clean state + s.SetupTest() + + txs, expTxHashes := tc.setupTxs() + + // Call CheckTx for transactions + err := s.checkTxs(txs) + s.Require().NoError(err) + + // Call FinalizeBlock to make finalizeState before calling PrepareProposal + _, err = s.network.FinalizeBlock() + s.Require().NoError(err) + + // Call PrepareProposal to selcet transactions from mempool and make proposal + prepareProposalRes, err := s.network.App.PrepareProposal(&abci.RequestPrepareProposal{ + MaxTxBytes: 1_000_000, + Height: 1, + }) + s.Require().NoError(err) + + // Check whether expected transactions are included and returned as pending state in mempool + mpool := s.network.App.GetMempool() + iterator := mpool.Select(s.network.GetContext(), nil) + for _, txHash := range expTxHashes { + actualTxHash := s.getTxHash(iterator.Tx()) + s.Require().Equal(txHash, actualTxHash) + + iterator = iterator.Next() + } + + // Check whether expected transactions are selcted by PrepareProposal + txHashes := make([]string, 0) + for _, txBytes := range prepareProposalRes.Txs { + txHash := hex.EncodeToString(tmhash.Sum(txBytes)) + txHashes = append(txHashes, txHash) + } + s.Require().Equal(expTxHashes, txHashes) + }) + } +} + +// TestNonceGappedEVMTransactionsWithABCIMethodCalls tests the behavior of nonce-gapped EVM transactions +// and the transition from queued to pending when gaps are filled +func (s *IntegrationTestSuite) TestNonceGappedEVMTransactionsWithABCIMethodCalls() { + testCases := []struct { + name string + setupTxs func() ([]sdk.Tx, []string) // Returns transactions and their expected nonces + verifyFunc func(mpool mempool.Mempool) + }{ + { + name: "insert transactions with nonce gaps", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + var txs []sdk.Tx + + // Insert transactions with gaps: nonces 0, 2, 4, 6 (missing 1, 3, 5) + for i := 0; i <= 6; i += 2 { + tx := s.createEVMValueTransferTx(key, i, big.NewInt(2000000000)) + txs = append(txs, tx) + } + + // Expected txs in order + expectedTxs := txs[:1] + expTxHashes := s.getTxHashes(expectedTxs) + + return txs, expTxHashes + }, + verifyFunc: func(mpool mempool.Mempool) { + // Only nonce 0 should be pending (the first consecutive transaction) + // nonces 2, 4, 6 should be queued + count := mpool.CountTx() + s.Require().Equal(1, count, "Only nonce 0 should be pending, others should be queued") + }, + }, + { + name: "fill nonce gap and verify pending count increases", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + var txs []sdk.Tx + + // First, insert transactions with gaps: nonces 0, 2, 4 + for i := 0; i <= 4; i += 2 { + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) + txs = append(txs, tx) + } + + // Then fill the gap by inserting nonce 1 + tx := s.createEVMValueTransferTx(key, 1, big.NewInt(1000000000)) + txs = append(txs, tx) + + // Expected txs in order + expectedTxs := []sdk.Tx{txs[0], txs[3], txs[1]} + expTxHashes := s.getTxHashes(expectedTxs) + + return txs, expTxHashes + }, + verifyFunc: func(mpool mempool.Mempool) { + // After filling nonce 1, transactions 0, 1, 2 should be pending + // nonce 4 should still be queued + count := mpool.CountTx() + s.Require().Equal(3, count, "After filling gap, nonces 0, 1, 2 should be pending") + }, + }, + { + name: "fill multiple nonce gaps", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + var txs []sdk.Tx + + // Insert transactions with multiple gaps: nonces 0, 3, 6, 9 + for i := 0; i <= 9; i += 3 { + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) + txs = append(txs, tx) + + } + + // Fill gaps by inserting nonces 1, 2, 4, 5, 7, 8 + for i := 1; i <= 8; i++ { + if i%3 != 0 { // Skip nonces that are already inserted + tx := s.createEVMValueTransferTx(key, i, big.NewInt(1000000000)) + txs = append(txs, tx) + + } + } + + // Expected txs in order + expectedTxs := []sdk.Tx{txs[0], txs[4], txs[5], txs[1], txs[6], txs[7], txs[2], txs[8], txs[9], txs[3]} + expTxHashes := s.getTxHashes(expectedTxs) + + return txs, expTxHashes + }, + verifyFunc: func(mpool mempool.Mempool) { + // After filling all gaps, all transactions should be pending + count := mpool.CountTx() + s.Require().Equal(10, count, "After filling all gaps, all 10 transactions should be pending") + }, + }, + { + name: "test different accounts with nonce gaps", + setupTxs: func() ([]sdk.Tx, []string) { + var txs []sdk.Tx + + // Use different keys for different accounts + key1 := s.keyring.GetKey(0) + key2 := s.keyring.GetKey(1) + + // Account 1: nonces 0, 2 (gap at 1) + for i := 0; i <= 2; i += 2 { + tx := s.createEVMValueTransferTx(key1, i, big.NewInt(1000000000)) + txs = append(txs, tx) + } + + // Account 2: nonces 0, 3 (gaps at 1, 2) + for i := 0; i <= 3; i += 3 { + tx := s.createEVMValueTransferTx(key2, i, big.NewInt(1000000000)) + txs = append(txs, tx) + } + + // Expected txs in order + expectedTxs := []sdk.Tx{txs[0], txs[2]} + expTxHashes := s.getTxHashes(expectedTxs) + + return txs, expTxHashes + }, + verifyFunc: func(mpool mempool.Mempool) { + // Account 1: nonce 0 pending, nonce 2 queued + // Account 2: nonce 0 pending, nonce 3 queued + // Total: 2 pending transactions + count := mpool.CountTx() + s.Require().Equal(2, count, "Only nonce 0 from each account should be pending") + }, + }, + { + name: "test replacement transactions with higher gas price", + setupTxs: func() ([]sdk.Tx, []string) { + key := s.keyring.GetKey(0) + var txs []sdk.Tx + + // Insert transaction with nonce 0 and low gas price + tx1 := s.createEVMValueTransferTx(key, 0, big.NewInt(1000000000)) + txs = append(txs, tx1) + + // Insert transaction with nonce 1 + tx2 := s.createEVMValueTransferTx(key, 1, big.NewInt(1000000000)) + txs = append(txs, tx2) + + // Replace nonce 0 transaction with higher gas price + tx3 := s.createEVMValueTransferTx(key, 0, big.NewInt(2000000000)) + txs = append(txs, tx3) + + // Expected txs in order + expectedTxs := []sdk.Tx{txs[2], txs[1]} + expTxHashes := s.getTxHashes(expectedTxs) + + return txs, expTxHashes + }, + verifyFunc: func(mpool mempool.Mempool) { + // After replacement, both nonces 0 and 1 should be pending + count := mpool.CountTx() + s.Require().Equal(2, count, "After replacement, both transactions should be pending") + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + txs, expTxHashes := tc.setupTxs() + + // Call CheckTx for transactions + err := s.checkTxs(txs) + s.Require().NoError(err) + + // Call FinalizeBlock to make finalizeState before calling PrepareProposal + _, err = s.network.FinalizeBlock() + s.Require().NoError(err) + + // Call PrepareProposal to selcet transactions from mempool and make proposal + prepareProposalRes, err := s.network.App.PrepareProposal(&abci.RequestPrepareProposal{ + MaxTxBytes: 1_000_000, + Height: 1, + }) + s.Require().NoError(err) + + mpool := s.network.App.GetMempool() + iterator := mpool.Select(s.network.GetContext(), nil) + + // Check whether expected transactions are included and returned as pending state in mempool + for _, txHash := range expTxHashes { + actualTxHash := s.getTxHash(iterator.Tx()) + s.Require().Equal(txHash, actualTxHash) + + iterator = iterator.Next() + } + tc.verifyFunc(mpool) + + // Check whether expected transactions are selcted by PrepareProposal + txHashes := make([]string, 0) + for _, txBytes := range prepareProposalRes.Txs { + txHash := hex.EncodeToString(tmhash.Sum(txBytes)) + txHashes = append(txHashes, txHash) + } + s.Require().Equal(expTxHashes, txHashes) + }) + } +} + +// TestCheckTxHandlerForCommittedAndLowerNonceTxs tests that: +// 1. Committed transactions are not in the mempool after block finalization +// 2. New transactions with nonces lower than current nonce fail at mempool level +func (s *IntegrationTestSuite) TestCheckTxHandlerForCommittedAndLowerNonceTxs() { + testCases := []struct { + name string + setupTxs func() []sdk.Tx + verifyFunc func() + }{ + { + name: "EVM transactions: committed txs removed from mempool and lower nonce txs fail", + setupTxs: func() []sdk.Tx { + key := s.keyring.GetKey(0) + + // Create transactions with sequential nonces (0, 1, 2) + tx0 := s.createEVMValueTransferTx(key, 0, big.NewInt(2000000000)) + tx1 := s.createEVMValueTransferTx(key, 1, big.NewInt(2000000000)) + tx2 := s.createEVMValueTransferTx(key, 2, big.NewInt(2000000000)) + + return []sdk.Tx{tx0, tx1, tx2} + }, + verifyFunc: func() { + // 1. Verify the correct nonce transaction is in mempool + mpool := s.network.App.GetMempool() + s.Require().Equal(0, mpool.CountTx(), "Only the correct nonce transaction should be in mempool") + + // 2. Check current sequence + acc := s.network.App.GetAccountKeeper().GetAccount(s.network.GetContext(), s.keyring.GetAccAddr(0)) + sequence := acc.GetSequence() + s.Require().Equal(uint64(3), sequence) + + // 3. Check new transactions with nonces lower than current nonce fails + // Current nonce should be 3 after committing nonces 1, 2 + // + // NOTE: The reason we don't try tx with nonce 0 is + // because txFactory replace nonce 0 with curreent nonce. + // So we just test for nonce 1 and 2. + key := s.keyring.GetKey(0) + + // Try to add transaction with nonce 1 (lower than current nonce 3) - should fail + dupTx1 := s.createEVMValueTransferTx(key, 1, big.NewInt(2000000000)) + res, err := s.checkTx(dupTx1) + s.Require().NoError(err, "Transaction with nonce 1 should fail when current nonce is 3") + s.Require().Contains(res.GetLog(), core.ErrNonceTooLow.Error()) + s.Require().Equal(0, mpool.CountTx(), "Only the correct nonce transaction should be in mempool") + + // Try to add transaction with nonce 2 (lower than current nonce 3) - should fail + dupTx2 := s.createEVMValueTransferTx(key, 2, big.NewInt(2000000000)) + res, err = s.checkTx(dupTx2) + s.Require().NoError(err, "Transaction with nonce 2 should fail when current nonce is 3") + s.Require().Contains(res.GetLog(), core.ErrNonceTooLow.Error()) + s.Require().Equal(0, mpool.CountTx(), "Only the correct nonce transaction should be in mempool") + + // Verify transaction with correct nonce (3) still works + tx3 := s.createEVMValueTransferTx(key, 3, big.NewInt(2000000000)) + res, err = s.checkTx(tx3) + s.Require().NoError(err, "Transaction with correct nonce 3 should succeed") + s.Require().Equal(abci.CodeTypeOK, res.Code) + s.Require().Equal(1, mpool.CountTx(), "Only the correct nonce transaction should be in mempool") + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + // Reset test setup to ensure clean state + s.SetupTest() + + txs := tc.setupTxs() + + // Call CheckTx for transactions + err := s.checkTxs(txs) + s.Require().NoError(err) + + // Finalize block with txs and Commit state + txBytes, err := s.getTxBytes(txs) + s.Require().NoError(err) + + _, err = s.network.NextBlockWithTxs(txBytes...) + s.Require().NoError(err) + + // Manually trigger chain head event to notify mempool about the new block + // This simulates the natural block notification that occurs in production + s.notifyNewBlockToMempool() + + // Run verification function + tc.verifyFunc() + }) + } +} diff --git a/tests/integration/precompiles/distribution/test_setup.go b/tests/integration/precompiles/distribution/test_setup.go index e611fea6c..57b15cb85 100644 --- a/tests/integration/precompiles/distribution/test_setup.go +++ b/tests/integration/precompiles/distribution/test_setup.go @@ -18,6 +18,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) @@ -131,6 +132,8 @@ func (s *PrecompileTestSuite) SetupTest() { s.network = nw s.precompile, err = distribution.NewPrecompile( s.network.App.GetDistrKeeper(), + distrkeeper.NewMsgServerImpl(s.network.App.GetDistrKeeper()), + distrkeeper.NewQuerier(s.network.App.GetDistrKeeper()), *s.network.App.GetStakingKeeper(), s.network.App.GetBankKeeper(), address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), diff --git a/tests/integration/precompiles/distribution/test_utils.go b/tests/integration/precompiles/distribution/test_utils.go index d5f03c6a5..13ddda323 100644 --- a/tests/integration/precompiles/distribution/test_utils.go +++ b/tests/integration/precompiles/distribution/test_utils.go @@ -10,6 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -84,6 +85,8 @@ func (s *PrecompileTestSuite) fundAccountWithBaseDenom(ctx sdk.Context, addr sdk func (s *PrecompileTestSuite) getStakingPrecompile() (*staking.Precompile, error) { return staking.NewPrecompile( *s.network.App.GetStakingKeeper(), + stakingkeeper.NewMsgServerImpl(s.network.App.GetStakingKeeper()), + stakingkeeper.NewQuerier(s.network.App.GetStakingKeeper()), s.network.App.GetBankKeeper(), address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), ) diff --git a/tests/integration/precompiles/erc20/test_setup.go b/tests/integration/precompiles/erc20/test_setup.go index fd07dbc49..d6d2fad43 100644 --- a/tests/integration/precompiles/erc20/test_setup.go +++ b/tests/integration/precompiles/erc20/test_setup.go @@ -68,10 +68,13 @@ func (s *PrecompileTestSuite) SetupTest() { s.precompile, err = s.setupERC20Precompile(s.tokenDenom) s.Require().NoError(err) + erc20ABI, err := erc20.LoadABI() + s.Require().NoError(err) + // Instantiate the precompile2 with the bond denom (the token pair was already set up in genesis). tokenPairID := s.network.App.GetErc20Keeper().GetDenomMap(s.network.GetContext(), bondDenom) tokenPair, found := s.network.App.GetErc20Keeper().GetTokenPair(s.network.GetContext(), tokenPairID) s.Require().True(found) - s.precompile2, err = erc20.NewPrecompile(tokenPair, s.network.App.GetBankKeeper(), s.network.App.GetErc20Keeper(), s.network.App.GetTransferKeeper()) + s.precompile2, err = erc20.NewPrecompile(tokenPair, s.network.App.GetBankKeeper(), s.network.App.GetErc20Keeper(), s.network.App.GetTransferKeeper(), erc20ABI) s.Require().NoError(err) } diff --git a/tests/integration/precompiles/erc20/test_utils.go b/tests/integration/precompiles/erc20/test_utils.go index 06d6b3884..31e75c6b3 100644 --- a/tests/integration/precompiles/erc20/test_utils.go +++ b/tests/integration/precompiles/erc20/test_utils.go @@ -171,11 +171,15 @@ func (is *IntegrationTestSuite) setupERC20Precompile(denom string, tokenPairs [] tokenPair = tp } + erc20ABI, err := erc20.LoadABI() + Expect(err).To(BeNil()) + precompile, err := erc20.NewPrecompile( tokenPair, is.network.App.GetBankKeeper(), is.network.App.GetErc20Keeper(), is.network.App.GetTransferKeeper(), + erc20ABI, ) Expect(err).ToNot(HaveOccurred(), "failed to set up %q erc20 precompile", tokenPair.Denom) @@ -188,11 +192,16 @@ func (is *IntegrationTestSuite) setupERC20Precompile(denom string, tokenPairs [] func setupERC20PrecompileForTokenPair( unitNetwork network.UnitTestNetwork, tokenPair erc20types.TokenPair, ) (*erc20.Precompile, error) { + erc20ABI, err := erc20.LoadABI() + if err != nil { + return nil, err + } precompile, err := erc20.NewPrecompile( tokenPair, unitNetwork.App.GetBankKeeper(), unitNetwork.App.GetErc20Keeper(), unitNetwork.App.GetTransferKeeper(), + erc20ABI, ) if err != nil { return nil, errorsmod.Wrapf(err, "failed to create %q erc20 precompile", tokenPair.Denom) @@ -215,11 +224,16 @@ func setupERC20PrecompileForTokenPair( func (is *IntegrationTestSuite) setupNewERC20PrecompileForTokenPair( tokenPair erc20types.TokenPair, ) (*erc20.Precompile, error) { + erc20ABI, err := erc20.LoadABI() + if err != nil { + return nil, err + } precompile, err := erc20.NewPrecompile( tokenPair, is.network.App.GetBankKeeper(), is.network.App.GetErc20Keeper(), is.network.App.GetTransferKeeper(), + erc20ABI, ) if err != nil { return nil, errorsmod.Wrapf(err, "failed to create %q erc20 precompile", tokenPair.Denom) diff --git a/tests/integration/precompiles/erc20factory/test_erc20factory.go b/tests/integration/precompiles/erc20factory/test_erc20factory.go new file mode 100644 index 000000000..41ca6ce21 --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_erc20factory.go @@ -0,0 +1,67 @@ +package erc20factory + +import ( + "math/big" + + "github.com/cosmos/evm/precompiles/erc20factory" + utiltx "github.com/cosmos/evm/testutil/tx" +) + +const ( + tokenName = "Test" + tokenSymbol = "TEST" +) + +func (s *PrecompileTestSuite) TestIsTransaction() { + s.SetupTest() + + // Queries + method := s.precompile.Methods[erc20factory.CalculateAddressMethod] + s.Require().False(s.precompile.IsTransaction(&method)) + + // Transactions + method = s.precompile.Methods[erc20factory.CreateMethod] + s.Require().True(s.precompile.IsTransaction(&method)) +} + +func (s *PrecompileTestSuite) TestRequiredGas() { + s.SetupTest() + + mintAddr := utiltx.GenerateAddress() + decimals := uint8(18) + amount := big.NewInt(1000000) + name := tokenName + symbol := tokenSymbol + + testcases := []struct { + name string + malleate func() []byte + expGas uint64 + }{ + { + name: erc20factory.CalculateAddressMethod, + malleate: func() []byte { + bz, err := s.precompile.Pack(erc20factory.CalculateAddressMethod, [32]uint8{}) + s.Require().NoError(err, "expected no error packing ABI") + return bz + }, + expGas: erc20factory.GasCalculateAddress, + }, + { + name: erc20factory.CreateMethod, + malleate: func() []byte { + bz, err := s.precompile.Pack(erc20factory.CreateMethod, [32]uint8{}, name, symbol, decimals, mintAddr, amount) + s.Require().NoError(err, "expected no error packing ABI") + return bz + }, + expGas: erc20factory.GasCreate, + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + gas := s.precompile.RequiredGas(tc.malleate()) + s.Require().Equal(tc.expGas, gas) + }) + } +} diff --git a/tests/integration/precompiles/erc20factory/test_events.go b/tests/integration/precompiles/erc20factory/test_events.go new file mode 100644 index 000000000..1fd8cd857 --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_events.go @@ -0,0 +1,70 @@ +package erc20factory + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + + cmn "github.com/cosmos/evm/precompiles/common" + "github.com/cosmos/evm/precompiles/erc20factory" + utiltx "github.com/cosmos/evm/testutil/tx" +) + +func (s *PrecompileTestSuite) TestEmitCreateEvent() { + testcases := []struct { + testName string + tokenAddress common.Address + tokenType uint8 + salt [32]uint8 + name string + symbol string + decimals uint8 + minter common.Address + premintedSupply *big.Int + }{ + { + testName: "pass", + tokenAddress: utiltx.GenerateAddress(), + tokenType: 0, + salt: [32]uint8{0}, + name: "Test", + symbol: "TEST", + decimals: 18, + minter: utiltx.GenerateAddress(), + premintedSupply: big.NewInt(1000000), + }, + } + + for _, tc := range testcases { + s.Run(tc.testName, func() { + s.SetupTest() + stateDB := s.network.GetStateDB() + + err := s.precompile.EmitCreateEvent(s.network.GetContext(), stateDB, tc.tokenAddress, tc.salt, tc.name, tc.symbol, tc.decimals, tc.minter, tc.premintedSupply) + s.Require().NoError(err, "expected create event to be emitted successfully") + + log := stateDB.Logs()[0] + s.Require().Equal(log.Address, s.precompile.Address()) + + // Check event signature matches the one emitted + event := s.precompile.ABI.Events[erc20factory.EventTypeCreate] + s.Require().Equal(crypto.Keccak256Hash([]byte(event.Sig)), common.HexToHash(log.Topics[0].Hex())) + s.Require().Equal(log.BlockNumber, uint64(s.network.GetContext().BlockHeight())) //nolint:gosec // G115 + + // Check event parameters + var createEvent erc20factory.EventCreate + err = cmn.UnpackLog(s.precompile.ABI, &createEvent, erc20factory.EventTypeCreate, *log) + s.Require().NoError(err, "unable to unpack log into create event") + + s.Require().Equal(tc.tokenAddress, createEvent.TokenAddress, "expected different token address") + s.Require().Equal(tc.tokenType, createEvent.TokenPairType, "expected different token type") + s.Require().Equal(tc.salt, createEvent.Salt, "expected different salt") + s.Require().Equal(tc.name, createEvent.Name, "expected different name") + s.Require().Equal(tc.symbol, createEvent.Symbol, "expected different symbol") + s.Require().Equal(tc.decimals, createEvent.Decimals, "expected different decimals") + s.Require().Equal(tc.minter, createEvent.Minter, "expected different minter") + s.Require().Equal(tc.premintedSupply, createEvent.PremintedSupply, "expected different preminted supply") + }) + } +} diff --git a/tests/integration/precompiles/erc20factory/test_query.go b/tests/integration/precompiles/erc20factory/test_query.go new file mode 100644 index 000000000..fd17eb274 --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_query.go @@ -0,0 +1,65 @@ +package erc20factory + +import ( + "github.com/ethereum/go-ethereum/common" + + "github.com/cosmos/evm/precompiles/erc20factory" +) + +func (s *PrecompileTestSuite) TestCalculateAddress() { + defaultCaller := common.HexToAddress("0xDc411BaFB148ebDA2B63EBD5f3D8669DD4383Af5") + + testcases := []struct { + name string + caller common.Address + args []interface{} + expPass bool + errContains string + expAddress common.Address + }{ + { + name: "pass - correct arguments", + caller: defaultCaller, + args: []interface{}{ + [32]uint8(common.HexToHash("0x4f5b6f778b28c4d67a9c12345678901234567890123456789012345678901234").Bytes()), + }, + expPass: true, + expAddress: common.HexToAddress("0xc047E2F9302F4dE42115E40CEdb3FA0F1CfbD6b7"), + }, + { + name: "fail - invalid salt", + caller: defaultCaller, + args: []interface{}{ + "invalid salt", + }, + errContains: "invalid salt", + }, + { + name: "fail - invalid number of arguments", + caller: defaultCaller, + args: []interface{}{ + 1, 2, 3, + }, + errContains: "invalid number of arguments", + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + s.SetupTest() + + precompile := s.setupERC20FactoryPrecompile() + + method := precompile.Methods[erc20factory.CalculateAddressMethod] + + bz, err := precompile.CalculateAddress( + &method, + tc.caller, + tc.args, + ) + + // NOTE: all output and error checking happens in here + s.requireOut(bz, err, method, tc.expPass, tc.errContains, tc.expAddress) + }) + } +} diff --git a/tests/integration/precompiles/erc20factory/test_setup.go b/tests/integration/precompiles/erc20factory/test_setup.go new file mode 100644 index 000000000..e8f07c504 --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_setup.go @@ -0,0 +1,62 @@ +package erc20factory + +import ( + "github.com/stretchr/testify/suite" + + "github.com/cosmos/evm/precompiles/erc20factory" + "github.com/cosmos/evm/testutil/integration/evm/factory" + "github.com/cosmos/evm/testutil/integration/evm/grpc" + "github.com/cosmos/evm/testutil/integration/evm/network" + testkeyring "github.com/cosmos/evm/testutil/keyring" +) + +// PrecompileTestSuite is the implementation of the TestSuite interface for ERC20 Factory precompile +// unit tests. +type PrecompileTestSuite struct { + suite.Suite + + create network.CreateEvmApp + options []network.ConfigOption + bondDenom string + network *network.UnitTestNetwork + factory factory.TxFactory + grpcHandler grpc.Handler + keyring testkeyring.Keyring + + precompile *erc20factory.Precompile +} + +func NewPrecompileTestSuite(create network.CreateEvmApp, options ...network.ConfigOption) *PrecompileTestSuite { + return &PrecompileTestSuite{ + create: create, + options: options, + } +} + +func (s *PrecompileTestSuite) SetupTest() { + keyring := testkeyring.New(2) + options := []network.ConfigOption{ + network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), + } + options = append(options, s.options...) + integrationNetwork := network.NewUnitTestNetwork(s.create, options...) + grpcHandler := grpc.NewIntegrationHandler(integrationNetwork) + txFactory := factory.New(integrationNetwork, grpcHandler) + + ctx := integrationNetwork.GetContext() + sk := integrationNetwork.App.GetStakingKeeper() + bondDenom, err := sk.BondDenom(ctx) + s.Require().NoError(err) + s.Require().NotEmpty(bondDenom, "bond denom cannot be empty") + + s.bondDenom = bondDenom + s.factory = txFactory + s.grpcHandler = grpcHandler + s.keyring = keyring + s.network = integrationNetwork + + // Instantiate the precompile with an exemplary token denomination. + // + // NOTE: This has to be done AFTER assigning the suite fields. + s.precompile = s.setupERC20FactoryPrecompile() +} diff --git a/tests/integration/precompiles/erc20factory/test_tx.go b/tests/integration/precompiles/erc20factory/test_tx.go new file mode 100644 index 000000000..e83b83982 --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_tx.go @@ -0,0 +1,164 @@ +package erc20factory + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/cosmos/evm/precompiles/erc20factory" + erc20types "github.com/cosmos/evm/x/erc20/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (s *PrecompileTestSuite) TestCreate() { + caller := common.HexToAddress("0x2c7882f69Cd115F470aAEde121f57F932936a56f") + mintAddr := common.HexToAddress("0x73657398D483143AF7db7899757e5E7037fB713d") + expectedAddress := common.HexToAddress("0xc5ecc46b3cf020351c2186afCD5C734EE15E4da2") + amount := big.NewInt(1000000) + decimals := uint8(18) + name := "Test" + symbol := "TEST" + + method := s.precompile.Methods[erc20factory.CreateMethod] + + testcases := []struct { + name string + args []interface{} + expPass bool + postExpPass func(output []byte) + errContains string + expAddress common.Address + }{ + { + name: "pass - correct arguments", + args: []interface{}{[32]uint8(common.HexToHash("0x4f5b6f778b28c4d67a9c12345678901234567890123456789012345678901234").Bytes()), name, symbol, decimals, mintAddr, amount}, + expPass: true, + postExpPass: func(output []byte) { + res, err := method.Outputs.Unpack(output) + s.Require().NoError(err, "expected no error unpacking output") + s.Require().Len(res, 1, "expected one output") + address, ok := res[0].(common.Address) + s.Require().True(ok, "expected address type") + + // Check the balance of the token for the mintAddr + balance := s.network.App.GetBankKeeper().GetBalance(s.network.GetContext(), sdk.AccAddress(mintAddr.Bytes()), erc20types.CreateDenom(address.String())) + s.Require().Equal(amount, balance.Amount.BigInt(), "expected balance to match preminted amount") + + s.Require().Equal(address.String(), expectedAddress, "expected address to match") + }, + expAddress: expectedAddress, + }, + { + name: "fail - blocked addresses cannot receive tokens", + args: []interface{}{ + [32]uint8(common.HexToHash("0x4f5b6f778b28c4d67a9c12345678901234567890123456789012345678901234").Bytes()), + name, + symbol, + decimals, + erc20types.ModuleAddress, + amount, + }, + }, + { + name: "fail - invalid salt", + args: []interface{}{ + "invalid salt", + name, + symbol, + decimals, + mintAddr, + amount, + }, + errContains: "invalid salt", + }, + { + name: "fail - invalid name", + args: []interface{}{ + [32]uint8{}, + "", + symbol, + decimals, + mintAddr, + amount, + }, + errContains: "invalid name", + }, + { + name: "fail - invalid symbol", + args: []interface{}{ + [32]uint8{}, + name, + "", + decimals, + mintAddr, + amount, + }, + errContains: "invalid symbol", + }, + { + name: "fail - invalid decimals", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + "invalid decimals", + mintAddr, + amount, + }, + errContains: "invalid decimals", + }, + { + name: "fail - invalid minter", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + decimals, + "invalid address", + amount, + }, + errContains: "invalid minter", + }, + { + name: "fail - invalid preminted supply", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + decimals, + mintAddr, + "invalid amount", + }, + errContains: "invalid premintedSupply", + }, + { + name: "fail - invalid number of arguments", + args: []interface{}{ + 1, 2, 3, + }, + errContains: "invalid number of arguments", + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + s.SetupTest() + + precompile := s.setupERC20FactoryPrecompile() + + method := precompile.Methods[erc20factory.CreateMethod] + + bz, err := precompile.Create( + s.network.GetContext(), + s.network.GetStateDB(), + &method, + caller, + tc.args, + ) + + // NOTE: all output and error checking happens in here + s.requireOut(bz, err, method, tc.expPass, tc.errContains, tc.expAddress) + }) + } +} diff --git a/tests/integration/precompiles/erc20factory/test_types.go b/tests/integration/precompiles/erc20factory/test_types.go new file mode 100644 index 000000000..bc665c95f --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_types.go @@ -0,0 +1,193 @@ +package erc20factory + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/cosmos/evm/precompiles/erc20factory" + utiltx "github.com/cosmos/evm/testutil/tx" +) + +func (s *PrecompileTestSuite) TestParseCalculateAddressArgs() { + s.SetupTest() + + testcases := []struct { + name string + args []interface{} + expPass bool + errContains string + }{ + { + name: "pass - correct arguments", + args: []interface{}{ + [32]uint8{}, + }, + expPass: true, + }, + { + name: "fail - invalid salt", + args: []interface{}{ + uint8(0), + "invalid salt", + }, + }, + { + name: "fail - invalid number of arguments", + args: []interface{}{ + 1, 2, 3, + }, + errContains: "invalid number of arguments", + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + salt, err := erc20factory.ParseCalculateAddressArgs(tc.args) + if tc.expPass { + s.Require().NoError(err, "unexpected error parsing the calculate address arguments") + s.Require().Equal(salt, tc.args[0], "expected different salt") + } else { + s.Require().Error(err, "expected an error parsing the calculate address arguments") + s.Require().ErrorContains(err, tc.errContains, "expected different error message") + } + }) + } +} + +func (s *PrecompileTestSuite) TestParseCreateArgs() { + addr := utiltx.GenerateAddress() + decimals := uint8(18) + amount := big.NewInt(1000000) + name := "Test" + symbol := "TEST" + + s.SetupTest() + + testcases := []struct { + name string + args []interface{} + expPass bool + errContains string + }{ + { + name: "pass - correct arguments", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + decimals, + addr, + amount, + }, + expPass: true, + }, + { + name: "fail - invalid salt", + args: []interface{}{ + "invalid salt", + name, + symbol, + decimals, + addr, + big.NewInt(1000000), + }, + }, + { + name: "fail - invalid name", + args: []interface{}{ + [32]uint8{}, + uint8(0), + symbol, + decimals, + addr, + big.NewInt(1000000), + }, + errContains: "invalid name", + }, + { + name: "fail - invalid symbol", + args: []interface{}{ + [32]uint8{}, + name, + "", + decimals, + addr, + big.NewInt(1000000), + }, + errContains: "invalid symbol", + }, + { + name: "fail - invalid decimals", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + "invalid decimals", + addr, + big.NewInt(1000000), + }, + errContains: "invalid decimals", + }, + { + name: "fail - invalid minter", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + decimals, + "invalid address", + big.NewInt(1000000), + }, + errContains: "invalid minter", + }, + { + name: "fail - zero address minter", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + decimals, + common.Address{}, // Zero address + big.NewInt(1000000), + }, + errContains: "invalid minter: cannot be zero address", + }, + { + name: "fail - invalid preminted supply", + args: []interface{}{ + [32]uint8{}, + name, + symbol, + decimals, + addr, + big.NewInt(-1), + }, + errContains: "invalid premintedSupply: cannot be negative", + }, + { + name: "fail - invalid number of arguments", + args: []interface{}{ + 1, 2, 3, 4, 5, + }, + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + salt, name, symbol, decimals, minter, premintedSupply, err := erc20factory.ParseCreateArgs(tc.args) + if tc.expPass { + s.Require().NoError(err, "unexpected error parsing the create arguments") + s.Require().Equal(salt, tc.args[0], "expected different salt") + s.Require().Equal(name, tc.args[1], "expected different name") + s.Require().Equal(symbol, tc.args[2], "expected different symbol") + s.Require().Equal(decimals, tc.args[3], "expected different decimals") + s.Require().Equal(minter, tc.args[4], "expected different minter") + s.Require().Equal(premintedSupply, tc.args[5], "expected different preminted supply") + } else { + s.Require().Error(err, "expected an error parsing the create arguments") + s.Require().ErrorContains(err, tc.errContains, "expected different error message") + } + }) + } +} diff --git a/tests/integration/precompiles/erc20factory/test_utils.go b/tests/integration/precompiles/erc20factory/test_utils.go new file mode 100644 index 000000000..c85d95aa1 --- /dev/null +++ b/tests/integration/precompiles/erc20factory/test_utils.go @@ -0,0 +1,59 @@ +package erc20factory + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/cosmos/evm/precompiles/erc20factory" +) + +func (s *PrecompileTestSuite) setupERC20FactoryPrecompile() *erc20factory.Precompile { + precompile, err := erc20factory.NewPrecompile( + s.network.App.GetErc20Keeper(), + s.network.App.GetBankKeeper(), + s.network.App.GetEVMKeeper(), + ) + s.Require().NoError(err, "failed to create erc20factory precompile") + + return precompile +} + +// requireOut is a helper utility to reduce the amount of boilerplate code in the query tests. +// +// It requires the output bytes and error to match the expected values. Additionally, the method outputs +// are unpacked and the first value is compared to the expected value. +// +// NOTE: It's sufficient to only check the first value because all methods in the ERC20 precompile only +// return a single value. +func (s *PrecompileTestSuite) requireOut( + bz []byte, + err error, + method abi.Method, + expPass bool, + errContains string, + expValue interface{}, +) { + if expPass { + s.Require().NoError(err, "expected no error") + s.Require().NotEmpty(bz, "expected bytes not to be empty") + + // Unpack the name into a string + out, err := method.Outputs.Unpack(bz) + s.Require().NoError(err, "expected no error unpacking") + + // Check if expValue is a big.Int. Because of a difference in uninitialized/empty values for big.Ints, + // this comparison is often not working as expected, so we convert to Int64 here and compare those values. + bigExp, ok := expValue.(*big.Int) + if ok { + bigOut, ok := out[0].(*big.Int) + s.Require().True(ok, "expected output to be a big.Int") + s.Require().Equal(bigExp.Int64(), bigOut.Int64(), "expected different value") + } else { + s.Require().Equal(expValue, out[0], "expected different value") + } + } else { + s.Require().Error(err, "expected error") + s.Require().Contains(err.Error(), errContains, "expected different error") + } +} diff --git a/tests/integration/precompiles/gov/test_gov.go b/tests/integration/precompiles/gov/test_gov.go index 1b37f7ff7..b2a2aee96 100644 --- a/tests/integration/precompiles/gov/test_gov.go +++ b/tests/integration/precompiles/gov/test_gov.go @@ -107,11 +107,10 @@ func (s *PrecompileTestSuite) TestRun() { s.Require().NoError(err, "failed to instantiate EVM config") // Instantiate EVM - headerHash := ctx.HeaderHash() stDB := statedb.New( ctx, s.network.App.GetEVMKeeper(), - statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), + statedb.NewEmptyTxConfig(), ) evm := s.network.App.GetEVMKeeper().NewEVM( ctx, *msg, cfg, nil, stDB, diff --git a/tests/integration/precompiles/gov/test_setup.go b/tests/integration/precompiles/gov/test_setup.go index 1c71b3f4f..312f91b47 100644 --- a/tests/integration/precompiles/gov/test_setup.go +++ b/tests/integration/precompiles/gov/test_setup.go @@ -19,6 +19,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" ) @@ -136,8 +137,10 @@ func (s *PrecompileTestSuite) SetupTest() { s.keyring = keyring s.network = nw + govKeeper := s.network.App.GetGovKeeper() if s.precompile, err = gov.NewPrecompile( - s.network.App.GetGovKeeper(), + govkeeper.NewMsgServerImpl(&govKeeper), + govkeeper.NewQueryServer(&govKeeper), s.network.App.GetBankKeeper(), s.network.App.AppCodec(), address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), diff --git a/tests/integration/precompiles/ics20/test_setup.go b/tests/integration/precompiles/ics20/test_setup.go index 28ce0c399..462e7c6b7 100644 --- a/tests/integration/precompiles/ics20/test_setup.go +++ b/tests/integration/precompiles/ics20/test_setup.go @@ -48,7 +48,6 @@ func (s *PrecompileTestSuite) SetupTest() { *evmAppA.GetStakingKeeper(), evmAppA.GetTransferKeeper(), evmAppA.GetIBCKeeper().ChannelKeeper, - evmAppA.GetEVMKeeper(), ) s.chainABondDenom, _ = evmAppA.GetStakingKeeper().BondDenom(s.chainA.GetContext()) evmAppB := s.chainB.App.(evm.EvmApp) @@ -57,7 +56,6 @@ func (s *PrecompileTestSuite) SetupTest() { *evmAppB.GetStakingKeeper(), evmAppB.GetTransferKeeper(), evmAppB.GetIBCKeeper().ChannelKeeper, - evmAppB.GetEVMKeeper(), ) s.chainBBondDenom, _ = evmAppB.GetStakingKeeper().BondDenom(s.chainB.GetContext()) } diff --git a/tests/integration/precompiles/slashing/test_setup.go b/tests/integration/precompiles/slashing/test_setup.go index 7558a34f5..f5118c5e6 100644 --- a/tests/integration/precompiles/slashing/test_setup.go +++ b/tests/integration/precompiles/slashing/test_setup.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" ) type PrecompileTestSuite struct { @@ -56,6 +57,7 @@ func (s *PrecompileTestSuite) SetupTest() { if s.precompile, err = slashing.NewPrecompile( s.network.App.GetSlashingKeeper(), + slashingkeeper.NewMsgServerImpl(s.network.App.GetSlashingKeeper()), s.network.App.GetBankKeeper(), address.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), address.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), diff --git a/tests/integration/precompiles/staking/test_integration.go b/tests/integration/precompiles/staking/test_integration.go index 7d49f82df..13e48e60c 100644 --- a/tests/integration/precompiles/staking/test_integration.go +++ b/tests/integration/precompiles/staking/test_integration.go @@ -1896,6 +1896,58 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp txSenderFinalBal := balRes.Balance Expect(txSenderFinalBal.Amount).To(Equal(txSenderInitialBal.Amount.Sub(fees)), "expected tx sender balance to be deducted by fees") }) + It("should test nested precompile calls with revert", func() { + outerTimes := int64(3) + innerTimes := int64(2) + expectedDelegations := outerTimes + 2 // 1 before + outerTimes after catches + 1 after loop + expectedDelegationAmount := math.NewInt(10).MulRaw(expectedDelegations) + + callArgs := testutiltypes.CallArgs{ + ContractABI: stakingReverterContract.ABI, + MethodName: "nestedTryCatchDelegations", + Args: []interface{}{ + big.NewInt(outerTimes), big.NewInt(innerTimes), s.network.GetValidators()[0].OperatorAddress, + }, + } + + expEvents := make([]string, 0, expectedDelegations) + for range expectedDelegations { + expEvents = append(expEvents, staking.EventTypeDelegate) + } + delegateCheck := passCheck.WithExpEvents(expEvents...) + + res, _, err := s.factory.CallContractAndCheckLogs( + s.keyring.GetPrivKey(0), + evmtypes.EvmTxArgs{ + To: &stkReverterAddr, + GasPrice: gasPrice.BigInt(), + }, + callArgs, + delegateCheck, + ) + Expect(err).To(BeNil(), "error while calling the smart contract: %v", err) + Expect(s.network.NextBlock()).To(BeNil()) + + fees := gasPrice.MulRaw(res.GasUsed) + + // delegation should have been created with expected shares + qRes, err := s.grpcHandler.GetDelegation(sdk.AccAddress(stkReverterAddr.Bytes()).String(), s.network.GetValidators()[0].OperatorAddress) + Expect(err).To(BeNil()) + Expect(qRes.DelegationResponse.Delegation.GetDelegatorAddr()).To(Equal(sdk.AccAddress(stkReverterAddr.Bytes()).String())) + Expect(qRes.DelegationResponse.Delegation.GetShares().BigInt()).To(Equal(expectedDelegationAmount.BigInt())) + + // contract balance should be deducted by total delegation amount + balRes, err := s.grpcHandler.GetBalanceFromBank(stkReverterAddr.Bytes(), s.bondDenom) + Expect(err).To(BeNil()) + contractFinalBalance := balRes.Balance + Expect(contractFinalBalance.Amount).To(Equal(contractInitialBalance.Amount.Sub(expectedDelegationAmount))) + + // fees deducted on tx sender only + balRes, err = s.grpcHandler.GetBalanceFromBank(s.keyring.GetAccAddr(0), s.bondDenom) + Expect(err).To(BeNil()) + txSenderFinalBal := balRes.Balance + Expect(txSenderFinalBal.Amount).To(Equal(txSenderInitialBal.Amount.Sub(fees))) + }) }) Context("Table-driven tests for Delegate method", func() { diff --git a/tests/integration/precompiles/staking/test_setup.go b/tests/integration/precompiles/staking/test_setup.go index 2e7aedfa5..cb4e04d63 100644 --- a/tests/integration/precompiles/staking/test_setup.go +++ b/tests/integration/precompiles/staking/test_setup.go @@ -16,6 +16,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) const InitialTestBalance = 1000000000000000000 // 1 atom @@ -82,6 +83,8 @@ func (s *PrecompileTestSuite) SetupTest() { if s.precompile, err = staking.NewPrecompile( *s.network.App.GetStakingKeeper(), + stakingkeeper.NewMsgServerImpl(s.network.App.GetStakingKeeper()), + stakingkeeper.NewQuerier(s.network.App.GetStakingKeeper()), s.network.App.GetBankKeeper(), address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), ); err != nil { diff --git a/tests/integration/precompiles/staking/test_staking.go b/tests/integration/precompiles/staking/test_staking.go index b61c2cad1..d8b5149dc 100644 --- a/tests/integration/precompiles/staking/test_staking.go +++ b/tests/integration/precompiles/staking/test_staking.go @@ -436,11 +436,10 @@ func (s *PrecompileTestSuite) TestRun() { s.Require().NoError(err, "failed to instantiate EVM config") // Instantiate EVM - headerHash := ctx.HeaderHash() stDB := statedb.New( ctx, s.network.App.GetEVMKeeper(), - statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), + statedb.NewEmptyTxConfig(), ) evm := s.network.App.GetEVMKeeper().NewEVM( ctx, *msg, cfg, nil, stDB, diff --git a/tests/integration/precompiles/werc20/test_events.go b/tests/integration/precompiles/werc20/test_events.go index e4734754d..8d1a3be45 100644 --- a/tests/integration/precompiles/werc20/test_events.go +++ b/tests/integration/precompiles/werc20/test_events.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/suite" cmn "github.com/cosmos/evm/precompiles/common" + "github.com/cosmos/evm/precompiles/erc20" "github.com/cosmos/evm/precompiles/werc20" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" @@ -72,11 +73,18 @@ func (s *PrecompileUnitTestSuite) SetupTest(chainID testconstants.ChainID) { s.Require().True(found, "expected wevmos precompile to be registered in the tokens map") s.Require().Equal(s.precompileAddrHex, tokenPair.Erc20Address, "expected a different address of the contract") + erc20ABI, err := erc20.LoadABI() + s.Require().NoError(err) + werc20ABI, err := werc20.LoadABI() + s.Require().NoError(err) + precompile, err := werc20.NewPrecompile( tokenPair, s.network.App.GetBankKeeper(), s.network.App.GetErc20Keeper(), s.network.App.GetTransferKeeper(), + erc20ABI, + werc20ABI, ) s.Require().NoError(err, "failed to instantiate the werc20 precompile") s.Require().NotNil(precompile) diff --git a/tests/integration/precompiles/werc20/test_integration.go b/tests/integration/precompiles/werc20/test_integration.go index 686bdb65f..3185954d7 100644 --- a/tests/integration/precompiles/werc20/test_integration.go +++ b/tests/integration/precompiles/werc20/test_integration.go @@ -160,11 +160,19 @@ func TestPrecompileIntegrationTestSuite(t *testing.T, create network.CreateEvmAp evmtypes.GetEVMCoinDenom(), erc20types.OWNER_MODULE, ) + + erc20ABI, err := erc20.LoadABI() + Expect(err).To(BeNil()) + werc20ABI, err := werc20.LoadABI() + Expect(err).To(BeNil()) + precompile, err := werc20.NewPrecompile( tokenPair, is.network.App.GetBankKeeper(), is.network.App.GetErc20Keeper(), is.network.App.GetTransferKeeper(), + erc20ABI, + werc20ABI, ) Expect(err).ToNot(HaveOccurred(), "failed to instantiate the werc20 precompile") is.precompile = precompile diff --git a/tests/integration/rpc/backend/test_backend_suite.go b/tests/integration/rpc/backend/test_backend_suite.go index 053bd93c8..c464d673b 100644 --- a/tests/integration/rpc/backend/test_backend_suite.go +++ b/tests/integration/rpc/backend/test_backend_suite.go @@ -91,7 +91,7 @@ func (s *TestSuite) SetupTest() { allowUnprotectedTxs := false idxer := indexer.NewKVIndexer(dbm.NewMemDB(), ctx.Logger, clientCtx) - s.backend = rpcbackend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer) + s.backend = rpcbackend.NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs, idxer, nil) s.backend.Cfg.JSONRPC.GasCap = 0 s.backend.Cfg.JSONRPC.EVMTimeout = 0 s.backend.Cfg.JSONRPC.AllowInsecureUnlock = true diff --git a/tests/integration/rpc/backend/test_client.go b/tests/integration/rpc/backend/test_client.go index c3971b49b..1df0c9277 100644 --- a/tests/integration/rpc/backend/test_client.go +++ b/tests/integration/rpc/backend/test_client.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -23,6 +24,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -199,19 +201,23 @@ func TestRegisterConsensusParams(t *testing.T) { } // BlockResults - func RegisterBlockResultsWithEventLog(client *mocks.Client, height int64) (*cmtrpctypes.ResultBlockResults, error) { + anyValue, err := codectypes.NewAnyWithValue(&evmtypes.MsgEthereumTxResponse{ + Logs: []*evmtypes.Log{ + {Data: []byte("data")}, + }, + }) + if err != nil { + return nil, err + } + data, err := proto.Marshal(&sdk.TxMsgData{MsgResponses: []*codectypes.Any{anyValue}}) + if err != nil { + return nil, err + } res := &cmtrpctypes.ResultBlockResults{ Height: height, TxsResults: []*abci.ExecTxResult{ - {Code: 0, GasUsed: 0, Events: []abci.Event{{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{{ - Key: evmtypes.AttributeKeyTxLog, - Value: "{\"test\": \"hello\"}", // TODO refactor the value to unmarshall to a evmtypes.Log struct successfully - Index: true, - }}, - }}}, + {Code: 0, GasUsed: 0, Data: data}, }, } client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). diff --git a/tests/integration/rpc/backend/test_filters.go b/tests/integration/rpc/backend/test_filters.go index 844334333..67b945da8 100644 --- a/tests/integration/rpc/backend/test_filters.go +++ b/tests/integration/rpc/backend/test_filters.go @@ -1,8 +1,6 @@ package backend import ( - "encoding/json" - "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" @@ -16,12 +14,12 @@ import ( func (s *TestSuite) TestGetLogs() { _, bz := s.buildEthereumTx() block := cmttypes.MakeBlock(1, []cmttypes.Tx{bz}, nil, nil) - logs := make([]*evmtypes.Log, 0, 1) - var log evmtypes.Log - err := json.Unmarshal([]byte("{\"test\": \"hello\"}"), &log) // TODO refactor this to unmarshall to a log struct successfully - s.Require().NoError(err) - - logs = append(logs, &log) + logs := []*evmtypes.Log{ + { + Data: []byte("data"), + BlockNumber: 1, + }, + } testCases := []struct { name string diff --git a/tests/integration/rpc/backend/test_tx_info.go b/tests/integration/rpc/backend/test_tx_info.go index f79ab273a..3c74471aa 100644 --- a/tests/integration/rpc/backend/test_tx_info.go +++ b/tests/integration/rpc/backend/test_tx_info.go @@ -710,18 +710,15 @@ func (s *TestSuite) TestGetTransactionReceipt() { } func (s *TestSuite) TestGetGasUsed() { - origin := s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight testCases := []struct { - name string - fixRevertGasRefundHeight int64 - txResult *cosmosevmtypes.TxResult - price *big.Int - gas uint64 - exp uint64 + name string + txResult *cosmosevmtypes.TxResult + price *big.Int + gas uint64 + exp uint64 }{ { "success txResult", - 1, &cosmosevmtypes.TxResult{ Height: 1, Failed: false, @@ -732,20 +729,7 @@ func (s *TestSuite) TestGetGasUsed() { 53026, }, { - "fail txResult before cap", - 2, - &cosmosevmtypes.TxResult{ - Height: 1, - Failed: true, - GasUsed: 53026, - }, - new(big.Int).SetUint64(200000), - 5000000000000, - 1000000000000000000, - }, - { - "fail txResult after cap", - 2, + "fail txResult", &cosmosevmtypes.TxResult{ Height: 3, Failed: true, @@ -758,9 +742,7 @@ func (s *TestSuite) TestGetGasUsed() { } for _, tc := range testCases { s.Run(fmt.Sprintf("Case %s", tc.name), func() { - s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight = tc.fixRevertGasRefundHeight s.Require().Equal(tc.exp, s.backend.GetGasUsed(tc.txResult, tc.price, tc.gas)) - s.backend.Cfg.JSONRPC.FixRevertGasRefundHeight = origin }) } } diff --git a/tests/integration/x/ibc/test_msg_server.go b/tests/integration/x/ibc/test_msg_server.go index 79d8fa8c8..56a9599ce 100644 --- a/tests/integration/x/ibc/test_msg_server.go +++ b/tests/integration/x/ibc/test_msg_server.go @@ -341,7 +341,6 @@ func (suite *KeeperTestSuite) TestTransfer() { suite.network.App.SetTransferKeeper(transferkeeper.NewKeeper( suite.network.App.AppCodec(), runtime.NewKVStoreService(suite.network.App.GetKey(types.StoreKey)), - suite.network.App.GetSubspace(types.ModuleName), &MockICS4Wrapper{}, // ICS4 Wrapper mockChannelKeeper, suite.network.App.MsgServiceRouter(), @@ -494,7 +493,6 @@ func (suite *KeeperTestSuite) TestPrefixTrimming() { suite.network.App.SetTransferKeeper(transferkeeper.NewKeeper( suite.network.App.AppCodec(), runtime.NewKVStoreService(suite.network.App.GetKey(types.StoreKey)), - suite.network.App.GetSubspace(types.ModuleName), &MockICS4Wrapper{}, // ICS4 Wrapper mockChannelKeeper, suite.network.App.MsgServiceRouter(), diff --git a/tests/integration/x/vm/test_genesis.go b/tests/integration/x/vm/test_genesis.go index de241713b..10e5f407c 100644 --- a/tests/integration/x/vm/test_genesis.go +++ b/tests/integration/x/vm/test_genesis.go @@ -119,7 +119,7 @@ func (s *GenesisTestSuite) TestInitGenesis() { ctx = s.network.GetContext() vmdb = statedb.New( ctx, s.network.App.GetEVMKeeper(), - statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) + statedb.NewEmptyTxConfig()) tc.malleate(s.network) err := vmdb.Commit() @@ -222,7 +222,7 @@ func (s *GenesisTestSuite) TestExportGenesis() { genState := vm.ExportGenesis(s.network.GetContext(), s.network.App.GetEVMKeeper()) // Exported accounts 4 default preinstalls - s.Require().Len(genState.Accounts, 7) + s.Require().Len(genState.Accounts, 8) addrs := make([]string, len(genState.Accounts)) for i, acct := range genState.Accounts { diff --git a/tests/integration/x/vm/test_grpc_query.go b/tests/integration/x/vm/test_grpc_query.go index 0a6af97a2..f9b55fac3 100644 --- a/tests/integration/x/vm/test_grpc_query.go +++ b/tests/integration/x/vm/test_grpc_query.go @@ -425,7 +425,6 @@ func (s *KeeperTestSuite) TestQueryTxLogs() { for _, tc := range testCases { s.Run(fmt.Sprintf("Case %s", tc.msg), func() { txCfg := statedb.NewTxConfig( - common.BytesToHash(s.Network.GetContext().HeaderHash()), txHash, txIndex, logIndex, diff --git a/tests/integration/x/vm/test_hooks.go b/tests/integration/x/vm/test_hooks.go index 9127cf9d0..23aef41ac 100644 --- a/tests/integration/x/vm/test_hooks.go +++ b/tests/integration/x/vm/test_hooks.go @@ -70,7 +70,6 @@ func (s *KeeperTestSuite) TestEvmHooks() { ctx := s.Network.GetContext() txHash := common.BigToHash(big.NewInt(1)) vmdb := statedb.New(ctx, k, statedb.NewTxConfig( - common.BytesToHash(ctx.HeaderHash()), txHash, 0, 0, diff --git a/tests/integration/x/vm/test_iterate_contracts.go b/tests/integration/x/vm/test_iterate_contracts.go index 66f2659d2..3c6cd5497 100644 --- a/tests/integration/x/vm/test_iterate_contracts.go +++ b/tests/integration/x/vm/test_iterate_contracts.go @@ -67,7 +67,7 @@ func TestIterateContracts(t *testing.T, create network.CreateEvmApp, options ... return false }) - require.Len(t, foundAddrs, 6, "expected 6 contracts to be found when iterating (4 preinstalled + 2 deployed)") + require.Len(t, foundAddrs, 7, "expected 7 contracts to be found when iterating (5 preinstalled + 2 deployed)") require.Contains(t, foundAddrs, contractAddr, "expected contract 1 to be found when iterating") require.Contains(t, foundAddrs, contractAddr2, "expected contract 2 to be found when iterating") diff --git a/tests/integration/x/vm/test_keeper.go b/tests/integration/x/vm/test_keeper.go index c31b3bb7f..8e5d0b446 100644 --- a/tests/integration/x/vm/test_keeper.go +++ b/tests/integration/x/vm/test_keeper.go @@ -5,6 +5,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + ethparams "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" "github.com/cosmos/evm/utils" @@ -89,7 +90,7 @@ func (s *KeeperTestSuite) TestGetAccountStorage() { storage := s.Network.App.GetEVMKeeper().GetAccountStorage(ctx, address) - if address == contractAddr { + if address == contractAddr || address == ethparams.HistoryStorageAddress { s.Require().NotEqual(0, len(storage), "expected account %d to have non-zero amount of storage slots, got %d", i, len(storage), diff --git a/tests/integration/x/vm/test_msg_server.go b/tests/integration/x/vm/test_msg_server.go index 510a3f1b6..7a32b83d7 100644 --- a/tests/integration/x/vm/test_msg_server.go +++ b/tests/integration/x/vm/test_msg_server.go @@ -63,7 +63,6 @@ func (s *KeeperTestSuite) TestEthereumTx() { // check expected events were emitted s.Require().NotEmpty(events) s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), types.EventTypeEthereumTx)) - s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), types.EventTypeTxLog)) s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), sdktypes.EventTypeMessage)) } diff --git a/tests/integration/x/vm/test_params.go b/tests/integration/x/vm/test_params.go index 9f5402503..4381a8116 100644 --- a/tests/integration/x/vm/test_params.go +++ b/tests/integration/x/vm/test_params.go @@ -63,21 +63,6 @@ func (s *KeeperTestSuite) TestParams() { }, true, }, - { - "success - Check AllowUnprotectedTxs param is set to false and can be retrieved correctly", - func() interface{} { - params := defaultChainEVMParams - params.AllowUnprotectedTxs = false - err := s.Network.App.GetEVMKeeper().SetParams(s.Network.GetContext(), params) - s.Require().NoError(err) - return params.AllowUnprotectedTxs - }, - func() interface{} { - evmParams := s.Network.App.GetEVMKeeper().GetParams(s.Network.GetContext()) - return evmParams.GetAllowUnprotectedTxs() - }, - true, - }, { name: "success - Active precompiles are sorted when setting params", paramsFun: func() interface{} { diff --git a/tests/integration/x/vm/test_state_transition.go b/tests/integration/x/vm/test_state_transition.go index 633ec4ae5..9d6b8af59 100644 --- a/tests/integration/x/vm/test_state_transition.go +++ b/tests/integration/x/vm/test_state_transition.go @@ -1,18 +1,19 @@ package vm import ( + "errors" "fmt" "math" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" + ethtypes "github.com/ethereum/go-ethereum/core/types" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/cometbft/cometbft/crypto/tmhash" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - cmttypes "github.com/cometbft/cometbft/types" "github.com/cosmos/evm/testutil/config" "github.com/cosmos/evm/testutil/integration/evm/factory" @@ -33,7 +34,6 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) func (s *KeeperTestSuite) TestContextSetConsensusParams() { @@ -81,9 +81,11 @@ func (s *KeeperTestSuite) TestContextSetConsensusParams() { func (s *KeeperTestSuite) TestGetHashFn() { s.SetupTest() - header := s.Network.GetContext().BlockHeader() - h, _ := cmttypes.HeaderFromProto(&header) - hash := h.Hash() + s.Require().NoError(s.Network.NextBlock()) + ctx := s.Network.GetContext() + height := uint64(ctx.BlockHeight()) //nolint:gosec // G115 + headerHash := common.BytesToHash(ctx.HeaderHash()) + fmt.Println("get headerHash", height, headerHash) testCases := []struct { msg string @@ -93,7 +95,7 @@ func (s *KeeperTestSuite) TestGetHashFn() { }{ { "case 1.1: context hash cached", - uint64(s.Network.GetContext().BlockHeight()), //nolint:gosec // G115 + height, func() sdk.Context { return s.Network.GetContext().WithHeaderHash( tmhash.Sum([]byte("header")), @@ -102,51 +104,22 @@ func (s *KeeperTestSuite) TestGetHashFn() { common.BytesToHash(tmhash.Sum([]byte("header"))), }, { - "case 1.2: failed to cast CometBFT header", - uint64(s.Network.GetContext().BlockHeight()), //nolint:gosec // G115 + "case 1.2: works for invalid CometBFT header", + height, func() sdk.Context { header := tmproto.Header{} header.Height = s.Network.GetContext().BlockHeight() return s.Network.GetContext().WithBlockHeader(header) }, - common.Hash{}, - }, - { - "case 1.3: hash calculated from CometBFT header", - uint64(s.Network.GetContext().BlockHeight()), //nolint:gosec // G115 - func() sdk.Context { - return s.Network.GetContext().WithBlockHeader(header) - }, - common.BytesToHash(hash), - }, - { - "case 2.1: height lower than current one, hist info not found", - 1, - func() sdk.Context { - return s.Network.GetContext().WithBlockHeight(10) - }, - common.Hash{}, - }, - { - "case 2.2: height lower than current one, invalid hist info header", - 1, - func() sdk.Context { - s.Require().NoError(s.Network.App.GetStakingKeeper().SetHistoricalInfo(s.Network.GetContext(), 1, &stakingtypes.HistoricalInfo{})) - return s.Network.GetContext().WithBlockHeight(10) - }, - common.Hash{}, + headerHash, }, { - "case 2.3: height lower than current one, calculated from hist info header", - 1, + "case 2.1: height lower than current one works", + height, func() sdk.Context { - histInfo := &stakingtypes.HistoricalInfo{ - Header: header, - } - s.Require().NoError(s.Network.App.GetStakingKeeper().SetHistoricalInfo(s.Network.GetContext(), 1, histInfo)) return s.Network.GetContext().WithBlockHeight(10) }, - common.BytesToHash(hash), + headerHash, }, { "case 3: height greater than current one", @@ -653,6 +626,173 @@ func (s *KeeperTestSuite) TestApplyTransaction() { } } +type testHooks struct { + postProcessing func(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error +} + +func (h *testHooks) PostTxProcessing(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error { + return h.postProcessing(ctx, sender, msg, receipt) +} + +func (s *KeeperTestSuite) TestApplyTransactionWithTxPostProcessing() { + s.EnableFeemarket = true + defer func() { s.EnableFeemarket = false }() + + testCases := []struct { + name string + setup func(s *KeeperTestSuite) + do func(s *KeeperTestSuite) + after func(s *KeeperTestSuite) + }{ + { + "pass - evm tx succeeds, post processing is called, the balance is changed", + func(s *KeeperTestSuite) { + s.Network.App.GetEVMKeeper().SetHooks( + keeper.NewMultiEvmHooks( + &testHooks{ + postProcessing: func(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error { + return nil + }, + }, + ), + ) + }, + func(s *KeeperTestSuite) { + senderBefore := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(0), "aatom").Amount + recipientBefore := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(1), "aatom").Amount + + // Generate a transfer tx message + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + transferAmt := big.NewInt(100) + + tx, err := s.Factory.GenerateSignedEthTx(sender.Priv, types.EvmTxArgs{ + To: &recipient, + Amount: transferAmt, + }) + s.Require().NoError(err) + + ethMsg := tx.GetMsgs()[0].(*types.MsgEthereumTx) + res, err := s.Network.App.GetEVMKeeper().ApplyTransaction(s.Network.GetContext(), ethMsg.AsTransaction()) + s.Require().NoError(err) + s.Require().False(res.Failed()) + + senderAfter := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(0), "aatom").Amount + recipientAfter := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(1), "aatom").Amount + s.Require().Equal(senderBefore.Sub(sdkmath.NewIntFromBigInt(transferAmt)), senderAfter) + s.Require().Equal(recipientBefore.Add(sdkmath.NewIntFromBigInt(transferAmt)), recipientAfter) + }, + func(s *KeeperTestSuite) {}, + }, + { + "pass - evm tx succeeds, post processing is called but fails, the balance is unchanged", + func(s *KeeperTestSuite) { + s.Network.App.GetEVMKeeper().SetHooks( + keeper.NewMultiEvmHooks( + &testHooks{ + postProcessing: func(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error { + return errors.New("post processing failed :(") + }, + }, + ), + ) + }, + func(s *KeeperTestSuite) { + senderBefore := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(0), "aatom").Amount + recipientBefore := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(1), "aatom").Amount + + // Generate a transfer tx message + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + transferAmt := big.NewInt(100) + + tx, err := s.Factory.GenerateSignedEthTx(sender.Priv, types.EvmTxArgs{ + To: &recipient, + Amount: transferAmt, + }) + s.Require().NoError(err) + + ethMsg := tx.GetMsgs()[0].(*types.MsgEthereumTx) + res, err := s.Network.App.GetEVMKeeper().ApplyTransaction(s.Network.GetContext(), ethMsg.AsTransaction()) + s.Require().NoError(err) + s.Require().True(res.Failed()) + + senderAfter := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(0), "aatom").Amount + recipientAfter := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(1), "aatom").Amount + s.Require().Equal(senderBefore, senderAfter) + s.Require().Equal(recipientBefore, recipientAfter) + }, + func(s *KeeperTestSuite) {}, + }, + { + "evm tx fails, post processing is called and persisted, the balance is not changed", + func(s *KeeperTestSuite) { + s.Network.App.GetEVMKeeper().SetHooks( + keeper.NewMultiEvmHooks( + &testHooks{ + postProcessing: func(ctx sdk.Context, sender common.Address, msg core.Message, receipt *ethtypes.Receipt) error { + return s.Network.App.GetMintKeeper().MintCoins( + ctx, sdk.NewCoins(sdk.NewCoin("arandomcoin", sdkmath.NewInt(100))), + ) + }, + }, + ), + ) + }, + func(s *KeeperTestSuite) { + senderBefore := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(0), "aatom").Amount + recipientBefore := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(1), "aatom").Amount + + // Generate a transfer tx message + sender := s.Keyring.GetKey(0) + recipient := s.Keyring.GetAddr(1) + transferAmt := senderBefore.Add(sdkmath.NewInt(100)) // transfer more than the balance + + tx, err := s.Factory.GenerateSignedEthTx(sender.Priv, types.EvmTxArgs{ + To: &recipient, + Amount: transferAmt.BigInt(), + }) + s.Require().NoError(err) + + ethMsg := tx.GetMsgs()[0].(*types.MsgEthereumTx) + res, err := s.Network.App.GetEVMKeeper().ApplyTransaction(s.Network.GetContext(), ethMsg.AsTransaction()) + s.Require().NoError(err) + s.Require().True(res.Failed()) + + senderAfter := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(0), "aatom").Amount + recipientAfter := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Keyring.GetAccAddr(1), "aatom").Amount + s.Require().Equal(senderBefore, senderAfter) + s.Require().Equal(recipientBefore, recipientAfter) + }, + func(s *KeeperTestSuite) { + // check if the mint module has "arandomcoin" in its balance, it was minted in the post processing, proving that the post processing was called + // and that it can persist state even when the tx fails + balance := s.Network.App.GetBankKeeper().GetBalance(s.Network.GetContext(), s.Network.App.GetAccountKeeper().GetModuleAddress("mint"), "arandomcoin") + s.Require().Equal(sdkmath.NewInt(100), balance.Amount) + }, + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.name), func() { + s.SetupTest() + + tc.setup(s) + + // set bounded cosmos block gas limit + ctx := s.Network.GetContext().WithBlockGasMeter(storetypes.NewGasMeter(1e6)) + err := s.Network.App.GetBankKeeper().MintCoins(ctx, "mint", sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18)))) + s.Require().NoError(err) + err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, "mint", "fee_collector", sdk.NewCoins(sdk.NewCoin("aatom", sdkmath.NewInt(3e18)))) + s.Require().NoError(err) + + tc.do(s) + + tc.after(s) + }) + } +} + func (s *KeeperTestSuite) TestApplyMessage() { s.EnableFeemarket = true defer func() { s.EnableFeemarket = false }() diff --git a/tests/integration/x/vm/test_statedb.go b/tests/integration/x/vm/test_statedb.go index fe801ac04..5ac2ac861 100644 --- a/tests/integration/x/vm/test_statedb.go +++ b/tests/integration/x/vm/test_statedb.go @@ -729,7 +729,6 @@ func (s *KeeperTestSuite) TestAddLog() { }, ðtypes.Log{ Address: addr, - TxHash: txHash, Topics: make([]common.Hash, 0), }, func(vm.StateDB) {}, @@ -743,7 +742,6 @@ func (s *KeeperTestSuite) TestAddLog() { }, ðtypes.Log{ Address: addr, - TxHash: txHash3, Topics: make([]common.Hash, 0), }, func(vm.StateDB) {}, @@ -754,7 +752,6 @@ func (s *KeeperTestSuite) TestAddLog() { s.Run(tc.name, func() { s.SetupTest() vmdb := statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewTxConfig( - common.BytesToHash(s.Network.GetContext().HeaderHash()), tc.hash, 0, 0, )) diff --git a/tests/integration/x/vm/utils.go b/tests/integration/x/vm/utils.go index c22b8b1ee..ab5b0b30a 100644 --- a/tests/integration/x/vm/utils.go +++ b/tests/integration/x/vm/utils.go @@ -24,7 +24,7 @@ func (s *KeeperTestSuite) EvmDenom() string { } func (s *KeeperTestSuite) StateDB() *statedb.StateDB { - return statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig(common.BytesToHash(s.Network.GetContext().HeaderHash()))) + return statedb.New(s.Network.GetContext(), s.Network.App.GetEVMKeeper(), statedb.NewEmptyTxConfig()) } // DeployTestContract deploy a test erc20 contract and returns the contract address diff --git a/tests/jsonrpc/scripts/run-compat-test.sh b/tests/jsonrpc/scripts/run-compat-test.sh index 89e4bcf8f..fe11ee334 100755 --- a/tests/jsonrpc/scripts/run-compat-test.sh +++ b/tests/jsonrpc/scripts/run-compat-test.sh @@ -46,4 +46,4 @@ echo "🚀 Running JSON-RPC compatibility tests..." cd "$JSONRPC_DIR" && docker compose up --build --abort-on-container-exit -echo "✅ JSON-RPC compatibility test completed!" \ No newline at end of file +echo "✅ JSON-RPC compatibility test completed!" diff --git a/tests/jsonrpc/simulator/go.mod b/tests/jsonrpc/simulator/go.mod index 93bac6738..120fc812e 100644 --- a/tests/jsonrpc/simulator/go.mod +++ b/tests/jsonrpc/simulator/go.mod @@ -5,10 +5,9 @@ go 1.23.8 require ( github.com/ethereum/go-ethereum v1.15.10 github.com/fatih/color v1.16.0 - github.com/google/go-cmp v0.5.9 + github.com/gorilla/websocket v1.4.2 github.com/status-im/keycard-go v0.2.0 github.com/xuri/excelize/v2 v2.8.1 - gopkg.in/yaml.v2 v2.4.0 ) require ( @@ -24,7 +23,6 @@ require ( github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/gorilla/websocket v1.4.2 // indirect github.com/holiman/uint256 v1.3.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/tests/jsonrpc/simulator/go.sum b/tests/jsonrpc/simulator/go.sum index 6e9fc6183..8bd721ee3 100644 --- a/tests/jsonrpc/simulator/go.sum +++ b/tests/jsonrpc/simulator/go.sum @@ -65,8 +65,6 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -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 v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -197,9 +195,6 @@ golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/tests/jsonrpc/simulator/namespaces/debug.go b/tests/jsonrpc/simulator/namespaces/debug.go index a02cc0a85..88c9ac02e 100644 --- a/tests/jsonrpc/simulator/namespaces/debug.go +++ b/tests/jsonrpc/simulator/namespaces/debug.go @@ -999,7 +999,7 @@ func DebugStartGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { // Call debug_startGoTrace with test parameters filename := "/tmp/go_trace_start.out" - + var result any err := rCtx.Evmd.RPCClient().Call(&result, string(MethodNameDebugStartGoTrace), filename) if err != nil { @@ -1024,7 +1024,7 @@ func DebugStartGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { rCtx.AlreadyTestedRPCs = append(rCtx.AlreadyTestedRPCs, rpcResult) return rpcResult, nil } - + rpcResult := &types.RpcResult{ Method: MethodNameDebugStartGoTrace, Status: types.Ok, @@ -1065,7 +1065,7 @@ func DebugStopGoTrace(rCtx *types.RPCContext) (*types.RpcResult, error) { rCtx.AlreadyTestedRPCs = append(rCtx.AlreadyTestedRPCs, rpcResult) return rpcResult, nil } - + rpcResult := &types.RpcResult{ Method: MethodNameDebugStopGoTrace, Status: types.Ok, diff --git a/tests/jsonrpc/simulator/namespaces/eth.go b/tests/jsonrpc/simulator/namespaces/eth.go index f1922bc4c..803b00510 100644 --- a/tests/jsonrpc/simulator/namespaces/eth.go +++ b/tests/jsonrpc/simulator/namespaces/eth.go @@ -1671,7 +1671,6 @@ func EthEstimateGas(rCtx *types.RPCContext) (*types.RpcResult, error) { func EthFeeHistory(rCtx *types.RPCContext) (*types.RpcResult, error) { var result interface{} err := rCtx.Evmd.RPCClient().Call(&result, string(MethodNameEthFeeHistory), "0x2", "latest", []float64{25.0, 50.0, 75.0}) - if err != nil { if err.Error() == "the method "+string(MethodNameEthFeeHistory)+" does not exist/is not available" || err.Error() == types.ErrorMethodNotFound { @@ -1874,6 +1873,7 @@ func EthSign(rCtx *types.RPCContext) (*types.RpcResult, error) { func EthCreateAccessList(rCtx *types.RPCContext) (*types.RpcResult, error) { var result interface{} callData := map[string]interface{}{ + "from": rCtx.Evmd.Acc.Address.Hex(), "to": rCtx.Evmd.Acc.Address.Hex(), "data": "0x", } @@ -1926,7 +1926,6 @@ func EthGetHeaderByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { var header any err = rCtx.Evmd.RPCClient().Call(&header, string(MethodNameEthGetHeaderByHash), receipt.BlockHash.Hex()) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") { @@ -2004,7 +2003,6 @@ func EthGetHeaderByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { var header any err = rCtx.Evmd.RPCClient().Call(&header, string(MethodNameEthGetHeaderByNumber), blockNumberHex) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") { @@ -2091,7 +2089,6 @@ func EthSimulateV1(rCtx *types.RPCContext) (*types.RpcResult, error) { var result any err := rCtx.Evmd.RPCClient().Call(&result, string(MethodNameEthSimulateV1), simulationReq) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") || @@ -2158,7 +2155,6 @@ func EthPendingTransactions(rCtx *types.RPCContext) (*types.RpcResult, error) { var pendingTxs any err := rCtx.Evmd.RPCClient().Call(&pendingTxs, string(MethodNameEthPendingTransactions)) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") || diff --git a/tests/jsonrpc/simulator/report/report.go b/tests/jsonrpc/simulator/report/report.go index d1f668bc7..20b664b2e 100644 --- a/tests/jsonrpc/simulator/report/report.go +++ b/tests/jsonrpc/simulator/report/report.go @@ -359,7 +359,6 @@ func PrintCategoryMatrix(summary *types.TestSummary) { catSummary.Total) } } - } func PrintSummary(summary *types.TestSummary) { diff --git a/tests/jsonrpc/simulator/runner/testcases.go b/tests/jsonrpc/simulator/runner/testcases.go index f444fd427..db769ae78 100644 --- a/tests/jsonrpc/simulator/runner/testcases.go +++ b/tests/jsonrpc/simulator/runner/testcases.go @@ -68,6 +68,7 @@ func GetTestCases() []types.TestCase { {Name: ns.MethodNameEthGetPendingTransactions, Handler: func(rCtx *types.RPCContext) (*types.RpcResult, error) { return utils.Legacy(rCtx, ns.MethodNameEthGetPendingTransactions, "eth", "Use eth_newPendingTransactionFilter + eth_getFilterChanges instead") }}, + {Name: ns.MethodNameEthCreateAccessList, Handler: ns.EthCreateAccessList}, {Name: ns.MethodNameEthPendingTransactions, Handler: ns.EthPendingTransactions, Description: "Go-ethereum compatible pending transactions method"}, // Execute subcategory {Name: ns.MethodNameEthCall, Handler: ns.EthCall}, @@ -88,7 +89,6 @@ func GetTestCases() []types.TestCase { {Name: ns.MethodNameEthFeeHistory, Handler: ns.EthFeeHistory}, {Name: ns.MethodNameEthGetProof, Handler: ns.EthGetProof}, {Name: ns.MethodNameEthProtocolVersion, Handler: nil, SkipReason: "Protocol version deprecated"}, - {Name: ns.MethodNameEthCreateAccessList, Handler: nil, SkipReason: "Access list creation not implemented"}, // Standard methods that should be implemented {Name: ns.MethodNameEthSendTransaction, Handler: ns.EthSendTransaction}, {Name: ns.MethodNameEthSign, Handler: ns.EthSign}, diff --git a/tests/jsonrpc/simulator/types/context.go b/tests/jsonrpc/simulator/types/context.go index 79d0c2203..3a65245a2 100644 --- a/tests/jsonrpc/simulator/types/context.go +++ b/tests/jsonrpc/simulator/types/context.go @@ -77,7 +77,6 @@ type RPCContext struct { // Dual API testing fields EnableComparison bool // Enable dual API comparison ComparisonResults []*ComparisonResult // Store comparison results - } func NewRPCContext(conf *config.Config) (*RPCContext, error) { @@ -134,7 +133,6 @@ func (rCtx *RPCContext) AlreadyTested(rpc RpcName) *RpcResult { } } return nil - } // CompareRPCCall performs a dual API call and compares response structures diff --git a/tests/jsonrpc/simulator/utils/test_helpers.go b/tests/jsonrpc/simulator/utils/test_helpers.go index d584b116d..ea0bda5de 100644 --- a/tests/jsonrpc/simulator/utils/test_helpers.go +++ b/tests/jsonrpc/simulator/utils/test_helpers.go @@ -390,7 +390,6 @@ func Legacy(rCtx *types.RPCContext, methodName types.RpcName, category string, r // First test if the API is actually implemented var result interface{} err := rCtx.Evmd.RPCClient().Call(&result, string(methodName)) - if err != nil { // Check if it's a "method not found" error (API not implemented) if err.Error() == "the method "+string(methodName)+" does not exist/is not available" || diff --git a/tests/solidity/init-node.sh b/tests/solidity/init-node.sh deleted file mode 100755 index 249b6a532..000000000 --- a/tests/solidity/init-node.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash - -set -ex - -# TODO: remove this script and just use the local node script for it, add flag to start node in given directory - -CHAINID="${CHAIN_ID:-cosmos_262144-1}" -MONIKER="localtestnet" -KEYRING="test" # remember to change to other types of keyring like 'file' in-case exposing to outside world, otherwise your balance will be wiped quickly. The keyring test does not require private key to steal tokens from you -KEYALGO="eth_secp256k1" #gitleaks:allow -LOGLEVEL="info" -# to trace evm -#TRACE="--trace" -TRACE="" -PRUNING="default" -#PRUNING="custom" - -CHAINDIR="$HOME/.tmp-evmd-solidity-tests" # TODO: make configurable like chain id -GENESIS="$CHAINDIR/config/genesis.json" -TMP_GENESIS="$CHAINDIR/config/tmp_genesis.json" -APP_TOML="$CHAINDIR/config/app.toml" -CONFIG_TOML="$CHAINDIR/config/config.toml" - -# make sure to reset chain directory before test -rm -rf "$CHAINDIR" - -# validate dependencies are installed -command -v jq >/dev/null 2>&1 || { - echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/" - exit 1 -} - -# used to exit on first error (any non-zero exit code) -set -e - -# feemarket params basefee -BASEFEE=1000000000 - -# Set client config -evmd config set client chain-id "$CHAINID" --home "$CHAINDIR" -evmd config set client keyring-backend "$KEYRING" --home "$CHAINDIR" - -# myKey address 0x7cb61d4117ae31a12e393a1cfa3bac666481d02e -VAL_KEY="mykey" -VAL_MNEMONIC="gesture inject test cycle original hollow east ridge hen combine junk child bacon zero hope comfort vacuum milk pitch cage oppose unhappy lunar seat" - -# user1 address 0xc6fe5d33615a1c52c08018c47e8bc53646a0e101 -USER1_KEY="user1" -USER1_MNEMONIC="copper push brief egg scan entry inform record adjust fossil boss egg comic alien upon aspect dry avoid interest fury window hint race symptom" - -# user2 address 0x963ebdf2e1f8db8707d05fc75bfeffba1b5bac17 -USER2_KEY="user2" -USER2_MNEMONIC="maximum display century economy unlock van census kite error heart snow filter midnight usage egg venture cash kick motor survey drastic edge muffin visual" - -# user3 address 0x40a0cb1C63e026A81B55EE1308586E21eec1eFa9 -USER3_KEY="user3" -USER3_MNEMONIC="will wear settle write dance topic tape sea glory hotel oppose rebel client problem era video gossip glide during yard balance cancel file rose" - -# user4 address 0x498B5AeC5D439b733dC2F58AB489783A23FB26dA -USER4_KEY="user4" -USER4_MNEMONIC="doll midnight silk carpet brush boring pluck office gown inquiry duck chief aim exit gain never tennis crime fragile ship cloud surface exotic patch" - -# Import keys from mnemonics -echo "$VAL_MNEMONIC" | evmd keys add "$VAL_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" -echo "$USER1_MNEMONIC" | evmd keys add "$USER1_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" -echo "$USER2_MNEMONIC" | evmd keys add "$USER2_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" -echo "$USER3_MNEMONIC" | evmd keys add "$USER3_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" -echo "$USER4_MNEMONIC" | evmd keys add "$USER4_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" - -# Set moniker and chain-id for Cosmos EVM (Moniker can be anything, chain-id must be an integer) -evmd init "$MONIKER" --chain-id "$CHAINID" --home "$CHAINDIR" - -# Change parameter token denominations to atest -jq '.app_state["staking"]["params"]["bond_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" -jq '.app_state["mint"]["params"]["mint_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Enable precompiles in EVM params -jq '.app_state["evm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Change proposal periods to pass within a reasonable time for local testing -sed -i.bak 's/"max_deposit_period": "172800s"/"max_deposit_period": "30s"/g' "$GENESIS" -sed -i.bak 's/"voting_period": "172800s"/"voting_period": "30s"/g' "$GENESIS" -sed -i.bak 's/"expedited_voting_period": "86400s"/"expedited_voting_period": "15s"/g' "$GENESIS" - -# Set gas limit in genesis -jq '.consensus_params.block.max_gas="10000000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# Set base fee in genesis -jq '.app_state["feemarket"]["params"]["base_fee"]="'${BASEFEE}'"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - -# disable produce empty block -sed -i.bak 's/create_empty_blocks = true/create_empty_blocks = false/g' "$CONFIG_TOML" - -# Allocate genesis accounts (cosmos formatted addresses) -evmd genesis add-genesis-account "$(evmd keys show "$VAL_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 100000000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" -evmd genesis add-genesis-account "$(evmd keys show "$USER1_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" -evmd genesis add-genesis-account "$(evmd keys show "$USER2_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" -evmd genesis add-genesis-account "$(evmd keys show "$USER3_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" -evmd genesis add-genesis-account "$(evmd keys show "$USER4_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" - -# set custom pruning settings -if [ "$PRUNING" = "custom" ]; then - sed -i.bak 's/pruning = "default"/pruning = "custom"/g' "$APP_TOML" - sed -i.bak 's/pruning-keep-recent = "0"/pruning-keep-recent = "2"/g' "$APP_TOML" - sed -i.bak 's/pruning-interval = "0"/pruning-interval = "10"/g' "$APP_TOML" -fi - -# make sure the localhost IP is 0.0.0.0 -sed -i.bak 's/localhost/0.0.0.0/g' "$CONFIG_TOML" -sed -i.bak 's/127.0.0.1/0.0.0.0/g' "$APP_TOML" - -# use timeout_commit 1s to make test faster -sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "100ms"/g' "$CONFIG_TOML" - -# Sign genesis transaction -evmd genesis gentx "$VAL_KEY" 1000000000000000000000atest --gas-prices ${BASEFEE}atest --keyring-backend "$KEYRING" --chain-id "$CHAINID" --home "$CHAINDIR" -## In case you want to create multiple validators at genesis -## 1. Back to `evmd keys add` step, init more keys -## 2. Back to `evmd add-genesis-account` step, add balance for those -## 3. Clone this ~/.evmd home directory into some others, let's say `~/.clonedosd` -## 4. Run `gentx` in each of those folders -## 5. Copy the `gentx-*` folders under `~/.clonedosd/config/gentx/` folders into the original `~/.evmd/config/gentx` - -# Enable the APIs for the tests to be successful -sed -i.bak 's/enable = false/enable = true/g' "$APP_TOML" - -# Don't enable memiavl by default -grep -q -F '[memiavl]' "$APP_TOML" && sed -i.bak '/\[memiavl\]/,/^\[/ s/enable = true/enable = false/' "$APP_TOML" - -# Collect genesis tx -evmd genesis collect-gentxs --home "$CHAINDIR" - -# Run this to ensure everything worked and that the genesis file is setup correctly -evmd genesis validate-genesis --home "$CHAINDIR" - -# Start the node -evmd start "$TRACE" \ - --log_level $LOGLEVEL \ - --minimum-gas-prices=0.0001utest \ - --json-rpc.api eth,txpool,personal,net,debug,web3 \ - --chain-id "$CHAINID" \ - --home "$CHAINDIR" diff --git a/tests/solidity/suites/precompiles/test/erc20factory.js b/tests/solidity/suites/precompiles/test/erc20factory.js new file mode 100644 index 000000000..eac7d3bb1 --- /dev/null +++ b/tests/solidity/suites/precompiles/test/erc20factory.js @@ -0,0 +1,60 @@ +const { expect } = require('chai') +const hre = require('hardhat') + +const abi = [ + "function create(bytes32 salt, string memory name, string memory symbol, uint8 decimals, address minter, uint256 premintedSupply) external returns (address)", + "function calculateAddress(bytes32 salt) external view returns (address)", + "event Create(address indexed tokenAddress, bytes32 salt, string name, string symbol, uint8 decimals, address minter, uint256 premintedSupply)" +] + +describe('ERC20Factory', function () { + + it('should calculate the correct address', async function () { + const salt = '0x4f5b6f778b28c4d67a9c12345678901234567890123456789012345678901234' + const erc20Factory = await hre.ethers.getContractAt('IERC20Factory', '0x0000000000000000000000000000000000000900') + console.log("erc20Factory contract loaded") + const expectedAddress = await erc20Factory.calculateAddress(salt) + console.log("erc20factory calculateAddress") + expect(expectedAddress).to.equal('0x8C9521848ee0d03BF47390F98c6dc968DA0b2915') + }) + + it('should create a new ERC20 token', async function () { + const salt = '0x4f5b6f778b28c4d67a9c12345678901234567890123456789012345678901234' + const name = 'Test' + const symbol = 'TEST' + const decimals = 18 + const premintedSupply = hre.ethers.parseEther("1000000") // 1M tokens + const [signer] = await hre.ethers.getSigners() + const minter = signer.address + + // Calculate the expected token address before deployment + const erc20Factory = await hre.ethers.getContractAt('IERC20Factory', '0x0000000000000000000000000000000000000900') + + const tokenAddress = await erc20Factory.calculateAddress(salt) + const tx = await erc20Factory.connect(signer).create(salt, name, symbol, decimals, minter, premintedSupply) + + // Get the token address from the transaction receipt + const receipt = await tx.wait() + expect(receipt.status).to.equal(1) // Check transaction was successful + + // Create a contract instance with the full ABI including events for event filtering + const erc20FactoryWithEvents = new hre.ethers.Contract('0x0000000000000000000000000000000000000900', abi, signer) + + // Get the Create event from the transaction receipt + const createEvents = await erc20FactoryWithEvents.queryFilter(erc20FactoryWithEvents.filters.Create(), receipt.blockNumber, receipt.blockNumber) + expect(createEvents.length).to.equal(1) + expect(createEvents[0].args.tokenAddress).to.equal(tokenAddress) + expect(createEvents[0].args.salt).to.equal(salt) + expect(createEvents[0].args.name).to.equal(name) + expect(createEvents[0].args.symbol).to.equal(symbol) + expect(createEvents[0].args.decimals).to.equal(decimals) + expect(createEvents[0].args.minter).to.equal(minter) + expect(createEvents[0].args.premintedSupply).to.equal(premintedSupply) + + // Get the token contract instance + const erc20Token = await hre.ethers.getContractAt('contracts/cosmos/erc20/IERC20.sol:IERC20', tokenAddress) + + // Verify token details through IERC20 queries + expect(await erc20Token.totalSupply()).to.equal(premintedSupply) + }) +}) \ No newline at end of file diff --git a/tests/solidity/suites/revert_cases/contracts/RevertTestContract.sol b/tests/solidity/suites/revert_cases/contracts/RevertTestContract.sol new file mode 100644 index 000000000..d20f80c3e --- /dev/null +++ b/tests/solidity/suites/revert_cases/contracts/RevertTestContract.sol @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./cosmos/staking/StakingI.sol"; +import "./cosmos/distribution/DistributionI.sol"; +import "./cosmos/bank/IBank.sol"; +import "./cosmos/common/Types.sol"; + +/** + * @title RevertTestContract + * @dev Contract for testing Cosmos precompile revert scenarios and error message handling + * Focuses specifically on precompile calls and interactions with Cosmos SDK modules + */ +contract RevertTestContract { + uint256 public counter = 0; + + // Events to track what operations are performed + event PrecompileCallMade(string precompileName, bool success); + event OutOfGasSimulated(uint256 gasLeft); + + constructor() payable {} + + // ============ DIRECT PRECOMPILE CALL REVERTS ============ + + /** + * @dev Direct staking precompile call that will revert + */ + function directStakingRevert(string calldata invalidValidator) external { + counter++; + emit PrecompileCallMade("staking", false); + // This should revert with invalid validator address + STAKING_CONTRACT.delegate(address(this), invalidValidator, 1); + } + + /** + * @dev Direct distribution precompile call that will revert + */ + function directDistributionRevert(string calldata invalidValidator) external { + counter++; + emit PrecompileCallMade("distribution", false); + // This should revert with invalid validator address + DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(address(this), invalidValidator); + } + + /** + * @dev Direct bank precompile call that will revert + */ + function directBankRevert() external pure { + revert("intended revert"); + } + + // ============ PRECOMPILE CALL VIA CONTRACT REVERTS ============ + + /** + * @dev Precompile call via contract that reverts + */ + function precompileViaContractRevert(string calldata invalidValidator) external { + counter++; + try this.internalStakingCall(invalidValidator) { + // Should not reach here + } catch (bytes memory reason) { + // Re-throw the error to maintain the revert + assembly { + revert(add(reason, 0x20), mload(reason)) + } + } + } + + /** + * @dev Internal function for precompile call via contract + */ + function internalStakingCall(string calldata validatorAddress) external { + require(msg.sender == address(this), "Only self can call"); + emit PrecompileCallMade("staking_internal", false); + STAKING_CONTRACT.delegate(address(this), validatorAddress, 1); + } + + /** + * @dev Complex scenario: multiple precompile calls with revert + */ + function multiplePrecompileCallsWithRevert(string calldata validatorAddress) external { + counter++; + + // First, make a successful call + try IBANK_CONTRACT.balances(address(this)) returns (Balance[] memory) { + emit PrecompileCallMade("bank", true); + } catch { + emit PrecompileCallMade("bank", false); + } + + // Then make a call that will revert + emit PrecompileCallMade("staking_multi", false); + STAKING_CONTRACT.delegate(address(this), validatorAddress, 1); + } + + // ============ PRECOMPILE OUT OF GAS ERROR CASES ============ + + /** + * @dev Direct precompile call that runs out of gas + */ + function directStakingOutOfGas(string calldata validatorAddress) external { + counter++; + emit OutOfGasSimulated(gasleft()); + + // First consume most gas + for (uint256 i = 0; i < 1000000; i++) { + counter++; + } + + // Then try precompile call with remaining gas + STAKING_CONTRACT.delegate(address(this), validatorAddress, 1); + } + + /** + * @dev Precompile call via contract that runs out of gas + */ + function precompileViaContractOutOfGas(string calldata validatorAddress) external { + counter++; + emit OutOfGasSimulated(gasleft()); + + // Consume most gas first + for (uint256 i = 0; i < 1000000; i++) { + counter++; + } + + // Then try internal precompile call + this.internalStakingCall(validatorAddress); + } + + /** + * @dev Wrapper precompile call that runs out of gas + */ + function wrappedPrecompileOutOfGas(string calldata validatorAddress) external { + counter++; + emit OutOfGasSimulated(gasleft()); + + // Consume most gas in expensive operations + for (uint256 i = 0; i < 500000; i++) { + keccak256(abi.encode(i, block.timestamp, msg.sender)); + counter++; + } + + // Then try multiple precompile calls + STAKING_CONTRACT.delegate(address(this), validatorAddress, 1); + DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(address(this), validatorAddress); + } + + // ============ UTILITY FUNCTIONS ============ + + /** + * @dev Get current counter value + */ + function getCounter() external view returns (uint256) { + return counter; + } + + /** + * @dev Reset counter (for testing) + */ + function resetCounter() external { + counter = 0; + } + + /** + * @dev Fund contract with native tokens + */ + receive() external payable {} + + /** + * @dev Withdraw funds (for testing) + */ + function withdraw() external { + payable(msg.sender).transfer(address(this).balance); + } +} + +/** + * @title PrecompileWrapper + * @dev Helper contract for testing precompile calls via external contracts + */ +contract PrecompileWrapper { + event WrapperCall(string operation, bool success); + + constructor() payable {} + + /** + * @dev Wrapper function that calls staking precompile and reverts + */ + function wrappedStakingCall(string calldata validatorAddress, uint256 amount) external { + emit WrapperCall("staking", false); + STAKING_CONTRACT.delegate(address(this), validatorAddress, amount); + revert("Wrapper intentional revert"); + } + + /** + * @dev Wrapper function that calls distribution precompile and reverts + */ + function wrappedDistributionCall(string calldata validatorAddress) external { + emit WrapperCall("distribution", false); + DISTRIBUTION_CONTRACT.withdrawDelegatorRewards(address(this), validatorAddress); + revert("Wrapper intentional revert"); + } + + /** + * @dev Wrapper function that runs out of gas + */ + function wrappedOutOfGasCall(string calldata validatorAddress) external { + // Consume all gas + for (uint256 i = 0; i < 1000000; i++) { + // Gas consuming operation + keccak256(abi.encode(i)); + } + + STAKING_CONTRACT.delegate(address(this), validatorAddress, 1); + } + + /** + * @dev Fund wrapper contract + */ + receive() external payable {} +} diff --git a/tests/solidity/suites/revert_cases/contracts/StandardRevertTestContract.sol b/tests/solidity/suites/revert_cases/contracts/StandardRevertTestContract.sol new file mode 100644 index 000000000..5ee137ecd --- /dev/null +++ b/tests/solidity/suites/revert_cases/contracts/StandardRevertTestContract.sol @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title StandardRevertTestContract + * @dev Contract for testing standard Ethereum revert scenarios and error message handling + * Compatible with any Ethereum node (Geth, etc.) - no custom precompiles required + */ +contract StandardRevertTestContract { + uint256 public counter = 0; + + // Events to track what operations are performed + event StandardRevert(string reason); + event OutOfGasSimulated(uint256 gasLeft); + event CounterIncremented(uint256 newValue); + + constructor() payable {} + + // ============ STANDARD CONTRACT REVERT CASES ============ + + /** + * @dev Simple revert with custom message + */ + function standardRevert(string calldata reason) external { + counter++; + emit StandardRevert(reason); + revert(reason); + } + + /** + * @dev Revert with require statement + */ + function requireRevert(uint256 value, uint256 threshold) external { + counter++; + require(value < threshold, "Value exceeds threshold"); + emit CounterIncremented(counter); + } + + /** + * @dev Assert revert (should generate Panic error) + */ + function assertRevert() external { + counter++; + assert(false); + } + + /** + * @dev Division by zero (should generate Panic error) + */ + function divisionByZero() external pure returns (uint256) { + uint256 zero = 0; + return 1 / zero; + } + + /** + * @dev Array out of bounds (should generate Panic error) + */ + function arrayOutOfBounds() external pure returns (uint256) { + uint256[] memory arr = new uint256[](2); + return arr[5]; // This will cause an out of bounds error + } + + /** + * @dev Division by zero in transaction context (should generate Panic error) + */ + function divisionByZeroTx() external returns (uint256) { + counter++; // State change to make it a transaction + uint256 zero = 0; + return 1 / zero; + } + + /** + * @dev Array out of bounds in transaction context (should generate Panic error) + */ + function arrayOutOfBoundsTx() external returns (uint256) { + counter++; // State change to make it a transaction + uint256[] memory arr = new uint256[](2); + return arr[5]; // This will cause an out of bounds error + } + + /** + * @dev Overflow error (should generate Panic error in older Solidity) + */ + function overflowError() external pure returns (uint256) { + unchecked { + uint256 max = type(uint256).max; + return max + 1; // This might overflow depending on Solidity version + } + } + + // ============ OUT OF GAS ERROR CASES ============ + + /** + * @dev Standard contract call that runs out of gas + */ + function standardOutOfGas() external { + counter++; + emit OutOfGasSimulated(gasleft()); + + // Consume all remaining gas + while (gasleft() > 1000) { + // Consume gas in a loop + counter++; + } + } + + /** + * @dev Expensive computation that can run out of gas + */ + function expensiveComputation(uint256 iterations) external { + counter++; + emit OutOfGasSimulated(gasleft()); + + // Perform expensive operations + for (uint256 i = 0; i < iterations; i++) { + // Hash operations are gas-expensive + keccak256(abi.encode(i, block.timestamp, msg.sender)); + counter++; + } + } + + /** + * @dev Storage operations that can run out of gas + */ + function expensiveStorage(uint256 iterations) external { + counter++; + emit OutOfGasSimulated(gasleft()); + + // Storage operations are very gas-expensive + for (uint256 i = 0; i < iterations; i++) { + assembly { + sstore(add(counter.slot, i), i) + } + } + } + + // ============ COMPLEX REVERT SCENARIOS ============ + + /** + * @dev Multiple function calls with revert + */ + function multipleCallsWithRevert() external { + counter++; + + // First, do some successful operations + this.incrementCounter(); + + // Then revert + revert("Multiple calls revert"); + } + + /** + * @dev Try-catch with revert + */ + function tryCatchRevert(bool shouldRevert) external { + counter++; + + if (shouldRevert) { + try this.internalRevert() { + // Should not reach here + } catch (bytes memory reason) { + // Re-throw the error to maintain the revert + assembly { + revert(add(reason, 0x20), mload(reason)) + } + } + } else { + // Successful path + emit CounterIncremented(counter); + } + } + + /** + * @dev Internal function that always reverts + */ + function internalRevert() external pure { + revert("Internal function revert"); + } + + // ============ UTILITY FUNCTIONS ============ + + /** + * @dev Simple function that increments counter + */ + function incrementCounter() external { + counter++; + emit CounterIncremented(counter); + } + + /** + * @dev Get current counter value + */ + function getCounter() external view returns (uint256) { + return counter; + } + + /** + * @dev Reset counter (for testing) + */ + function resetCounter() external { + counter = 0; + } + + /** + * @dev Fund contract with native tokens + */ + receive() external payable {} + + /** + * @dev Withdraw funds (for testing) + */ + function withdraw() external { + payable(msg.sender).transfer(address(this).balance); + } + + /** + * @dev Get contract balance + */ + function getBalance() external view returns (uint256) { + return address(this).balance; + } +} + +/** + * @title SimpleWrapper + * @dev Helper contract for testing reverts via external contracts + */ +contract SimpleWrapper { + event WrapperCall(string operation, bool success); + + constructor() payable {} + + /** + * @dev Wrapper function that calls standard revert + */ + function wrappedStandardCall(StandardRevertTestContract target, string calldata reason) external { + emit WrapperCall("standard_revert", false); + target.standardRevert(reason); + } + + /** + * @dev Wrapper function that runs out of gas + */ + function wrappedOutOfGasCall(StandardRevertTestContract target) external { + emit WrapperCall("out_of_gas", false); + + // Consume most gas first + for (uint256 i = 0; i < 100000; i++) { + // Gas consuming operation + keccak256(abi.encode(i)); + } + + // Then try the expensive call + target.expensiveComputation(10000); + } + + /** + * @dev Fund wrapper contract + */ + receive() external payable {} +} \ No newline at end of file diff --git a/tests/solidity/suites/revert_cases/hardhat.config.js b/tests/solidity/suites/revert_cases/hardhat.config.js new file mode 100644 index 000000000..019d79017 --- /dev/null +++ b/tests/solidity/suites/revert_cases/hardhat.config.js @@ -0,0 +1,27 @@ +require("@nomicfoundation/hardhat-toolbox"); + +/** @type import('hardhat/config').HardhatUserConfig */ +module.exports = { + solidity: { + compilers: [ + { + version: "0.8.18", + }, + // This version is required to compile the werc9 contract. + { + version: "0.4.22", + }, + ], + }, + networks: { + cosmos: { + url: "http://127.0.0.1:8545", + chainId: 262144, + accounts: [ + "0x88CBEAD91AEE890D27BF06E003ADE3D4E952427E88F88D31D61D3EF5E5D54305", + "0x3B7955D25189C99A7468192FCBC6429205C158834053EBE3F78F4512AB432DB9", + "0xe9b1d63e8acd7fe676acb43afb390d4b0202dab61abec9cf2a561e4becb147de", + ], + }, + }, +}; diff --git a/tests/solidity/suites/revert_cases/package.json b/tests/solidity/suites/revert_cases/package.json new file mode 100644 index 000000000..7788ed08a --- /dev/null +++ b/tests/solidity/suites/revert_cases/package.json @@ -0,0 +1,35 @@ +{ + "name": "revert_cases", + "version": "1.0.0", + "author": "Evmos team", + "license": "GPL-3.0-or-later", + "scripts": { + "get-contracts": "mkdir -p ./contracts/cosmos && rsync -avm --include='*/' --exclude='**/ERC20Minter_OpenZeppelinV5.sol' --exclude='**/WEVMOS.sol' --exclude='**/ERC20NoMetadata.sol' --include='*.sol' --exclude='*' ../../../../precompiles/ ./contracts/cosmos/", + "clean-contracts": "rm -rf ./contracts/cosmos/*", + "test-ganache": "yarn hardhat test", + "test-cosmos": "yarn get-contracts && yarn hardhat test --network cosmos && yarn clean-contracts" + }, + "devDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "^2.0.2", + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-network-helpers": "^1.0.8", + "@nomicfoundation/hardhat-toolbox": "^3.0.0", + "@nomicfoundation/hardhat-verify": "^1.1.1", + "@openzeppelin/hardhat-upgrades": "^2.0.2", + "@openzeppelin/contracts": "^4.9.6", + "@typechain/ethers-v6": "^0.4.3", + "@typechain/hardhat": "^8.0.3", + "@types/chai": "^4.3.5", + "@types/mocha": "^10.0.1", + "chai": "^4.3.7", + "hardhat": "^2.20.0", + "hardhat-gas-reporter": "^1.0.9", + "solidity-coverage": "^0.8.4", + "ts-node": "^10.9.1", + "typechain": "^8.3.1", + "typescript": "^5.1.6" + }, + "dependencies": { + "ethers": "^6.7.0" + } +} diff --git a/tests/solidity/suites/revert_cases/test/common.js b/tests/solidity/suites/revert_cases/test/common.js new file mode 100644 index 000000000..5291c324f --- /dev/null +++ b/tests/solidity/suites/revert_cases/test/common.js @@ -0,0 +1,41 @@ +// Common constants and helper utilities for precompile tests + +const STAKING_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000800' +const BECH32_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000400' +const DISTRIBUTION_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000801' +const BANK_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000804' +const GOV_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000805' +const SLASHING_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000806' +const P256_PRECOMPILE_ADDRESS = '0x0000000000000000000000000000000000000100' +const WERC20_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' + +// Default gas limits used across tests +const DEFAULT_GAS_LIMIT = 1_000_000 +const LARGE_GAS_LIMIT = 10_000_000 +const LOW_GAS_LIMIT=50_000 + +const PANIC_ASSERT_0x01 = "Panic(1)" +const PANIC_DIVISION_BY_ZERO_0x12 = "Panic(18)" +const PANIC_ARRAY_OUT_OF_BOUND_0x32 = "Panic(50)" + +module.exports = { + // Precompile Addresses + STAKING_PRECOMPILE_ADDRESS, + BECH32_PRECOMPILE_ADDRESS, + DISTRIBUTION_PRECOMPILE_ADDRESS, + BANK_PRECOMPILE_ADDRESS, + GOV_PRECOMPILE_ADDRESS, + SLASHING_PRECOMPILE_ADDRESS, + P256_PRECOMPILE_ADDRESS, + WERC20_ADDRESS, + + // Gas limits + DEFAULT_GAS_LIMIT, + LARGE_GAS_LIMIT, + LOW_GAS_LIMIT, + + // Panics + PANIC_ASSERT_0x01, + PANIC_DIVISION_BY_ZERO_0x12, + PANIC_ARRAY_OUT_OF_BOUND_0x32 +} \ No newline at end of file diff --git a/tests/solidity/suites/revert_cases/test/precompile_revert_cases.js b/tests/solidity/suites/revert_cases/test/precompile_revert_cases.js new file mode 100644 index 000000000..ce397d0ff --- /dev/null +++ b/tests/solidity/suites/revert_cases/test/precompile_revert_cases.js @@ -0,0 +1,239 @@ +const { expect } = require('chai'); +const hre = require('hardhat'); +const { LARGE_GAS_LIMIT, LOW_GAS_LIMIT } = require('./common'); +const { + decodeRevertReason, + analyzeFailedTransaction, + verifyTransactionRevert, + verifyOutOfGasError +} = require('./test_helper') + +describe('Precompile Revert Cases E2E Tests', function () { + let revertTestContract, precompileWrapper; + let validValidatorAddress, invalidValidatorAddress; + let analysis, decodedReason; + + before(async function () { + [signer] = await hre.ethers.getSigners(); + + // Deploy RevertTestContract + const RevertTestContractFactory = await hre.ethers.getContractFactory('RevertTestContract'); + revertTestContract = await RevertTestContractFactory.deploy({ + value: hre.ethers.parseEther('1.0'), // Fund with 1 ETH + gasLimit: LARGE_GAS_LIMIT + }); + await revertTestContract.waitForDeployment(); + + // Deploy PrecompileWrapper + const PrecompileWrapperFactory = await hre.ethers.getContractFactory('PrecompileWrapper'); + precompileWrapper = await PrecompileWrapperFactory.deploy({ + value: hre.ethers.parseEther('1.0'), // Fund with 1 ETH + gasLimit: LARGE_GAS_LIMIT + }); + await precompileWrapper.waitForDeployment(); + + // Use a known validator for valid cases and invalid one for error cases + validValidatorAddress = 'cosmosvaloper10jmp6sgh4cc6zt3e8gw05wavvejgr5pw4xyrql'; + invalidValidatorAddress = 'cosmosvaloper10jmp6sgh4cc6zt3e8gw05wavvejgr5pinvalid'; + + console.log('RevertTestContract deployed at:', await revertTestContract.getAddress()); + console.log('PrecompileWrapper deployed at:', await precompileWrapper.getAddress()); + + analysis = null; + decodedReason = null; + }); + + describe('Direct Precompile Call Reverts', function () { + it('should handle direct staking precompile revert', async function () { + try { + const tx = await revertTestContract.directStakingRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + + it('should handle direct distribution precompile revert', async function () { + try { + const tx = await revertTestContract.directDistributionRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + + it('should handle direct bank precompile revert', async function () { + // directBankRevert is a view function, so it should revert immediately + try { + await revertTestContract.directBankRevert(); + expect.fail('Call should have reverted'); + } catch (error) { + decodedReason = decodeRevertReason(error.data) + } + expect(decodedReason).contains("intended revert") + }); + + it('should capture precompile revert reason through transaction receipt', async function () { + try { + const tx = await revertTestContract.directStakingRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + }); + + describe('Precompile Call Via Contract Reverts', function () { + it('should handle precompile call via contract revert', async function () { + try { + const tx = await revertTestContract.precompileViaContractRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + + it('should handle multiple precompile calls with revert', async function () { + try { + const tx = await revertTestContract.multiplePrecompileCallsWithRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + + it('should handle wrapper contract precompile revert', async function () { + try { + const tx = await precompileWrapper.wrappedStakingCall(invalidValidatorAddress, 1, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + + it('should capture wrapper revert reason via transaction receipt', async function () { + try { + const tx = await precompileWrapper.wrappedDistributionCall(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyTransactionRevert(analysis, "invalid validator address") + }); + }); + + describe('Precompile OutOfGas Error Cases', function () { + it('should handle direct precompile OutOfGas', async function () { + // Use a very low gas limit to trigger OutOfGas on precompile calls + try { + const tx = await revertTestContract.directStakingOutOfGas(validValidatorAddress, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyOutOfGasError(analysis) + }); + + it('should handle precompile via contract OutOfGas', async function () { + try { + const tx = await revertTestContract.precompileViaContractOutOfGas(validValidatorAddress, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyOutOfGasError(analysis) + }); + + it('should handle wrapper precompile OutOfGas', async function () { + try { + const tx = await precompileWrapper.wrappedOutOfGasCall(validValidatorAddress, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash) + } + verifyOutOfGasError(analysis) + }); + + it('should analyze precompile OutOfGas error through transaction receipt', async function () { + try { + const tx = await revertTestContract.directStakingOutOfGas(validValidatorAddress, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyOutOfGasError(analysis) + }); + }); + + describe('Comprehensive Precompile Error Analysis', function () { + it('should properly decode various precompile error types from transaction receipts', async function () { + const testCases = [ + { + name: 'Staking Precompile Revert', + call: () => revertTestContract.directStakingRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }), + expectedReason: "invalid validator address" + }, + { + name: 'Distribution Precompile Revert', + call: () => revertTestContract.directDistributionRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }), + expectedReason: "invalid validator address" + } + ]; + + for (const testCase of testCases) { + try { + const tx = await testCase.call(); + await tx.wait() + expect.fail(`${testCase.name} should have reverted`); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, testCase.expectedReason) + } + }); + + it('should verify precompile error data is properly hex-encoded in receipts', async function () { + try { + const tx = await revertTestContract.directStakingRevert(invalidValidatorAddress, { gasLimit: LARGE_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + if (error.receipt) { + // Simulate the call to get error data + try { + const contractAddress = await revertTestContract.getAddress(); + await hre.ethers.provider.call({ + to: contractAddress, + data: revertTestContract.interface.encodeFunctionData('directStakingRevert', [invalidValidatorAddress]), + gasLimit: LARGE_GAS_LIMIT + }); + } catch (callError) { + expect(callError.data).to.match(/^0x/); // Should be hex-encoded + console.log('Precompile error data (hex):', callError.data); + + const decoded = decodeRevertReason(callError.data); + expect(decoded).to.include("invalid validator address"); + console.log('Decoded precompile reason:', decoded); + } + } + } + }); + }); +}); \ No newline at end of file diff --git a/tests/solidity/suites/revert_cases/test/standard_revert_cases.js b/tests/solidity/suites/revert_cases/test/standard_revert_cases.js new file mode 100644 index 000000000..87e1e608f --- /dev/null +++ b/tests/solidity/suites/revert_cases/test/standard_revert_cases.js @@ -0,0 +1,374 @@ +const { expect } = require('chai'); +const hre = require('hardhat'); +const { + DEFAULT_GAS_LIMIT, + LARGE_GAS_LIMIT, + LOW_GAS_LIMIT, + PANIC_ASSERT_0x01, + PANIC_DIVISION_BY_ZERO_0x12, + PANIC_ARRAY_OUT_OF_BOUND_0x32 +} = require('./common'); +const { + decodeRevertReason, + analyzeFailedTransaction, + verifyTransactionRevert, + verifyOutOfGasError +} = require('./test_helper') + + +describe('Standard Revert Cases E2E Tests', function () { + let standardRevertTestContract, simpleWrapper, signer; + let analysis, decodedReason; + + before(async function () { + [signer] = await hre.ethers.getSigners(); + + // Deploy StandardRevertTestContract + const StandardRevertTestContractFactory = await hre.ethers.getContractFactory('StandardRevertTestContract'); + standardRevertTestContract = await StandardRevertTestContractFactory.deploy({ + value: hre.ethers.parseEther('1.0'), // Fund with 1 ETH + gasLimit: LARGE_GAS_LIMIT + }); + await standardRevertTestContract.waitForDeployment(); + + // Deploy SimpleWrapper + const SimpleWrapperFactory = await hre.ethers.getContractFactory('SimpleWrapper'); + simpleWrapper = await SimpleWrapperFactory.deploy({ + value: hre.ethers.parseEther('1.0'), // Fund with 1 ETH + gasLimit: LARGE_GAS_LIMIT + }); + await simpleWrapper.waitForDeployment(); + + // Verify successful deployment + const contractAddress = await standardRevertTestContract.getAddress(); + const wrapperAddress = await simpleWrapper.getAddress(); + console.log('StandardRevertTestContract deployed at:', contractAddress); + console.log('SimpleWrapper deployed at:', wrapperAddress); + + analysis = null; + decodedReason = null; + }); + + describe('Standard Contract Call Reverts', function () { + it('should handle standard revert with custom message', async function () { + const customMessage = "Custom revert message"; + try { + const tx = await standardRevertTestContract.standardRevert(customMessage, { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, customMessage); + + // Verify we can capture the revert reason via static call + try { + await standardRevertTestContract.standardRevert.staticCall(customMessage); + expect.fail('Static call should have reverted'); + } catch (error) { + decodedReason = decodeRevertReason(error.data); + } + expect(decodedReason).to.include(customMessage); + }); + + it('should handle require revert with proper error message', async function () { + const value = 100; + const threshold = 50; + + try { + const tx = await standardRevertTestContract.requireRevert(value, threshold, { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, "Value exceeds threshold"); + + // Verify we can capture the revert reason via static call + try { + await standardRevertTestContract.requireRevert.staticCall(value, threshold); + expect.fail('Static call should have reverted'); + } catch (error) { + decodedReason = decodeRevertReason(error.data); + } + expect(decodedReason).to.include("Value exceeds threshold"); + + // Verify successful case (no revert when value < threshold) + const successTx = await standardRevertTestContract.requireRevert(25, 50, { gasLimit: DEFAULT_GAS_LIMIT }); + const receipt = await successTx.wait(); + expect(receipt.status).to.equal(1, 'Transaction should succeed when value < threshold'); + }); + + it('should handle assert revert (Panic error)', async function () { + try { + const tx = await standardRevertTestContract.assertRevert({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, PANIC_ASSERT_0x01); + + // Verify we can capture the revert reason via static call + try { + await standardRevertTestContract.assertRevert.staticCall(); + expect.fail('Static call should have reverted'); + } catch (error) { + decodedReason = decodeRevertReason(error.data); + } + expect(decodedReason).to.include(PANIC_ASSERT_0x01); + }); + + it('should handle division by zero (View Panic error)', async function () { + try { + await standardRevertTestContract.divisionByZero(); + expect.fail('View call should have reverted'); + } catch (error) { + decodedReason = decodeRevertReason(error.data); + } + expect(decodedReason).to.include(PANIC_DIVISION_BY_ZERO_0x12); + }); + + it('should handle division by zero (Transaction Panic error)', async function () { + try { + const tx = await standardRevertTestContract.divisionByZeroTx({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, PANIC_DIVISION_BY_ZERO_0x12); + }); + + it('should handle array out of bounds (View Panic error)', async function () { + try { + await standardRevertTestContract.arrayOutOfBounds(); + expect.fail('View call should have reverted'); + } catch (error) { + decodedReason = decodeRevertReason(error.data); + } + expect(decodedReason).contains(PANIC_ARRAY_OUT_OF_BOUND_0x32); + }); + + it('should handle array out of bounds (Transaction Panic error)', async function () { + try { + const tx = await standardRevertTestContract.arrayOutOfBoundsTx({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, PANIC_ARRAY_OUT_OF_BOUND_0x32); + }); + + it('should capture revert reason through eth_getTransactionReceipt', async function () { + try { + const tx = await standardRevertTestContract.standardRevert("Test message", { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, "Test message"); + }); + }); + + describe('Complex Revert Scenarios', function () { + it('should handle multiple calls with revert', async function () { + try { + const tx = await standardRevertTestContract.multipleCallsWithRevert({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, "Multiple calls revert"); + }); + + it('should handle try-catch revert scenario', async function () { + try { + const tx = await standardRevertTestContract.tryCatchRevert(true, { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, "Internal function revert"); + }); + + it('should handle wrapper contract revert', async function () { + const contractAddress = await standardRevertTestContract.getAddress(); + try { + const tx = await simpleWrapper.wrappedStandardCall(contractAddress, "Wrapper test", { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, "Wrapper test"); + }); + }); + + describe('OutOfGas Error Cases', function () { + it('should handle standard contract OutOfGas', async function () { + try { + const tx = await standardRevertTestContract.standardOutOfGas({ gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyOutOfGasError(analysis); + }); + + it('should handle expensive computation OutOfGas', async function () { + try { + const tx = await standardRevertTestContract.expensiveComputation(10000, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyOutOfGasError(analysis); + }); + + it('should handle expensive storage OutOfGas', async function () { + try { + const tx = await standardRevertTestContract.expensiveStorage(100, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyOutOfGasError(analysis); + }); + + it('should handle wrapper OutOfGas', async function () { + const contractAddress = await standardRevertTestContract.getAddress(); + try { + const tx = await simpleWrapper.wrappedOutOfGasCall(contractAddress, { gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyOutOfGasError(analysis); + }); + + it('should analyze OutOfGas error through transaction receipt', async function () { + try { + const tx = await standardRevertTestContract.standardOutOfGas({ gasLimit: LOW_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have failed with OutOfGas'); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyOutOfGasError(analysis); + }); + }); + + describe('Comprehensive Error Analysis', function () { + it('should properly decode various error types from transaction receipts', async function () { + // Transaction-based functions that create receipts + const transactionTestCases = [ + { + name: 'Standard Revert', + call: async () => { + const tx = await standardRevertTestContract.standardRevert("Standard error", { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + }, + expectedReason: "Standard error" + }, + { + name: 'Require Revert', + call: async () => { + const tx = await standardRevertTestContract.requireRevert(100, 50, { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + }, + expectedReason: "Value exceeds threshold" + }, + { + name: 'Assert Revert', + call: async () => { + const tx = await standardRevertTestContract.assertRevert({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + }, + expectedReason: PANIC_ASSERT_0x01 + }, + { + name: 'Division by Zero (Transaction)', + call: async () => { + const tx = await standardRevertTestContract.divisionByZeroTx({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + }, + expectedReason: PANIC_DIVISION_BY_ZERO_0x12 + }, + { + name: 'Array Out of Bounds (Transaction)', + call: async () => { + const tx = await standardRevertTestContract.arrayOutOfBoundsTx({ gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + }, + expectedReason: PANIC_ARRAY_OUT_OF_BOUND_0x32 + } + ]; + + // View functions that don't create receipts but still revert + const viewTestCases = [ + { + name: 'Division by Zero (View)', + call: async () => await standardRevertTestContract.divisionByZero(), + expectedReason: PANIC_DIVISION_BY_ZERO_0x12 + }, + { + name: 'Array Out of Bounds (View)', + call: async () => await standardRevertTestContract.arrayOutOfBounds(), + expectedReason: PANIC_ARRAY_OUT_OF_BOUND_0x32 + } + ]; + + // Test transaction-based functions + for (const testCase of transactionTestCases) { + try { + await testCase.call(); + expect.fail(`${testCase.name} should have reverted`); + } catch (error) { + analysis = await analyzeFailedTransaction(error.receipt.hash); + } + verifyTransactionRevert(analysis, testCase.expectedReason); + } + + // Test view functions (no receipts) + for (const testCase of viewTestCases) { + try { + await testCase.call(); + expect.fail(`${testCase.name} should have reverted`); + } catch (error) { + decodedReason = decodeRevertReason(error.data); + } + expect(decodedReason).contains(testCase.expectedReason); + } + }); + + it('should verify error data is properly hex-encoded in receipts', async function () { + try { + const tx = await standardRevertTestContract.standardRevert("Hex encoding test", { gasLimit: DEFAULT_GAS_LIMIT }); + await tx.wait(); + expect.fail('Transaction should have reverted'); + } catch (error) { + try { + const contractAddress = await standardRevertTestContract.getAddress(); + await hre.ethers.provider.call({ + to: contractAddress, + data: standardRevertTestContract.interface.encodeFunctionData('standardRevert', ['Hex encoding test']), + gasLimit: DEFAULT_GAS_LIMIT + }); + expect.fail('Call should have reverted'); + } catch (error) { + decodedReason = await decodeRevertReason(error.data); + } + expect(decodedReason).to.include('Hex encoding test'); + } + }); + }); +}); \ No newline at end of file diff --git a/tests/solidity/suites/revert_cases/test/test_helper.js b/tests/solidity/suites/revert_cases/test/test_helper.js new file mode 100644 index 000000000..258bb2ac3 --- /dev/null +++ b/tests/solidity/suites/revert_cases/test/test_helper.js @@ -0,0 +1,144 @@ +const { expect } = require('chai'); + +// Helper to convert the raw tuple returned by staking.validator() into an object +function parseValidator (raw) { + return { + operatorAddress: raw[0], + consensusPubkey: raw[1], + jailed: raw[2], + status: raw[3], + tokens: raw[4], + delegatorShares: raw[5], + description: raw[6], + unbondingHeight: raw[7], + unbondingTime: raw[8], + commission: raw[9], + minSelfDelegation: raw[10] + } +} + +// Utility to parse logs and return the first matching event by name +function findEvent (logs, iface, eventName) { + for (const log of logs) { + try { + const parsed = iface.parseLog(log) + if (parsed && parsed.name === eventName) { + return parsed + } + } catch { + // ignore logs that do not match the contract interface + } + } + return null +} + +/** + * Helper function to decode hex error data from transaction receipt + */ +function decodeRevertReason(errorData) { + if (!errorData || errorData === '0x') { + return null; + } + + try { + // Remove '0x' prefix + const cleanHex = errorData.startsWith('0x') ? errorData.slice(2) : errorData; + + // Check if it's a standard revert string (function selector: 08c379a0) + if (cleanHex.startsWith('08c379a0')) { + const reasonHex = cleanHex.slice(8); // Remove function selector + const offsetHex = reasonHex.slice(0, 64); // Get offset (should be 0x20 = 32) + const offset = parseInt(offsetHex, 16); + + if (offset === 32) { // Standard ABI encoding has offset of 32 + const reasonLength = parseInt(reasonHex.slice(64, 128), 16); // Get string length from next 32 bytes + const reasonBytes = reasonHex.slice(128, 128 + reasonLength * 2); // Get string data + return Buffer.from(reasonBytes, 'hex').toString('utf8'); + } else { + // Fallback for non-standard encoding + const reasonLength = parseInt(reasonHex.slice(0, 64), 16); // Get string length + const reasonBytes = reasonHex.slice(128, 128 + reasonLength * 2); // Get string data + return Buffer.from(reasonBytes, 'hex').toString('utf8'); + } + } + + // Check if it's a Panic error (function selector: 4e487b71) + if (cleanHex.startsWith('4e487b71')) { + const panicCode = parseInt(cleanHex.slice(8, 72), 16); + return `Panic(${panicCode})`; + } + + // Return raw hex if not a standard format + return `Raw: ${errorData}`; + } catch (error) { + return `Decode error: ${error.message}`; + } +} + +/** + * Helper function to analyze transaction receipt for revert information + */ +async function analyzeFailedTransaction(txHash) { + const receipt = await hre.ethers.provider.getTransactionReceipt(txHash); + const tx = await hre.ethers.provider.getTransaction(txHash); + + // Try to get revert reason through call simulation + try { + await hre.ethers.provider.call({ + to: tx.to, + data: tx.data, + from: tx.from, + value: tx.value, + gasLimit: tx.gasLimit, + gasPrice: tx.gasPrice + }); + } catch (error) { + console.log(` Revert Reason: ${decodeRevertReason(error.data)}`); + return { + status: receipt.status, + gasUsed: receipt.gasUsed, + gasLimit: tx.gasLimit, + errorData: error.data, + decodedReason: decodeRevertReason(error.data), + errorMessage: error.message + }; + } + + return { + status: receipt.status, + gasUsed: receipt.gasUsed, + gasLimit: tx.gasLimit, + errorData: null, + decodedReason: null, + errorMessage: null + }; +} + +/** + * Helper function to verify decoded revert reason + */ +function verifyTransactionRevert(analysis, expectedRevertReason) { + expect(analysis).to.not.be.null; + expect(analysis.status).to.equal(0); // Failed transaction + expect(analysis.errorData).to.not.be.null; + expect(analysis.decodedReason).contains(expectedRevertReason, "unexpected revert reason"); +} + +/** + * Helper function to verify out of gas error + */ +function verifyOutOfGasError(analysis) { + expect(analysis).to.not.be.null; + expect(analysis.status).to.equal(0); // Failed transaction + expect(analysis.gasUsed).to.be.equal(analysis.gasLimit); + expect(analysis.errorMessage.toLowerCase()).include('out of gas'); +} + +module.exports = { + parseValidator, + findEvent, + decodeRevertReason, + analyzeFailedTransaction, + verifyTransactionRevert, + verifyOutOfGasError +} \ No newline at end of file diff --git a/tests/systemtests/README.md b/tests/systemtests/README.md new file mode 100644 index 000000000..d8d9c3c64 --- /dev/null +++ b/tests/systemtests/README.md @@ -0,0 +1,51 @@ +# Getting started with a new system test + +## Overview + +The systemtests suite is an end-to-end test suite that runs the evmd process and sends RPC requests from separate Ethereum/Cosmos clients. The systemtests for cosmos/evm use the `cosmossdk.io/systemtests` package by default. For more details, please refer to https://github.com/cosmos/cosmos-sdk/tree/main/tests/systemtests. + +## Preparation + +Build a new binary from current branch and copy it to the `tests/systemtests/binaries` folder by running system tests. + +```shell +make test-system +``` + +Or via manual steps + +```shell +make build +mkdir -= ./tests/systemtests/binaries +cp ./build/evmd ./tests/systemtests/binaries +cp ./build/evmd ./tests/systemtests/binaries/v0.4 +``` + +## Run Individual test + +### Run test cases for txs ordering + +```shell +go test -p 1 -parallel 1 -mod=readonly -tags='system_test' -v ./... \ +--run TestTxsOrdering --verbose --binary evmd --block-time 5s --chain-id local-4221 +``` + +### Run test cases for txs replacement + +```shell +go test -p 1 -parallel 1 -mod=readonly -tags='system_test' -v ./... \ +--run TestTxsReplacement --verbose --binary evmd --block-time 5s --chain-id local-4221 +``` + +### Run test exceptions + +```shell +go test -p 1 -parallel 1 -mod=readonly -tags='system_test' -v ./... \ +--run TestExceptions --verbose --binary evmd --block-time 5s --chain-id local-4221 +``` + +## Run Entire test + +```shell +make test +``` diff --git a/tests/systemtests/clients/config.go b/tests/systemtests/clients/config.go new file mode 100644 index 000000000..dec6081c2 --- /dev/null +++ b/tests/systemtests/clients/config.go @@ -0,0 +1,75 @@ +package clients + +import ( + "fmt" + "math/big" +) + +/** +# ---------------- dev mnemonics source ---------------- +# dev0 address 0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101 | cosmos1cml96vmptgw99syqrrz8az79xer2pcgp84pdun +# dev0's private key: 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305 # gitleaks:allow + +# dev1 address 0x963EBDf2e1f8DB8707D05FC75bfeFFBa1B5BaC17 | cosmos1jcltmuhplrdcwp7stlr4hlhlhgd4htqh3a79sq +# dev1's private key: 0x741de4f8988ea941d3ff0287911ca4074e62b7d45c991a51186455366f10b544 # gitleaks:allow + +# dev2 address 0x40a0cb1C63e026A81B55EE1308586E21eec1eFa9 | cosmos1gzsvk8rruqn2sx64acfsskrwy8hvrmafqkaze8 +# dev2's private key: 0x3b7955d25189c99a7468192fcbc6429205c158834053ebe3f78f4512ab432db9 # gitleaks:allow + +# dev3 address 0x498B5AeC5D439b733dC2F58AB489783A23FB26dA | cosmos1fx944mzagwdhx0wz7k9tfztc8g3lkfk6rrgv6l +# dev3's private key: 0x8a36c69d940a92fcea94b36d0f2928c7a0ee19a90073eda769693298dfa9603b # gitleaks:allow +*/ + +const ( + ChainID = "local-4221" + EVMChainID = "262144" + + Acc0PrivKey = "88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305" + Acc1PrivKey = "741de4f8988ea941d3ff0287911ca4074e62b7d45c991a51186455366f10b544" + Acc2PrivKey = "3b7955d25189c99a7468192fcbc6429205c158834053ebe3f78f4512ab432db9" + Acc3PrivKey = "8a36c69d940a92fcea94b36d0f2928c7a0ee19a90073eda769693298dfa9603b" + + JsonRPCUrl0 = "http://127.0.0.1:8545" + JsonRPCUrl1 = "http://127.0.0.1:8555" + JsonRPCUrl2 = "http://127.0.0.1:8565" + JsonRPCUrl3 = "http://127.0.0.1:8575" + + NodeRPCUrl0 = "http://127.0.0.1:26657" + NodeRPCUrl1 = "http://127.0.0.1:26658" + NodeRPCUrl2 = "http://127.0.0.1:26659" + NodeRPCUrl3 = "http://127.0.0.1:26660" +) + +type Config struct { + ChainID string + EVMChainID *big.Int + PrivKeys []string + JsonRPCUrls []string + NodeRPCUrls []string +} + +// NewConfig creates a new Config instance. +func NewConfig() (*Config, error) { + // evm chainID + evmChainID, ok := new(big.Int).SetString(EVMChainID, 10) + if !ok { + return nil, fmt.Errorf("error whilte setting chain id") + } + + // private keys of test accounts + privKeys := []string{Acc0PrivKey, Acc1PrivKey, Acc2PrivKey, Acc3PrivKey} + + // jsonrpc urls of testnet nodes + jsonRPCUrls := []string{JsonRPCUrl0, JsonRPCUrl1, JsonRPCUrl2, JsonRPCUrl3} + + // rpc urls of test nodes + nodeRPCUrls := []string{NodeRPCUrl0, NodeRPCUrl1, NodeRPCUrl2, NodeRPCUrl3} + + return &Config{ + ChainID: ChainID, + EVMChainID: evmChainID, + PrivKeys: privKeys, + JsonRPCUrls: jsonRPCUrls, + NodeRPCUrls: nodeRPCUrls, + }, nil +} diff --git a/tests/systemtests/clients/cosmosclient.go b/tests/systemtests/clients/cosmosclient.go new file mode 100644 index 000000000..56db64e20 --- /dev/null +++ b/tests/systemtests/clients/cosmosclient.go @@ -0,0 +1,265 @@ +package clients + +import ( + "context" + "encoding/hex" + "fmt" + "math/big" + "slices" + "time" + + "github.com/ethereum/go-ethereum/crypto" + + "github.com/cosmos/evm/crypto/ethsecp256k1" + + rpchttp "github.com/cometbft/cometbft/v2/rpc/client/http" + coretypes "github.com/cometbft/cometbft/v2/rpc/core/types" + + sdkmath "cosmossdk.io/math" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + clienttx "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/std" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// CosmosClient is a client for interacting with Cosmos SDK-based nodes. +type CosmosClient struct { + ChainID string + ClientCtx client.Context + RpcClients map[string]*rpchttp.HTTP + Accs map[string]*CosmosAccount +} + +// NewCosmosClient creates a new CosmosClient instance. +func NewCosmosClient() (*CosmosClient, error) { + config, err := NewConfig() + if err != nil { + return nil, fmt.Errorf("failed to load config") + } + + clientCtx, err := newClientContext(config) + if err != nil { + return nil, fmt.Errorf("failed to create client context: %v", err) + } + + rpcClients := make(map[string]*rpchttp.HTTP, 0) + for i, nodeUrl := range config.NodeRPCUrls { + rpcClient, err := client.NewClientFromNode(nodeUrl) + if err != nil { + return nil, fmt.Errorf("failed to connect rpc server: %v", err) + } + + rpcClients[fmt.Sprintf("node%v", i)] = rpcClient + } + + accs := make(map[string]*CosmosAccount, 0) + for i, privKeyHex := range config.PrivKeys { + priv, err := crypto.HexToECDSA(privKeyHex) + + privKey := ðsecp256k1.PrivKey{Key: crypto.FromECDSA(priv)} + addr := sdk.AccAddress(privKey.PubKey().Address().Bytes()) + + if err != nil { + return nil, err + } + acc := &CosmosAccount{ + AccAddress: addr, + AccountNumber: uint64(i + 1), + PrivKey: privKey, + } + accs[fmt.Sprintf("acc%v", i)] = acc + } + + return &CosmosClient{ + ChainID: config.ChainID, + ClientCtx: *clientCtx, + RpcClients: rpcClients, + Accs: accs, + }, nil +} + +// BankSend sends a bank send transaction from one account to another. +func (c *CosmosClient) BankSend(nodeID, accID string, from, to sdk.AccAddress, amount sdkmath.Int, nonce uint64, gasPrice *big.Int) (*sdk.TxResponse, error) { + c.ClientCtx = c.ClientCtx.WithClient(c.RpcClients[nodeID]) + + privKey := c.Accs[accID].PrivKey + accountNumber := c.Accs[accID].AccountNumber + + msg := banktypes.NewMsgSend(from, to, sdk.NewCoins(sdk.NewCoin("atest", amount))) + + txBytes, err := c.signMsgsV2(privKey, accountNumber, nonce, gasPrice, msg) + if err != nil { + return nil, fmt.Errorf("failed to sign tx msg: %v", err) + } + + resp, err := c.ClientCtx.BroadcastTx(txBytes) + if err != nil { + return nil, fmt.Errorf("failed to broadcast tx: %v", err) + } + + return resp, nil +} + +// WaitForCommit waits for a transaction to be committed in a block. +func (c *CosmosClient) WaitForCommit( + nodeID string, + txHash string, + timeout time.Duration, +) (*coretypes.ResultTx, error) { + c.ClientCtx = c.ClientCtx.WithClient(c.RpcClients[nodeID]) + + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + + hashBytes, err := hex.DecodeString(txHash) + if err != nil { + return nil, fmt.Errorf("invalid tx hash format: %v", err) + } + + for { + select { + case <-ctx.Done(): + return nil, fmt.Errorf("timeout waiting for transaction %s", txHash) + case <-ticker.C: + result, err := c.ClientCtx.Client.Tx(ctx, hashBytes, false) + if err != nil { + continue + } + + return result, nil + } + } +} + +// CheckTxsPending checks if a transaction is either pending in the mempool or already committed. +func (c *CosmosClient) CheckTxsPending( + nodeID string, + txHash string, + timeout time.Duration, +) error { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return fmt.Errorf("timeout waiting for transaction %s", txHash) + case <-ticker.C: + result, err := c.UnconfirmedTxs(nodeID) + if err != nil { + return fmt.Errorf("failed to call unconfired transactions from cosmos client: %v", err) + } + + pendingTxHashes := make([]string, 0) + for _, tx := range result.Txs { + pendingTxHashes = append(pendingTxHashes, tx.Hash().String()) + } + + if ok := slices.Contains(pendingTxHashes, txHash); ok { + return nil + } + } + } +} + +// UnconfirmedTxs retrieves the list of unconfirmed transactions from the node's mempool. +func (c *CosmosClient) UnconfirmedTxs(nodeID string) (*coretypes.ResultUnconfirmedTxs, error) { + return c.RpcClients[nodeID].UnconfirmedTxs(context.Background(), nil) +} + +// newClientContext creates a new client context for the Cosmos SDK. +func newClientContext(config *Config) (*client.Context, error) { + // Create codec and tx config + interfaceRegistry := types.NewInterfaceRegistry() + std.RegisterInterfaces(interfaceRegistry) + marshaler := codec.NewProtoCodec(interfaceRegistry) + txConfig := tx.NewTxConfig(marshaler, tx.DefaultSignModes) + + // Create client context + clientCtx := client.Context{ + BroadcastMode: flags.BroadcastSync, + TxConfig: txConfig, + Codec: marshaler, + InterfaceRegistry: interfaceRegistry, + ChainID: config.ChainID, + AccountRetriever: authtypes.AccountRetriever{}, + } + + return &clientCtx, nil +} + +// signMsgsV2 signs the provided messages using the given private key and returns the signed transaction bytes. +func (c *CosmosClient) signMsgsV2(privKey cryptotypes.PrivKey, accountNumber, sequence uint64, gasPrice *big.Int, msg sdk.Msg) ([]byte, error) { + senderAddr := sdk.AccAddress(privKey.PubKey().Address().Bytes()) + signMode := signing.SignMode_SIGN_MODE_DIRECT + + txBuilder := c.ClientCtx.TxConfig.NewTxBuilder() + txBuilder.SetMsgs(msg) + txBuilder.SetFeePayer(senderAddr) + + signerData := xauthsigning.SignerData{ + Address: senderAddr.String(), + ChainID: c.ChainID, + AccountNumber: accountNumber, + Sequence: sequence, + PubKey: privKey.PubKey(), + } + + sigsV2 := signing.SignatureV2{ + PubKey: privKey.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: signMode, + Signature: nil, + }, + Sequence: sequence, + } + + err := txBuilder.SetSignatures(sigsV2) + if err != nil { + return nil, fmt.Errorf("failed to set empty signatures: %v", err) + } + + txBuilder.SetGasLimit(150_000) + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin("atest", sdkmath.NewIntFromBigInt(gasPrice).MulRaw(150_001)))) + + sigV2, err := clienttx.SignWithPrivKey( + context.Background(), + signMode, + signerData, + txBuilder, + privKey, + c.ClientCtx.TxConfig, + sequence, + ) + if err != nil { + return nil, fmt.Errorf("failed to sign with private key: %v", err) + } + + err = txBuilder.SetSignatures(sigV2) + if err != nil { + return nil, fmt.Errorf("failed to set signatures: %v", err) + } + + txBytes, err := c.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx()) + if err != nil { + return nil, fmt.Errorf("failed to encode tx: %v", err) + } + + return txBytes, nil +} diff --git a/tests/systemtests/clients/ethclient.go b/tests/systemtests/clients/ethclient.go new file mode 100644 index 000000000..c084e8b4d --- /dev/null +++ b/tests/systemtests/clients/ethclient.go @@ -0,0 +1,184 @@ +package clients + +import ( + "context" + "fmt" + "maps" + "math/big" + "slices" + "time" + + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +// EthClient is a client for interacting with Ethereum-compatible nodes. +type EthClient struct { + ChainID *big.Int + Clients map[string]*ethclient.Client + Accs map[string]*EthAccount +} + +// NewEthClient creates a new EthClient instance. +func NewEthClient() (*EthClient, error) { + config, err := NewConfig() + if err != nil { + return nil, fmt.Errorf("failed to load config") + } + + clients := make(map[string]*ethclient.Client, 0) + for i, jsonrpcUrl := range config.JsonRPCUrls { + ethcli, err := ethclient.Dial(jsonrpcUrl) + if err != nil { + return nil, fmt.Errorf("failed to connecting node url: %s", jsonrpcUrl) + } + clients[fmt.Sprintf("node%v", i)] = ethcli + } + + accs := make(map[string]*EthAccount, 0) + for i, privKey := range config.PrivKeys { + ecdsaPrivKey, err := crypto.HexToECDSA(privKey) + if err != nil { + return nil, err + } + address := crypto.PubkeyToAddress(ecdsaPrivKey.PublicKey) + acc := &EthAccount{ + Address: address, + PrivKey: ecdsaPrivKey, + } + accs[fmt.Sprintf("acc%v", i)] = acc + } + + return &EthClient{ + ChainID: config.EVMChainID, + Clients: clients, + Accs: accs, + }, nil +} + +// Setup prepares the context, client, and address for the given node and account IDs. +func (ec *EthClient) Setup(nodeID string, accID string) (context.Context, *ethclient.Client, common.Address) { + return context.Background(), ec.Clients[nodeID], ec.Accs[accID].Address +} + +// SendRawTransaction sends a raw Ethereum transaction to the specified node. +func (ec *EthClient) SendRawTransaction( + nodeID string, + accID string, + tx *ethtypes.Transaction, +) (common.Hash, error) { + ethCli := ec.Clients[nodeID] + privKey := ec.Accs[accID].PrivKey + + signer := ethtypes.NewLondonSigner(ec.ChainID) + signedTx, err := ethtypes.SignTx(tx, signer, privKey) + if err != nil { + return common.Hash{}, err + } + + if err = ethCli.SendTransaction(context.Background(), signedTx); err != nil { + return common.Hash{}, err + } + + return signedTx.Hash(), nil +} + +// WaitForCommit waits for a transaction to be committed in a block. +func (ec *EthClient) WaitForCommit( + nodeID string, + txHash string, + timeout time.Duration, +) (*ethtypes.Receipt, error) { + ethCli := ec.Clients[nodeID] + + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return nil, fmt.Errorf("timeout waiting for transaction %s", txHash) + case <-ticker.C: + receipt, err := ethCli.TransactionReceipt(context.Background(), common.HexToHash(txHash)) + if err != nil { + continue // Transaction not mined yet + } + + return receipt, nil + } + } +} + +// CheckTxsPending checks if a transaction is either pending in the mempool or already committed. +func (ec *EthClient) CheckTxsPending( + nodeID string, + txHash string, + timeout time.Duration, +) error { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return fmt.Errorf("timeout waiting for transaction %s", txHash) + case <-ticker.C: + pendingTxs, _, err := ec.TxPoolContent(nodeID) + if err != nil { + return fmt.Errorf("failed to get txpool content") + } + + pendingTxHashes := extractTxHashesSorted(pendingTxs) + + if ok := slices.Contains(pendingTxHashes, txHash); ok { + return nil + } + } + } +} + +// TxPoolContent returns the pending and queued tx hashes in the tx pool of the given node +func (ec *EthClient) TxPoolContent(nodeID string) (map[string]map[string]*EthRPCTransaction, map[string]map[string]*EthRPCTransaction, error) { + ethCli := ec.Clients[nodeID] + + var result TxPoolResult + err := ethCli.Client().Call(&result, "txpool_content") + if err != nil { + return nil, nil, fmt.Errorf("failed to call txpool_content eth api: %v", err) + } + + return result.Pending, result.Queued, nil +} + +// extractTxHashesSorted processes transaction maps in a deterministic order and returns flat slice of tx hashes +func extractTxHashesSorted(txMap map[string]map[string]*EthRPCTransaction) []string { + var result []string + + // Get addresses and sort them for deterministic iteration + addresses := slices.Collect(maps.Keys(txMap)) + slices.Sort(addresses) + + // Process addresses in sorted order + for _, addr := range addresses { + txs := txMap[addr] + + // Sort transactions by nonce for deterministic ordering + nonces := slices.Collect(maps.Keys(txs)) + slices.Sort(nonces) + + // Add transaction hashes to flat result slice + for _, nonce := range nonces { + result = append(result, txs[nonce].Hash.Hex()) + } + } + + return result +} diff --git a/tests/systemtests/clients/types.go b/tests/systemtests/clients/types.go new file mode 100644 index 000000000..82206eabb --- /dev/null +++ b/tests/systemtests/clients/types.go @@ -0,0 +1,29 @@ +package clients + +import ( + "crypto/ecdsa" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/evm/crypto/ethsecp256k1" + "github.com/ethereum/go-ethereum/common" +) + +type EthAccount struct { + Address common.Address + PrivKey *ecdsa.PrivateKey +} + +type CosmosAccount struct { + AccAddress sdk.AccAddress + AccountNumber uint64 + PrivKey *ethsecp256k1.PrivKey +} + +type TxPoolResult struct { + Pending map[string]map[string]*EthRPCTransaction `json:"pending"` + Queued map[string]map[string]*EthRPCTransaction `json:"queued"` +} + +type EthRPCTransaction struct { + Hash common.Hash `json:"hash"` +} diff --git a/tests/systemtests/eth_test.go b/tests/systemtests/eth_test.go index 57b017fb8..d94c24286 100644 --- a/tests/systemtests/eth_test.go +++ b/tests/systemtests/eth_test.go @@ -29,7 +29,14 @@ const ( ) func StartChain(t *testing.T, sut *systemtests.SystemUnderTest) { - sut.StartChain(t, "--json-rpc.api=eth,txpool,personal,net,debug,web3", "--chain-id", "local-4221", "--api.enable=true") + chainID := "--chain-id=local-4221" + apiEnable := "--api.enable=true" + jsonrpcApi := "--json-rpc.api=eth,txpool,personal,net,debug,web3" + jsonrpcAllowUnprotectedTxs := "--json-rpc.allow-unprotected-txs=true" + + args := []string{jsonrpcApi, chainID, apiEnable, jsonrpcAllowUnprotectedTxs} + + sut.StartChain(t, args...) } // cosmos and eth tx with same nonce. @@ -70,39 +77,39 @@ func TestPriorityReplacement(t *testing.T) { wg := sync.WaitGroup{} + var highPrioRes []byte wg.Add(1) - var lowPrioRes []byte go func() { defer wg.Done() var prioErr error - lowPrioRes, prioErr = exec.Command( + highPrioRes, prioErr = exec.Command( "cast", "send", contractAddr, "increment()", "--rpc-url", "http://127.0.0.1:8545", "--private-key", pk, - "--gas-price", "100000000000", + "--gas-price", "100000000000000", + "--priority-gas-price", "100", "--nonce", "2", ).CombinedOutput() - require.Error(t, prioErr) + require.NoError(t, prioErr) }() - var highPrioRes []byte wg.Add(1) + var lowPrioRes []byte go func() { defer wg.Done() var prioErr error - highPrioRes, prioErr = exec.Command( + lowPrioRes, prioErr = exec.Command( "cast", "send", contractAddr, "increment()", "--rpc-url", "http://127.0.0.1:8545", "--private-key", pk, - "--gas-price", "100000000000000", - "--priority-gas-price", "100", + "--gas-price", "99900000000000", "--nonce", "2", ).CombinedOutput() - require.NoError(t, prioErr) + require.Error(t, prioErr) }() // wait a bit to make sure the tx is submitted and waiting in the txpool. @@ -121,9 +128,13 @@ func TestPriorityReplacement(t *testing.T) { wg.Wait() lowPrioReceipt, err := parseReceipt(string(lowPrioRes)) + fmt.Println("DEBUG - lowPrioRes: ", string(lowPrioRes)) + fmt.Println("DEBUG - lowPrioReceipt: ", lowPrioReceipt) require.NoError(t, err) highPrioReceipt, err := parseReceipt(string(highPrioRes)) + fmt.Println("DEBUG - highPrioRes: ", string(highPrioRes)) + fmt.Println("DEBUG - highPrioReceipt: ", highPrioReceipt) require.NoError(t, err) // 1 = success, 0 = failure. diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 14c227134..76231a8b2 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -1,11 +1,17 @@ -module github.com/evmos/tests/systemtests +module github.com/cosmos/evm/tests/systemtests go 1.24.4 require ( + cosmossdk.io/math v1.5.3 cosmossdk.io/systemtests v1.3.0 - github.com/ethereum/go-ethereum v1.15.5 + github.com/cometbft/cometbft/v2 v2.0.0-rc1 + github.com/cosmos/cosmos-sdk v0.54.0-rc.1 + github.com/cosmos/evm v0.5.0-rc.0 + github.com/ethereum/go-ethereum v1.15.11 github.com/stretchr/testify v1.10.0 + github.com/test-go/testify v1.1.4 + github.com/tidwall/gjson v1.18.0 ) require ( @@ -14,21 +20,22 @@ require ( cosmossdk.io/core v1.1.0-rc.1 // indirect cosmossdk.io/depinject v1.2.1 // indirect cosmossdk.io/errors v1.0.2 // indirect - cosmossdk.io/log v1.6.0 // indirect - cosmossdk.io/math v1.5.3 // indirect + cosmossdk.io/log v1.6.1 // indirect cosmossdk.io/schema v1.1.0 // indirect cosmossdk.io/store v1.10.0-rc.2 // indirect cosmossdk.io/x/tx v1.2.0-rc.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect - github.com/99designs/keyring v1.2.1 // indirect - github.com/DataDog/datadog-go v3.2.0+incompatible // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/DataDog/datadog-go v4.8.3+incompatible // indirect github.com/DataDog/zstd v1.5.7 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect github.com/bits-and-blooms/bitset v1.22.0 // indirect - github.com/bytedance/sonic v1.13.2 // indirect - github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.5 // indirect @@ -38,41 +45,44 @@ require ( github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.6 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb // indirect + github.com/cometbft/cometbft v0.38.18 // indirect github.com/cometbft/cometbft-db v1.0.4 // indirect github.com/cometbft/cometbft/api v1.1.0-rc1 // indirect - github.com/cometbft/cometbft/v2 v2.0.0-rc1 // indirect - github.com/consensys/bavard v0.1.22 // indirect - github.com/consensys/gnark-crypto v0.14.0 // indirect + github.com/consensys/gnark-crypto v0.18.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.1.3 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect - github.com/cosmos/cosmos-sdk v0.54.0-rc.1 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gogoproto v1.7.0 // indirect github.com/cosmos/iavl v1.2.6 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect - github.com/crate-crypto/go-kzg-4844 v1.1.0 // indirect github.com/creachadair/tomledit v0.0.28 // indirect - github.com/danieljoos/wincred v1.1.2 // indirect + github.com/danieljoos/wincred v1.2.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect - github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/desertbit/timer v1.0.1 // indirect github.com/dgraph-io/badger/v4 v4.6.0 // indirect github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect + github.com/docker/go-connections v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/emicklei/dot v1.8.0 // indirect - github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/getsentry/sentry-go v0.33.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-viper/mapstructure/v2 v2.3.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect @@ -114,7 +124,6 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/minio/highwayhash v1.0.3 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect @@ -133,47 +142,51 @@ require ( github.com/rs/zerolog v1.34.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/cast v1.9.2 // indirect github.com/spf13/cobra v1.9.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.7 // indirect github.com/spf13/viper v1.20.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.14 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect - github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.4.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/arch v0.17.0 // indirect - golang.org/x/crypto v0.39.0 // indirect + golang.org/x/crypto v0.41.0 // indirect golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect - golang.org/x/net v0.40.0 // indirect - golang.org/x/sync v0.15.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.26.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/grpc v1.73.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + google.golang.org/grpc v1.74.2 // indirect + google.golang.org/protobuf v1.36.7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect - nhooyr.io/websocket v1.8.6 // indirect + nhooyr.io/websocket v1.8.11 // indirect pgregory.net/rapid v1.2.0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) + +replace github.com/cosmos/evm => ../.. diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index 2605a2e4b..cb2a24f64 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -1,5 +1,22 @@ +cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= +cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0= +cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM= +cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= +cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc= +cloud.google.com/go/compute v1.29.0 h1:Lph6d8oPi38NHkOr6S55Nus/Pbbcp37m/J0ohgKAefs= +cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= +cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw= +cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU= cosmossdk.io/api v1.0.0-rc.1 h1:KwZHIMveoeg6YVwvKZxJLp7be5uk6qmnqNAar2tPxVU= cosmossdk.io/api v1.0.0-rc.1/go.mod h1:8YOT+XjVFb9eZJk62YqjFILOm8MlLhbnkC9/jxIYri8= cosmossdk.io/collections v1.3.1 h1:09e+DUId2brWsNOQ4nrk+bprVmMUaDH9xvtZkeqIjVw= @@ -10,8 +27,8 @@ cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.6.0 h1:SJIOmJ059wi1piyRgNRXKXhlDXGqnB5eQwhcZKv2tOk= -cosmossdk.io/log v1.6.0/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/log v1.6.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= +cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -20,23 +37,36 @@ cosmossdk.io/store v1.10.0-rc.2 h1:7ze2UoheVTVMK4ElHtoRhYv8nlUImj34e4yp1yy1bgE= cosmossdk.io/store v1.10.0-rc.2/go.mod h1:3p1IV4EGsULFfeyAcfj7/DBcDsy8d3VlYIEJnhhbP3U= cosmossdk.io/systemtests v1.3.0 h1:VzQ/3njGbxhxWuJTKi0pGQG5yr29FY0PAQgY5IOae4g= cosmossdk.io/systemtests v1.3.0/go.mod h1:WMcQ8geP7axtz6/gCq9za0zGUtUiz5bGtzqJl+0E3Yw= +cosmossdk.io/x/evidence v0.2.0 h1:o72zbmgCM7U0v7z7b0XnMB+NqX0tFamqb1HHkQbhrZ0= +cosmossdk.io/x/evidence v0.2.0/go.mod h1:zx/Xqy+hnGVzkqVuVuvmP9KsO6YCl4SfbAetYi+k+sE= +cosmossdk.io/x/feegrant v0.2.0 h1:oq3WVpoJdxko/XgWmpib63V1mYy9ZQN/1qxDajwGzJ8= +cosmossdk.io/x/feegrant v0.2.0/go.mod h1:9CutZbmhulk/Yo6tQSVD5LG8Lk40ZAQ1OX4d1CODWAE= cosmossdk.io/x/tx v1.2.0-rc.1 h1:AartiA6eiTD9KHmnlj3uG3H8FjyjI0qNkmvmU+p6cJ8= cosmossdk.io/x/tx v1.2.0-rc.1/go.mod h1:UzpMTUmQEFfz+m0E+lhzFIiEhtZCHjScU/NC652DBHI= +cosmossdk.io/x/upgrade v0.2.0 h1:ZHy0xny3wBCSLomyhE06+UmQHWO8cYlVYjfFAJxjz5g= +cosmossdk.io/x/upgrade v0.2.0/go.mod h1:DXDtkvi//TrFyHWSOaeCZGBoiGAE6Rs8/0ABt2pcDD0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= -github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= -github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= +github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= +github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE= github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -67,28 +97,33 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY= +github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -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 v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= -github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= -github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= +github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= -github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= +github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -118,6 +153,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= +github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -136,16 +173,16 @@ github.com/cockroachdb/redact v1.1.6/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb h1:3bCgBvB8PbJVMX1ouCcSIxvsqKPYM7gs72o0zC76n9g= github.com/cockroachdb/tokenbucket v0.0.0-20250429170803-42689b6311bb/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= +github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= github.com/cometbft/cometbft-db v1.0.4 h1:cezb8yx/ZWcF124wqUtAFjAuDksS1y1yXedvtprUFxs= github.com/cometbft/cometbft-db v1.0.4/go.mod h1:M+BtHAGU2XLrpUxo3Nn1nOCcnVCiLM9yx5OuT0u5SCA= github.com/cometbft/cometbft/api v1.1.0-rc1 h1:NdlXfp4wialMwJ+1ds1DBtfysdxErUxg8/AaqgT0ifQ= github.com/cometbft/cometbft/api v1.1.0-rc1/go.mod h1:Ivh6nSCTJPQOyfQo8dgnyu/T88it092sEqSrZSmTQN8= github.com/cometbft/cometbft/v2 v2.0.0-rc1 h1:3QyDHTFzH3a1N6c2jt03kFDCxM/hgUvhzDYBVnPVXY8= github.com/cometbft/cometbft/v2 v2.0.0-rc1/go.mod h1:/ze08eO171CqUqTqAE7FW7ydUJIVkgp6e2svpYvIR3c= -github.com/consensys/bavard v0.1.22 h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI0A= -github.com/consensys/bavard v0.1.22/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= -github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= -github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= +github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= +github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -169,12 +206,17 @@ github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fr github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/iavl v1.2.6 h1:Hs3LndJbkIB+rEvToKJFXZvKo6Vy0Ex1SJ54hhtioIs= github.com/cosmos/iavl v1.2.6/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= +github.com/cosmos/ibc-go/v10 v10.3.0 h1:w5DkHih8qn15deAeFoTk778WJU+xC1krJ5kDnicfUBc= +github.com/cosmos/ibc-go/v10 v10.3.0/go.mod h1:CthaR7n4d23PJJ7wZHegmNgbVcLXCQql7EwHrAXnMtw= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= 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.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/crate-crypto/go-eth-kzg v1.3.0 h1:05GrhASN9kDAidaFJOda6A4BEvgvuXbazXg/0E3OOdI= +github.com/crate-crypto/go-eth-kzg v1.3.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= @@ -183,18 +225,21 @@ github.com/creachadair/tomledit v0.0.28 h1:aQJVwcNTzx4SZ/tSbkyGE69w4YQ6Gn+xhHHKt github.com/creachadair/tomledit v0.0.28/go.mod h1:pqb2HRQi0lMu6MBiUmTk/0XQ+SmPtq2QbUrG+eiLP5w= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= -github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= +github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= -github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= +github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= github.com/dgraph-io/badger/v4 v4.6.0 h1:acOwfOOZ4p1dPRnYzvkVm7rUk2Y21TgPVepCy5dJdFQ= github.com/dgraph-io/badger/v4 v4.6.0/go.mod h1:KSJ5VTuZNC3Sd+YhvVjk2nYua9UZnnTr/SkXvdtiPgI= github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= @@ -202,15 +247,15 @@ github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4Typ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= -github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= +github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= @@ -224,11 +269,16 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M= +github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= +github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= -github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.15.5 h1:Fo2TbBWC61lWVkFw9tsMoHCNX1ndpuaQBRJ8H6xLUPo= -github.com/ethereum/go-ethereum v1.15.5/go.mod h1:1LG2LnMOx2yPRHR/S+xuipXH29vPr6BIH6GElD8N/fo= +github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= +github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/ethereum/c-kzg-4844/v2 v2.1.0 h1:gQropX9YFBhl3g4HYhwE70zq3IHFRgbbNPw0Shwzf5w= +github.com/ethereum/c-kzg-4844/v2 v2.1.0/go.mod h1:TC48kOKjJKPbN7C++qIgt0TJzZ70QznYR7Ob+WXl57E= +github.com/ethereum/go-ethereum v1.15.11 h1:JK73WKeu0WC0O1eyX+mdQAVHUV+UR1a9VB/domDngBU= +github.com/ethereum/go-ethereum v1.15.11/go.mod h1:mf8YiHIb0GR4x4TipcvBUPxJLw1mFdmxzoDi11sDRoI= github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -251,50 +301,51 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8 github.com/getsentry/sentry-go v0.33.0 h1:YWyDii0KGVov3xOaamOnF0mjOrqSjBqwv48UEzn7QFg= github.com/getsentry/sentry-go v0.33.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= +github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= @@ -305,9 +356,13 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= @@ -347,7 +402,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -358,11 +412,16 @@ github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= +github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= +github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= @@ -388,8 +447,14 @@ github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NM github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter v1.7.8 h1:mshVHx1Fto0/MydBekWan5zUipGq7jO0novchgMmSiY= +github.com/hashicorp/go-getter v1.7.8/go.mod h1:2c6CboOEb9jG6YvmC9xdD+tyAFsrUaJPedwXDGr0TM4= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -403,6 +468,8 @@ github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0U github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -410,6 +477,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -425,6 +494,10 @@ github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8 github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -433,6 +506,8 @@ github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0Jr github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -442,9 +517,13 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -455,8 +534,6 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -486,7 +563,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= @@ -516,29 +592,31 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 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/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -580,8 +658,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= +github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -613,12 +691,24 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= +github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= +github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= +github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= +github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -676,6 +766,7 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= 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/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= @@ -708,10 +799,13 @@ github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= +github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= +github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -741,6 +835,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= 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/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -760,15 +856,22 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1 github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/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.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= +github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= +github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= @@ -780,18 +883,26 @@ go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mI go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= +go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -811,6 +922,10 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -821,8 +936,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= @@ -868,11 +983,13 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= 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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -881,8 +998,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -899,6 +1016,7 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -925,7 +1043,6 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -934,25 +1051,30 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/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.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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= @@ -979,6 +1101,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.222.0 h1:Aiewy7BKLCuq6cUCeOUrsAlzjXPqBkEeQ/iwGHVQa/4= +google.golang.org/api v0.222.0/go.mod h1:efZia3nXpWELrwMlN5vyQrD4GmJN1Vw0x68Et3r+a9c= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1016,8 +1140,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1032,8 +1156,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 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.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 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= @@ -1045,6 +1169,8 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= 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= @@ -1069,14 +1195,13 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= +nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tests/systemtests/mempool/interface.go b/tests/systemtests/mempool/interface.go new file mode 100644 index 000000000..87834d2f1 --- /dev/null +++ b/tests/systemtests/mempool/interface.go @@ -0,0 +1,45 @@ +package mempool + +import ( + "math/big" + "testing" + "time" + + "github.com/cosmos/evm/tests/systemtests/suite" +) + +type TestSuite interface { + // Test Lifecycle + BeforeEachCase(t *testing.T) + AfterEachCase(t *testing.T) + AfterEachAction(t *testing.T) + + // Tx + SendTx(t *testing.T, nodeID string, accID string, nonceIdx uint64, gasPrice *big.Int, gasTipCap *big.Int) (*suite.TxInfo, error) + SendEthTx(t *testing.T, nodeID string, accID string, nonceIdx uint64, gasPrice *big.Int, gasTipCap *big.Int) (*suite.TxInfo, error) + SendEthLegacyTx(t *testing.T, nodeID string, accID string, nonceIdx uint64, gasPrice *big.Int) (*suite.TxInfo, error) + SendEthDynamicFeeTx(t *testing.T, nodeID string, accID string, nonceIdx uint64, gasPrice *big.Int, gasTipCap *big.Int) (*suite.TxInfo, error) + SendCosmosTx(t *testing.T, nodeID string, accID string, nonceIdx uint64, gasPrice *big.Int, gasTipCap *big.Int) (*suite.TxInfo, error) + + // Query + BaseFee() *big.Int + BaseFeeX2() *big.Int + WaitForCommit(nodeID string, txHash string, txType string, timeout time.Duration) error + TxPoolContent(nodeID string, txType string) (pendingTxs, queuedTxs []string, err error) + + // Config + GetOptions() *suite.TestOptions + Nodes() []string + Node(idx int) string + Acc(idx int) string + + // Expectation of mempool state + GetExpPendingTxs() []*suite.TxInfo + SetExpPendingTxs(txs ...*suite.TxInfo) + GetExpQueuedTxs() []*suite.TxInfo + SetExpQueuedTxs(txs ...*suite.TxInfo) + PromoteExpTxs(count int) + + // Test Utils + AwaitNBlocks(t *testing.T, n int64, duration ...time.Duration) +} diff --git a/tests/systemtests/mempool/test_exceptions.go b/tests/systemtests/mempool/test_exceptions.go new file mode 100644 index 000000000..87ec31741 --- /dev/null +++ b/tests/systemtests/mempool/test_exceptions.go @@ -0,0 +1,154 @@ +package mempool + +import ( + "fmt" + "testing" + + "github.com/cosmos/evm/tests/systemtests/suite" + "github.com/test-go/testify/require" +) + +func TestTxRebroadcasting(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + bypass bool + }{ + { + name: "ordering of pending txs %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + tx2, err := s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + tx3, err := s.SendTx(t, s.Node(2), "acc0", 2, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + // Skip tx4 with nonce 3 + + tx5, err := s.SendTx(t, s.Node(3), "acc0", 4, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + tx6, err := s.SendTx(t, s.Node(0), "acc0", 5, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + // At AfterEachAction hook, we will check expected queued txs are not broadcasted. + s.SetExpPendingTxs(tx1, tx2, tx3) + s.SetExpQueuedTxs(tx5, tx6) + }, + func(s TestSuite) { + // Wait for 3 blocks. + // It is because tx1, tx2, tx3 are sent to different nodes, tx3 needs maximum 3 blocks to be committed. + // e.g. node3 is 1st proposer -> tx3 will tale 1 block to be committed. + // e.g. node3 is 3rd proposer -> tx3 will take 3 blocks to be committed. + s.AwaitNBlocks(t, 3) + + // current nonce is 3. + // so, we should set nonce idx to 0. + nonce3Idx := uint64(0) + + tx4, err := s.SendTx(t, s.Node(2), "acc0", nonce3Idx, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + // At AfterEachAction hook, we will check expected pending txs are broadcasted. + s.SetExpPendingTxs(tx4) + s.PromoteExpTxs(2) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "EVM LegacyTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: false, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t) + + for _, to := range testOptions { + s.SetOptions(to) + for _, tc := range testCases { + testName := fmt.Sprintf(tc.name, to.Description) + t.Run(testName, func(t *testing.T) { + if tc.bypass { + return + } + + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) + } + s.AfterEachCase(t) + }) + } + } +} + +func TestMinimumGasPricesZero(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + bypass bool + }{ + { + name: "sequencial pending txs %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + tx2, err := s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + tx3, err := s.SendTx(t, s.Node(2), "acc0", 2, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx1, tx2, tx3) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "EVM LegacyTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: false, + }, + { + Description: "EVM DynamicFeeTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: true, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t, suite.MinimumGasPriceZeroArgs()...) + + for _, to := range testOptions { + s.SetOptions(to) + for _, tc := range testCases { + testName := fmt.Sprintf(tc.name, to.Description) + t.Run(testName, func(t *testing.T) { + if tc.bypass { + return + } + + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) + } + s.AfterEachCase(t) + }) + } + } +} diff --git a/tests/systemtests/mempool/test_ordering.go b/tests/systemtests/mempool/test_ordering.go new file mode 100644 index 000000000..4e92bc01c --- /dev/null +++ b/tests/systemtests/mempool/test_ordering.go @@ -0,0 +1,82 @@ +package mempool + +import ( + "fmt" + "math/big" + "testing" + + "github.com/cosmos/evm/tests/systemtests/suite" + "github.com/test-go/testify/require" +) + +func TestTxsOrdering(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + bypass bool + }{ + { + name: "ordering of pending txs %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + expPendingTxs := make([]*suite.TxInfo, 5) + for i := 0; i < 5; i++ { + // nonce order of submitted txs: 3,4,0,1,2 + nonceIdx := uint64((i + 3) % 5) + + // For cosmos tx, we should send tx to one node. + // Because cosmos pool does not manage queued txs. + nodeId := "node0" + if s.GetOptions().TxType == suite.TxTypeEVM { + // target node order of submitted txs: 0,1,2,3,0 + nodeId = s.Node(i % 4) + } + + txInfo, err := s.SendTx(t, nodeId, "acc0", nonceIdx, s.BaseFee(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + // nonce order of committed txs: 0,1,2,3,4 + expPendingTxs[nonceIdx] = txInfo + } + + s.SetExpPendingTxs(expPendingTxs...) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "EVM LegacyTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: false, + }, + { + Description: "EVM DynamicFeeTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: true, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t) + + for _, to := range testOptions { + s.SetOptions(to) + for _, tc := range testCases { + testName := fmt.Sprintf(tc.name, to.Description) + t.Run(testName, func(t *testing.T) { + if tc.bypass { + return + } + + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) + } + s.AfterEachCase(t) + }) + } + } +} diff --git a/tests/systemtests/mempool/test_replacement.go b/tests/systemtests/mempool/test_replacement.go new file mode 100644 index 000000000..dd53efcd2 --- /dev/null +++ b/tests/systemtests/mempool/test_replacement.go @@ -0,0 +1,425 @@ +package mempool + +import ( + "fmt" + "math/big" + "testing" + + "github.com/cosmos/evm/tests/systemtests/suite" + "github.com/test-go/testify/require" +) + +func TestTxsReplacement(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + bypass bool + }{ + { + name: "single pending tx submitted to same nodes %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx2) + }, + }, + bypass: true, + }, + { + name: "multiple pending txs submitted to same nodes %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + _, err = s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx4, err := s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + _, err = s.SendTx(t, s.Node(2), "acc0", 2, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx6, err := s.SendTx(t, s.Node(2), "acc0", 2, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx2, tx4, tx6) + }, + }, + bypass: true, + }, + { + name: "single queued tx %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpQueuedTxs(tx2) + }, + func(s TestSuite) { + txHash, err := s.SendTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(txHash) + s.PromoteExpTxs(1) + }, + }, + }, + { + name: "multiple queued txs %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + _, err = s.SendTx(t, s.Node(1), "acc0", 2, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx4, err := s.SendTx(t, s.Node(1), "acc0", 2, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + _, err = s.SendTx(t, s.Node(2), "acc0", 3, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx6, err := s.SendTx(t, s.Node(2), "acc0", 3, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpQueuedTxs(tx2, tx4, tx6) + }, + func(s TestSuite) { + tx, err := s.SendTx(t, s.Node(3), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx) + s.PromoteExpTxs(3) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "EVM LegacyTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: false, + }, + { + Description: "EVM DynamicFeeTx", + TxType: suite.TxTypeEVM, + IsDynamicFeeTx: true, + }, + { + Description: "Cosmos LegacyTx", + TxType: suite.TxTypeCosmos, + IsDynamicFeeTx: false, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t) + + for _, to := range testOptions { + s.SetOptions(to) + for _, tc := range testCases { + testName := fmt.Sprintf(tc.name, to.Description) + t.Run(testName, func(t *testing.T) { + if tc.bypass { + return + } + + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) + } + s.AfterEachCase(t) + }) + } + } +} + +func TestMixedTxsReplacementEVMAndCosmos(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + bypass bool + }{ + { + name: "single pending tx (low prio evm tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx2) + }, + }, + bypass: true, + }, + { + name: "single pending tx (high prio evm tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + _, err = s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx1) + }, + }, + bypass: true, + }, + { + name: "single pending tx (low prio cosmos tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx2) + }, + }, + bypass: true, + }, + { + name: "single pending tx (high prio cosmos tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + _, err = s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx1) + }, + }, + bypass: true, + }, + { + name: "single queued tx (low prio evm tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendEthTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendCosmosTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + // CosmosTx is not queued in local mempool + s.SetExpQueuedTxs(tx1) + }, + func(s TestSuite) { + tx3, err := s.SendEthTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx3) + s.PromoteExpTxs(1) + }, + }, + }, + { + name: "single queued tx (high prio evm tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendEthTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + _, err = s.SendCosmosTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + // CosmosTx is not queued in local mempool + s.SetExpQueuedTxs(tx1) + }, + func(s TestSuite) { + tx3, err := s.SendEthTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx3) + s.PromoteExpTxs(1) + }, + }, + }, + { + name: "single queued tx (low prio cosmos tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendCosmosTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendEthTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + // CosmosTx is not queued in local mempool + s.SetExpQueuedTxs(tx2) + }, + func(s TestSuite) { + tx3, err := s.SendEthTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx3) + s.PromoteExpTxs(1) + }, + }, + }, + { + name: "single queued tx (high prio cosmos tx first) %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendCosmosTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + tx2, err := s.SendEthTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + // CosmosTx is not queued in local mempool + s.SetExpQueuedTxs(tx2) + }, + func(s TestSuite) { + tx3, err := s.SendEthTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx3) + s.PromoteExpTxs(1) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "EVM LegacyTx & Cosmos LegacyTx", + }, + { + Description: "EVM DynamicTx & Cosmos LegacyTx", + IsDynamicFeeTx: true, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t) + + for _, to := range testOptions { + s.SetOptions(to) + for _, tc := range testCases { + testName := fmt.Sprintf(tc.name, to.Description) + t.Run(testName, func(t *testing.T) { + if tc.bypass { + return + } + + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) + } + s.AfterEachCase(t) + }) + } + } +} + +func TestMixedTxsReplacementLegacyAndDynamicFee(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + bypass bool + }{ + { + name: "dynamic fee tx should not replace legacy tx", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 1, s.BaseFee()) + require.NoError(t, err, "failed to send eth legacy tx") + + _, err = s.SendEthDynamicFeeTx(t, s.Node(0), s.Acc(0), 1, s.BaseFeeX2(), big.NewInt(1)) + require.Error(t, err) + require.Contains(t, err.Error(), "replacement transaction underpriced") + + s.SetExpQueuedTxs(tx1) + }, + func(s TestSuite) { + txHash, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 0, s.BaseFee()) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(txHash) + s.PromoteExpTxs(1) + }, + }, + }, + { + name: "dynamic fee tx should replace legacy tx", + actions: []func(s TestSuite){ + func(s TestSuite) { + _, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 1, s.BaseFee()) + require.NoError(t, err, "failed to send eth legacy tx") + + tx2, err := s.SendEthDynamicFeeTx(t, s.Node(0), s.Acc(0), 1, + s.BaseFeeX2(), + s.BaseFeeX2(), + ) + require.NoError(t, err) + + s.SetExpQueuedTxs(tx2) + }, + func(s TestSuite) { + txHash, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 0, s.BaseFee()) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(txHash) + s.PromoteExpTxs(1) + }, + }, + }, + { + name: "legacy should never replace dynamic fee tx", + actions: []func(s TestSuite){ + func(s TestSuite) { + tx1, err := s.SendEthDynamicFeeTx(t, s.Node(0), s.Acc(0), 1, s.BaseFeeX2(), + new(big.Int).Sub(s.BaseFee(), big.NewInt(1))) + require.NoError(t, err) + + _, err = s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 1, s.BaseFee()) + require.Error(t, err, "failed to send eth legacy tx") + require.Contains(t, err.Error(), "replacement transaction underpriced") + + // Legacy tx cannot replace dynamic fee tx. + s.SetExpQueuedTxs(tx1) + }, + func(s TestSuite) { + txHash, err := s.SendEthLegacyTx(t, s.Node(0), s.Acc(0), 0, s.BaseFee()) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(txHash) + s.PromoteExpTxs(1) + }, + }, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.bypass { + return + } + + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) + } + s.AfterEachCase(t) + }) + } +} diff --git a/tests/systemtests/mempool_test.go b/tests/systemtests/mempool_test.go new file mode 100644 index 000000000..e342a65fc --- /dev/null +++ b/tests/systemtests/mempool_test.go @@ -0,0 +1,24 @@ +//go:build system_test + +package systemtests + +import ( + "testing" + + "github.com/cosmos/evm/tests/systemtests/mempool" +) + +func TestTxsOrdering(t *testing.T) { + mempool.TestTxsOrdering(t) +} + +func TestTxsReplacement(t *testing.T) { + mempool.TestTxsReplacement(t) + mempool.TestMixedTxsReplacementEVMAndCosmos(t) + mempool.TestMixedTxsReplacementLegacyAndDynamicFee(t) +} + +func TestExceptions(t *testing.T) { + mempool.TestTxRebroadcasting(t) + mempool.TestMinimumGasPricesZero(t) +} diff --git a/tests/systemtests/suite/query.go b/tests/systemtests/suite/query.go new file mode 100644 index 000000000..5b3d885cf --- /dev/null +++ b/tests/systemtests/suite/query.go @@ -0,0 +1,179 @@ +package suite + +import ( + "fmt" + "maps" + "math/big" + "slices" + "time" + + "github.com/cosmos/evm/tests/systemtests/clients" +) + +// NonceAt returns the account nonce for the given account at the latest block +func (s *SystemTestSuite) NonceAt(nodeID string, accID string) (uint64, error) { + ctx, cli, addr := s.EthClient.Setup(nodeID, accID) + blockNumber, err := s.EthClient.Clients[nodeID].BlockNumber(ctx) + if err != nil { + return uint64(0), fmt.Errorf("failed to get block number from %s: %v", nodeID, err) + } + if int64(blockNumber) < 0 { + return uint64(0), fmt.Errorf("invaid block number %d", blockNumber) + } + return cli.NonceAt(ctx, addr, big.NewInt(int64(blockNumber))) +} + +// GetLatestBaseFee returns the base fee of the latest block +func (s *SystemTestSuite) GetLatestBaseFee(nodeID string) (*big.Int, error) { + ctx, cli, _ := s.EthClient.Setup(nodeID, "acc0") + blockNumber, err := cli.BlockNumber(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get block number from %s: %v", nodeID, err) + } + if int64(blockNumber) < 0 { + return nil, fmt.Errorf("invaid block number %d", blockNumber) + } + + block, err := cli.BlockByNumber(ctx, big.NewInt(int64(blockNumber))) + if err != nil { + return nil, fmt.Errorf("failed to get block from %s: %v", nodeID, err) + } + + if block.BaseFee().Cmp(big.NewInt(0)) <= 0 { + return nil, fmt.Errorf("failed to get block from %s: %v", nodeID, err) + } + + return block.BaseFee(), nil +} + +// BaseFee returns the base fee of the latest block +func (s *SystemTestSuite) WaitForCommit( + nodeID string, + txHash string, + txType string, + timeout time.Duration, +) error { + switch txType { + case TxTypeEVM: + return s.waitForEthCommmit(nodeID, txHash, timeout) + case TxTypeCosmos: + return s.waitForCosmosCommmit(nodeID, txHash, timeout) + default: + return fmt.Errorf("invalid txtype: %s", txType) + } +} + +// waitForEthCommmit waits for the given eth tx to be committed within the timeout duration +func (s *SystemTestSuite) waitForEthCommmit( + nodeID string, + txHash string, + timeout time.Duration, +) error { + receipt, err := s.EthClient.WaitForCommit(nodeID, txHash, timeout) + if err != nil { + return fmt.Errorf("failed to get receipt for tx(%s): %v", txHash, err) + } + + if receipt.Status != 1 { + return fmt.Errorf("tx(%s) is committed but failed: %v", txHash, err) + } + + return nil +} + +// waitForCosmosCommmit waits for the given cosmos tx to be committed within the timeout duration +func (s *SystemTestSuite) waitForCosmosCommmit( + nodeID string, + txHash string, + timeout time.Duration, +) error { + result, err := s.CosmosClient.WaitForCommit(nodeID, txHash, timeout) + if err != nil { + return fmt.Errorf("failed to get receipt for tx(%s): %v", txHash, err) + } + + if result.TxResult.Code != 0 { + return fmt.Errorf("tx(%s) is committed but failed: %v", result.Hash.String(), err) + } + + return nil +} + +// CheckTxsPending checks if the given tx is either pending or committed within the timeout duration +func (s *SystemTestSuite) CheckTxPending( + nodeID string, + txHash string, + txType string, + timeout time.Duration, +) error { + switch txType { + case TxTypeEVM: + return s.EthClient.CheckTxsPending(nodeID, txHash, timeout) + case TxTypeCosmos: + return s.CosmosClient.CheckTxsPending(nodeID, txHash, timeout) + default: + return fmt.Errorf("invalid tx type") + } +} + +// TxPoolContent returns the pending and queued tx hashes in the tx pool of the given node +func (s *SystemTestSuite) TxPoolContent(nodeID string, txType string) (pendingTxs, queuedTxs []string, err error) { + switch txType { + case TxTypeEVM: + return s.ethTxPoolContent(nodeID) + case TxTypeCosmos: + return s.cosmosTxPoolContent(nodeID) + default: + return nil, nil, fmt.Errorf("invalid tx type") + } +} + +// ethTxPoolContent returns the pending and queued tx hashes in the tx pool of the given node +func (s *SystemTestSuite) ethTxPoolContent(nodeID string) (pendingTxHashes, queuedTxHashes []string, err error) { + pendingTxs, queuedTxs, err := s.EthClient.TxPoolContent(nodeID) + if err != nil { + return nil, nil, fmt.Errorf("failed to get txpool content from eth client: %v", err) + } + + return s.extractTxHashesSorted(pendingTxs), s.extractTxHashesSorted(queuedTxs), nil +} + +// cosmosTxPoolContent returns the pending tx hashes in the tx pool of the given node +func (s *SystemTestSuite) cosmosTxPoolContent(nodeID string) (pendingTxHashes, queuedTxHashes []string, err error) { + result, err := s.CosmosClient.UnconfirmedTxs(nodeID) + if err != nil { + return nil, nil, fmt.Errorf("failed to call unconfired transactions from cosmos client: %v", err) + } + + pendingtxHashes := make([]string, 0) + for _, tx := range result.Txs { + pendingtxHashes = append(pendingtxHashes, tx.Hash().String()) + } + + return pendingtxHashes, nil, nil +} + +// extractTxHashesSorted processes transaction maps in a deterministic order and returns flat slice of tx hashes +func (s *SystemTestSuite) extractTxHashesSorted(txMap map[string]map[string]*clients.EthRPCTransaction) []string { + var result []string + + // Get addresses and sort them for deterministic iteration + addresses := slices.Collect(maps.Keys(txMap)) + slices.Sort(addresses) + + // Process addresses in sorted order + for _, addr := range addresses { + txs := txMap[addr] + + // Sort transactions by nonce for deterministic ordering + nonces := slices.Collect(maps.Keys(txs)) + slices.Sort(nonces) + + // Add transaction hashes to flat result slice + for _, nonce := range nonces { + result = append(result, txs[nonce].Hash.Hex()) + } + } + + return result +} diff --git a/tests/systemtests/suite/test_helpers.go b/tests/systemtests/suite/test_helpers.go new file mode 100644 index 000000000..bdaff5b2c --- /dev/null +++ b/tests/systemtests/suite/test_helpers.go @@ -0,0 +1,172 @@ +package suite + +import ( + "fmt" + "math/big" + "slices" + "sync" + "time" +) + +// BaseFee returns the most recently retrieved and stored baseFee. +func (s *SystemTestSuite) BaseFee() *big.Int { + return s.baseFee +} + +// BaseFeeX2 returns the double of the most recently retrieved and stored baseFee. +func (s *SystemTestSuite) BaseFeeX2() *big.Int { + return new(big.Int).Mul(s.baseFee, big.NewInt(2)) +} + +// GetExpPendingTxs returns the expected pending transactions +func (s *SystemTestSuite) GetExpPendingTxs() []*TxInfo { + return s.expPendingTxs +} + +// SetExpPendingTxs sets the expected pending transactions +func (s *SystemTestSuite) SetExpPendingTxs(txs ...*TxInfo) { + s.expPendingTxs = txs +} + +// GetExpQueuedTxs returns the expected queued transactions +func (s *SystemTestSuite) GetExpQueuedTxs() []*TxInfo { + return s.expQueuedTxs +} + +// SetExpQueuedTxs sets the expected queued transactions, filtering out any Cosmos transactions +func (s *SystemTestSuite) SetExpQueuedTxs(txs ...*TxInfo) { + queuedTxs := make([]*TxInfo, 0) + for _, txInfo := range txs { + if txInfo.TxType == TxTypeCosmos { + continue + } + queuedTxs = append(queuedTxs, txInfo) + } + s.expQueuedTxs = queuedTxs +} + +// PromoteExpTxs promotes the given number of expected queued transactions to expected pending transactions +func (s *SystemTestSuite) PromoteExpTxs(count int) { + if count <= 0 || len(s.expQueuedTxs) == 0 { + return + } + + // Ensure we don't try to promote more than available + actualCount := count + if actualCount > len(s.expQueuedTxs) { + actualCount = len(s.expQueuedTxs) + } + + // Pop from expQueuedTxs and push to expPendingTxs + txs := s.expQueuedTxs[:actualCount] + s.expPendingTxs = append(s.expPendingTxs, txs...) + s.expQueuedTxs = s.expQueuedTxs[actualCount:] +} + +// Nodes returns the node IDs in the system under test +func (s *SystemTestSuite) Nodes() []string { + nodes := make([]string, 4) + for i := 0; i < 4; i++ { + nodes[i] = fmt.Sprintf("node%d", i) + } + return nodes +} + +// Node returns the node ID for the given index +func (s *SystemTestSuite) Node(idx int) string { + return fmt.Sprintf("node%d", idx) +} + +// Acc returns the account ID for the given index +func (s *SystemTestSuite) Acc(idx int) string { + return fmt.Sprintf("acc%d", idx) +} + +// GetOptions returns the current test options +func (s *SystemTestSuite) GetOptions() *TestOptions { + return s.options +} + +// SetOptions sets the current test options +func (s *SystemTestSuite) SetOptions(options *TestOptions) { + s.options = options +} + +// CheckTxsPendingAsync verifies that the expected pending transactions are still pending in the mempool. +// The check runs asynchronously because, if done synchronously, the pending transactions +// might be committed before the verification takes place. +func (s *SystemTestSuite) CheckTxsPendingAsync(expPendingTxs []*TxInfo) error { + if len(expPendingTxs) == 0 { + return nil + } + + // Use mutex to ensure thread-safe error collection + var mu sync.Mutex + var errors []error + var wg sync.WaitGroup + + for _, txInfo := range expPendingTxs { + wg.Add(1) + go func(tx *TxInfo) { //nolint:gosec // Concurrency is intentional for parallel tx checking + defer wg.Done() + err := s.CheckTxPending(tx.DstNodeID, tx.TxHash, tx.TxType, time.Second*30) + if err != nil { + mu.Lock() + errors = append(errors, fmt.Errorf("tx %s is not pending or committed: %v", tx.TxHash, err)) + mu.Unlock() + } + }(txInfo) + } + + wg.Wait() + + // Return the first error if any occurred + if len(errors) > 0 { + return fmt.Errorf("failed to check transactions are pending status: %w", errors[0]) + } + + return nil +} + +// CheckTxsQueuedSync verifies that the expected queued transactions are actually queued and not pending in the mempool. +func (s *SystemTestSuite) CheckTxsQueuedSync(expQueuedTxs []*TxInfo) error { + pendingHashes := make([][]string, len(s.Nodes())) + queuedHashes := make([][]string, len(s.Nodes())) + for i := range s.Nodes() { + pending, queued, err := s.TxPoolContent(s.Node(i), TxTypeEVM) + if err != nil { + return fmt.Errorf("failed to call txpool_content api") + } + queuedHashes[i] = queued + pendingHashes[i] = pending + } + + for _, txInfo := range s.GetExpQueuedTxs() { + if txInfo.TxType != TxTypeEVM { + panic("queued txs should be only EVM txs") + } + + for i := range s.Nodes() { + pendingTxHashes := pendingHashes[i] + queuedTxHashes := queuedHashes[i] + + if s.Node(i) == txInfo.DstNodeID { + if ok := slices.Contains(pendingTxHashes, txInfo.TxHash); ok { + return fmt.Errorf("tx %s is pending but actually it should be queued.", txInfo.TxHash) + } + if ok := slices.Contains(queuedTxHashes, txInfo.TxHash); !ok { + return fmt.Errorf("tx %s is not contained in queued txs in mempool", txInfo.TxHash) + } + } else { + if ok := slices.Contains(pendingTxHashes, txInfo.TxHash); ok { + return fmt.Errorf("Locally queued transaction %s is also found in the pending transactions of another node's mempool", txInfo.TxHash) + } + if ok := slices.Contains(queuedTxHashes, txInfo.TxHash); ok { + return fmt.Errorf("Locally queued transaction %s is also found in the queued transactions of another node's mempool", txInfo.TxHash) + } + } + } + } + + return nil +} diff --git a/tests/systemtests/suite/test_suite.go b/tests/systemtests/suite/test_suite.go new file mode 100644 index 000000000..4f64e42f1 --- /dev/null +++ b/tests/systemtests/suite/test_suite.go @@ -0,0 +1,117 @@ +package suite + +import ( + "math/big" + "testing" + "time" + + "cosmossdk.io/systemtests" + "github.com/cosmos/evm/tests/systemtests/clients" + "github.com/stretchr/testify/require" +) + +// SystemTestSuite implements the TestSuite interface and +// provides methods for managing test lifecycle, +// sending transactions, querying state, +// and managing expected mempool state. +type SystemTestSuite struct { + *systemtests.SystemUnderTest + options *TestOptions + + // Clients + EthClient *clients.EthClient + CosmosClient *clients.CosmosClient + + // Most recently retrieved base fee + baseFee *big.Int + + // Expected transaction hashes + expPendingTxs []*TxInfo + expQueuedTxs []*TxInfo +} + +func NewSystemTestSuite(t *testing.T) *SystemTestSuite { + ethClient, err := clients.NewEthClient() + require.NoError(t, err) + + cosmosClient, err := clients.NewCosmosClient() + require.NoError(t, err) + + return &SystemTestSuite{ + SystemUnderTest: systemtests.Sut, + EthClient: ethClient, + CosmosClient: cosmosClient, + } +} + +// SetupTest initializes the test suite by resetting and starting the chain, then awaiting 2 blocks +func (s *SystemTestSuite) SetupTest(t *testing.T, nodeStartArgs ...string) { + if len(nodeStartArgs) == 0 { + nodeStartArgs = DefaultNodeArgs() + } + + s.ResetChain(t) + s.StartChain(t, nodeStartArgs...) + s.AwaitNBlocks(t, 2) +} + +// BeforeEach resets the expected mempool state and retrieves the current base fee before each test case +func (s *SystemTestSuite) BeforeEachCase(t *testing.T) { + // Reset expected pending/queued transactions + s.SetExpPendingTxs() + s.SetExpQueuedTxs() + + // Get current base fee + currentBaseFee, err := s.GetLatestBaseFee("node0") + require.NoError(t, err) + + s.baseFee = currentBaseFee +} + +// JustAfterEach checks the expected mempool state right after each test case +func (s *SystemTestSuite) AfterEachAction(t *testing.T) { + // Check pending txs exist in mempool or already committed - concurrently + err := s.CheckTxsPendingAsync(s.GetExpPendingTxs()) + require.NoError(t, err) + + // Check queued txs only exist in local mempool (queued txs should be only EVM txs) + err = s.CheckTxsQueuedSync(s.GetExpQueuedTxs()) + require.NoError(t, err) + + // Wait for block commit + s.AwaitNBlocks(t, 1) + + // Get current base fee and set it to suite.baseFee + currentBaseFee, err := s.GetLatestBaseFee("node0") + require.NoError(t, err) + + s.baseFee = currentBaseFee +} + +// AfterEach waits for all expected pending transactions to be committed +func (s *SystemTestSuite) AfterEachCase(t *testing.T) { + // Check all expected pending txs are committed + for _, txInfo := range s.GetExpPendingTxs() { + err := s.WaitForCommit(txInfo.DstNodeID, txInfo.TxHash, txInfo.TxType, time.Second*15) + require.NoError(t, err) + } + + // Check all evm pending txs are cleared in mempool + for i := range s.Nodes() { + pending, _, err := s.TxPoolContent(s.Node(i), TxTypeEVM) + require.NoError(t, err) + + require.Len(t, pending, 0, "pending txs are not cleared in mempool") + } + + // Check all cosmos pending txs are cleared in mempool + for i := range s.Nodes() { + pending, _, err := s.TxPoolContent(s.Node(i), TxTypeCosmos) + require.NoError(t, err) + + require.Len(t, pending, 0, "pending txs are not cleared in mempool") + } + + // Wait for block commit + s.AwaitNBlocks(t, 1) +} diff --git a/tests/systemtests/suite/tx.go b/tests/systemtests/suite/tx.go new file mode 100644 index 000000000..78a90f13b --- /dev/null +++ b/tests/systemtests/suite/tx.go @@ -0,0 +1,128 @@ +package suite + +import ( + "fmt" + "math/big" + "testing" + + sdkmath "cosmossdk.io/math" + ethtypes "github.com/ethereum/go-ethereum/core/types" +) + +// GetOptions retrieves the current test options. +func (s *SystemTestSuite) SendTx( + t *testing.T, + nodeID string, + accID string, + nonceIdx uint64, + gasPrice *big.Int, + gasTipCap *big.Int, +) (*TxInfo, error) { + options := s.GetOptions() + if options != nil && options.TxType == TxTypeCosmos { + return s.SendCosmosTx(t, nodeID, accID, nonceIdx, gasPrice, nil) + } + return s.SendEthTx(t, nodeID, accID, nonceIdx, gasPrice, gasTipCap) +} + +// SendEthTx sends an Ethereum transaction (either Legacy or Dynamic Fee based on options). +func (s *SystemTestSuite) SendEthTx( + t *testing.T, + nodeID string, + accID string, + nonceIdx uint64, + gasPrice *big.Int, + gasTipCap *big.Int, +) (*TxInfo, error) { + options := s.GetOptions() + if options != nil && options.IsDynamicFeeTx { + return s.SendEthDynamicFeeTx(t, nodeID, accID, nonceIdx, gasPrice, gasTipCap) + } + return s.SendEthLegacyTx(t, nodeID, accID, nonceIdx, gasPrice) +} + +// SendEthLegacyTx sends an Ethereum legacy transaction. +func (s *SystemTestSuite) SendEthLegacyTx( + t *testing.T, + nodeID string, + accID string, + nonceIdx uint64, + gasPrice *big.Int, +) (*TxInfo, error) { + nonce, err := s.NonceAt(nodeID, accID) + if err != nil { + return nil, fmt.Errorf("failed to get current nonce: %v", err) + } + gappedNonce := nonce + nonceIdx + to := s.EthClient.Accs["acc3"].Address + value := big.NewInt(1000) + gasLimit := uint64(50_000) + + tx := ethtypes.NewTransaction(gappedNonce, to, value, gasLimit, gasPrice, nil) + txHash, err := s.EthClient.SendRawTransaction(nodeID, accID, tx) + if err != nil { + return nil, fmt.Errorf("failed to send eth legacy tx: %v", err) + } + + return NewTxInfo(nodeID, txHash.Hex(), TxTypeEVM), nil +} + +// SendEthDynamicFeeTx sends an Ethereum dynamic fee transaction. +func (s *SystemTestSuite) SendEthDynamicFeeTx( + t *testing.T, + nodeID string, + accID string, + nonceIdx uint64, + gasFeeCap *big.Int, + gasTipCap *big.Int, +) (*TxInfo, error) { + nonce, err := s.NonceAt(nodeID, accID) + if err != nil { + return nil, fmt.Errorf("failed to get current nonce: %v", err) + } + gappedNonce := nonce + nonceIdx + + tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{ + ChainID: s.EthClient.ChainID, + Nonce: gappedNonce, + To: &(s.EthClient.Accs["acc3"].Address), + Value: big.NewInt(1000), + Gas: uint64(50_000), + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + }) + + txHash, err := s.EthClient.SendRawTransaction(nodeID, accID, tx) + if err != nil { + return nil, fmt.Errorf("failed to send eth dynamic fee tx: %v", err) + } + + return NewTxInfo(nodeID, txHash.Hex(), TxTypeEVM), nil +} + +// SendCosmosTx sends a Cosmos transaction. +func (s *SystemTestSuite) SendCosmosTx( + t *testing.T, + nodeID string, + accID string, + nonceIdx uint64, + gasPrice *big.Int, + gasTipCap *big.Int, +) (*TxInfo, error) { + from := s.CosmosClient.Accs[accID].AccAddress + to := s.CosmosClient.Accs["acc3"].AccAddress + amount := sdkmath.NewInt(1000) + + nonce, err := s.NonceAt(nodeID, accID) + if err != nil { + return nil, fmt.Errorf("failed to get current nonce: %v", err) + } + gappedNonce := nonce + nonceIdx + + resp, err := s.CosmosClient.BankSend(nodeID, accID, from, to, amount, gappedNonce, gasPrice) + if err != nil { + return nil, fmt.Errorf("failed to send cosmos bank send tx: %v", err) + } + + return NewTxInfo(nodeID, resp.TxHash, TxTypeCosmos), nil +} diff --git a/tests/systemtests/suite/types.go b/tests/systemtests/suite/types.go new file mode 100644 index 000000000..ee7e31c3f --- /dev/null +++ b/tests/systemtests/suite/types.go @@ -0,0 +1,49 @@ +package suite + +const ( + TxTypeEVM = "EVMTx" + TxTypeCosmos = "CosmosTx" + + NodeArgsChainID = "--chain-id=local-4221" + NodeArgsApiEnable = "--api.enable=true" + NodeArgsJsonrpcApi = "--json-rpc.api=eth,txpool,personal,net,debug,web3" + NodeArgsJsonrpcAllowUnprotectedTxs = "--json-rpc.allow-unprotected-txs=true" +) + +// TestOptions defines the options for a test case. +type TestOptions struct { + Description string + TxType string + IsDynamicFeeTx bool +} + +// TxInfo holds information about a transaction. +type TxInfo struct { + DstNodeID string + TxType string + TxHash string +} + +// NewTxInfo creates a new TxInfo instance. +func NewTxInfo(nodeID, txHash, txType string) *TxInfo { + return &TxInfo{ + DstNodeID: nodeID, + TxHash: txHash, + TxType: txType, + } +} + +// DefaultNodeArgs returns the default node arguments for starting the chain. +func DefaultNodeArgs() []string { + return []string{ + NodeArgsJsonrpcApi, + NodeArgsChainID, + NodeArgsApiEnable, + NodeArgsJsonrpcAllowUnprotectedTxs, + } +} + +// MinimumGasPriceZeroArgs returns the node arguments with minimum gas price set to zero. +func MinimumGasPriceZeroArgs() []string { + return append(DefaultNodeArgs(), "--minimum-gas-prices=0stake") +} diff --git a/tests/systemtests/upgrade_test.go b/tests/systemtests/upgrade_test.go new file mode 100644 index 000000000..9ae700e88 --- /dev/null +++ b/tests/systemtests/upgrade_test.go @@ -0,0 +1,102 @@ +//go:build system_test + +package systemtests + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" +) + +const ( + upgradeHeight int64 = 22 + upgradeName = "v0.4.0-to-v0.5.0" // must match UpgradeName in evmd/upgrades.go +) + +func TestChainUpgrade(t *testing.T) { + // Scenario: + // start a legacy chain with some state + // when a chain upgrade proposal is executed + // then the chain upgrades successfully + systest.Sut.StopChain() + + currentBranchBinary := systest.Sut.ExecBinary() + currentInitializer := systest.Sut.TestnetInitializer() + + legacyBinary := systest.WorkDir + "/binaries/v0.4/evmd" + systest.Sut.SetExecBinary(legacyBinary) + systest.Sut.SetTestnetInitializer(systest.InitializerWithBinary(legacyBinary, systest.Sut)) + systest.Sut.SetupChain() + + votingPeriod := 5 * time.Second // enough time to vote + systest.Sut.ModifyGenesisJSON(t, systest.SetGovVotingPeriod(t, votingPeriod)) + + systest.Sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight+1), "--chain-id=local-4221", "--minimum-gas-prices=0.00atest") + + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) + govAddr := sdk.AccAddress(address.Module("gov")).String() + // submit upgrade proposal + proposal := fmt.Sprintf(` +{ + "messages": [ + { + "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", + "authority": %q, + "plan": { + "name": %q, + "height": "%d" + } + } + ], + "metadata": "ipfs://CID", + "deposit": "100000000stake", + "title": "my upgrade", + "summary": "testing" +}`, govAddr, upgradeName, upgradeHeight) + rsp := cli.SubmitGovProposal(proposal, "--fees=10000000000000000000atest", "--from=node0") + systest.RequireTxSuccess(t, rsp) + raw := cli.CustomQuery("q", "gov", "proposals", "--depositor", cli.GetKeyAddr("node0")) + proposals := gjson.Get(raw, "proposals.#.id").Array() + require.NotEmpty(t, proposals, raw) + proposalID := proposals[len(proposals)-1].String() + + for i := range systest.Sut.NodesCount() { + go func(i int) { // do parallel + systest.Sut.Logf("Voting: validator %d\n", i) + rsp := cli.Run("tx", "gov", "vote", proposalID, "yes", "--fees=10000000000000000000atest", "--from", cli.GetKeyAddr(fmt.Sprintf("node%d", i))) + systest.RequireTxSuccess(t, rsp) + }(i) + } + + systest.Sut.AwaitBlockHeight(t, upgradeHeight-1, 60*time.Second) + t.Logf("current_height: %d\n", systest.Sut.CurrentHeight()) + raw = cli.CustomQuery("q", "gov", "proposal", proposalID) + proposalStatus := gjson.Get(raw, "proposal.status").String() + require.Equal(t, "PROPOSAL_STATUS_PASSED", proposalStatus, raw) + + t.Log("waiting for upgrade info") + systest.Sut.AwaitUpgradeInfo(t) + systest.Sut.StopChain() + + t.Log("Upgrade height was reached. Upgrading chain") + systest.Sut.SetExecBinary(currentBranchBinary) + systest.Sut.SetTestnetInitializer(currentInitializer) + systest.Sut.StartChain(t, "--chain-id=local-4221") + + require.Equal(t, upgradeHeight+1, systest.Sut.CurrentHeight()) + + // smoke test to make sure the chain still functions. + cli = systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) + to := cli.GetKeyAddr("node1") + from := cli.GetKeyAddr("node0") + got := cli.Run("tx", "bank", "send", from, to, "1atest", "--from=node0", "--fees=10000000000000000000atest", "--chain-id=local-4221") + systest.RequireTxSuccess(t, got) +} diff --git a/testutil/integration/evm/network/abci.go b/testutil/integration/evm/network/abci.go index 2050bc253..a1bdb7fa3 100644 --- a/testutil/integration/evm/network/abci.go +++ b/testutil/integration/evm/network/abci.go @@ -30,6 +30,27 @@ func (n *IntegrationNetwork) NextBlockWithTxs(txBytes ...[]byte) (*abcitypes.Res return n.finalizeBlockAndCommit(time.Second, txBytes...) } +// FinalizeBlock is a helper function that runs FinalizeBlock logic +// without Commit and initializing context. +func (n *IntegrationNetwork) FinalizeBlock() (*abcitypes.ResponseFinalizeBlock, error) { + header := n.ctx.BlockHeader() + // Update block header and BeginBlock + header.Height++ + header.AppHash = n.app.LastCommitID().Hash + // Calculate new block time after duration + newBlockTime := header.Time.Add(time.Second) + header.Time = newBlockTime + + // FinalizeBlock to run endBlock, deliverTx & beginBlock logic + req := buildFinalizeBlockReq(header, n.valSet.Validators) + + res, err := n.app.FinalizeBlock(req) + if err != nil { + return nil, err + } + return res, nil +} + // finalizeBlockAndCommit is a private helper function that runs the FinalizeBlock logic // with the provided txBytes, updates the context and // commits the changes to have a block time after the given duration. @@ -60,6 +81,7 @@ func (n *IntegrationNetwork) finalizeBlockAndCommit(duration time.Duration, txBy // This might have to be changed with time if we want to test gas limits newCtx = newCtx.WithBlockGasMeter(storetypes.NewInfiniteGasMeter()) newCtx = newCtx.WithVoteInfos(req.DecidedLastCommit.GetVotes()) + newCtx = newCtx.WithHeaderHash(header.AppHash) n.ctx = newCtx // commit changes diff --git a/testutil/integration/evm/network/setup.go b/testutil/integration/evm/network/setup.go index 9951cf576..f352bd4af 100644 --- a/testutil/integration/evm/network/setup.go +++ b/testutil/integration/evm/network/setup.go @@ -15,7 +15,6 @@ import ( feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" "github.com/cosmos/gogoproto/proto" - capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" sdkmath "cosmossdk.io/math" @@ -67,7 +66,6 @@ var genesisSetupFunctions = map[string]genSetupFn{ // This is handled accordingly on chain and context initialization return genesisState, nil }, - capabilitytypes.ModuleName: genStateSetter[*capabilitytypes.GenesisState](capabilitytypes.ModuleName), } // genStateSetter is a generic function to set module-specific genesis state diff --git a/testutil/integration/evm/network/unit_network.go b/testutil/integration/evm/network/unit_network.go index 9e23559f7..ff068b8f5 100644 --- a/testutil/integration/evm/network/unit_network.go +++ b/testutil/integration/evm/network/unit_network.go @@ -1,8 +1,6 @@ package network import ( - "github.com/ethereum/go-ethereum/common" - "github.com/cosmos/evm" "github.com/cosmos/evm/x/vm/statedb" @@ -36,11 +34,10 @@ func NewUnitTestNetwork(createEvmApp CreateEvmApp, opts ...ConfigOption) *UnitTe // GetStateDB returns the state database for the current block. func (n *UnitTestNetwork) GetStateDB() *statedb.StateDB { - headerHash := n.GetContext().HeaderHash() return statedb.New( n.GetContext(), n.app.GetEVMKeeper(), - statedb.NewEmptyTxConfig(common.BytesToHash(headerHash)), + statedb.NewEmptyTxConfig(), ) } diff --git a/testutil/statedb.go b/testutil/statedb.go index f248ae4d3..cbae8b280 100644 --- a/testutil/statedb.go +++ b/testutil/statedb.go @@ -1,8 +1,6 @@ package testutil import ( - "github.com/ethereum/go-ethereum/common" - anteinterfaces "github.com/cosmos/evm/ante/interfaces" "github.com/cosmos/evm/x/vm/statedb" @@ -11,5 +9,5 @@ import ( // NewStateDB returns a new StateDB for testing purposes. func NewStateDB(ctx sdk.Context, evmKeeper anteinterfaces.EVMKeeper) *statedb.StateDB { - return statedb.New(ctx, evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))) + return statedb.New(ctx, evmKeeper, statedb.NewEmptyTxConfig()) } diff --git a/x/erc20/keeper/keeper.go b/x/erc20/keeper/keeper.go index 1123b25d4..ce800a645 100644 --- a/x/erc20/keeper/keeper.go +++ b/x/erc20/keeper/keeper.go @@ -3,6 +3,10 @@ package keeper import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + + "github.com/cosmos/evm/precompiles/erc20" + "github.com/cosmos/evm/precompiles/werc20" "github.com/cosmos/evm/x/erc20/types" transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" @@ -25,6 +29,10 @@ type Keeper struct { evmKeeper types.EVMKeeper stakingKeeper types.StakingKeeper transferKeeper *transferkeeper.Keeper + + // cached abis + erc20ABI abi.ABI + werc20ABI abi.ABI } // NewKeeper creates new instances of the erc20 Keeper @@ -43,6 +51,16 @@ func NewKeeper( panic(err) } + erc20ABI, err := erc20.LoadABI() + if err != nil { + panic(err) + } + + werc20ABI, err := werc20.LoadABI() + if err != nil { + panic(err) + } + return Keeper{ authority: authority, storeKey: storeKey, @@ -52,6 +70,8 @@ func NewKeeper( evmKeeper: evmKeeper, stakingKeeper: sk, transferKeeper: transferKeeper, + erc20ABI: erc20ABI, + werc20ABI: werc20ABI, } } diff --git a/x/erc20/keeper/precompiles.go b/x/erc20/keeper/precompiles.go index 6c0312813..9daa52414 100644 --- a/x/erc20/keeper/precompiles.go +++ b/x/erc20/keeper/precompiles.go @@ -62,10 +62,10 @@ func (k Keeper) InstantiateERC20Precompile(ctx sdk.Context, contractAddr common. } if hasWrappedMethods { - return werc20.NewPrecompile(pair, k.bankKeeper, k, *k.transferKeeper) + return werc20.NewPrecompile(pair, k.bankKeeper, k, *k.transferKeeper, k.erc20ABI, k.werc20ABI) } - return erc20.NewPrecompile(pair, k.bankKeeper, k, *k.transferKeeper) + return erc20.NewPrecompile(pair, k.bankKeeper, k, *k.transferKeeper, k.erc20ABI) } // RegisterCodeHash checks if a new precompile already exists and registers the code hash it is not diff --git a/x/erc20/types/erc20.pb.go b/x/erc20/types/erc20.pb.go index 5089cc87b..9370f63d2 100644 --- a/x/erc20/types/erc20.pb.go +++ b/x/erc20/types/erc20.pb.go @@ -57,8 +57,8 @@ func (Owner) EnumDescriptor() ([]byte, []int) { return fileDescriptor_1164958b5b106e92, []int{0} } -// TokenPair defines an instance that records a pairing consisting of a native -// Cosmos Coin and an ERC20 token address. +// TokenPair defines an instance that records a pairing (mapping) consisting of a native +// Cosmos Coin and an ERC20 token address. The "pair" does not imply an asset swap exchange. type TokenPair struct { // erc20_address is the hex address of ERC20 contract token Erc20Address string `protobuf:"bytes,1,opt,name=erc20_address,json=erc20Address,proto3" json:"erc20_address,omitempty"` diff --git a/x/erc20/types/errors.go b/x/erc20/types/errors.go index 99ad293f2..7f50187f9 100644 --- a/x/erc20/types/errors.go +++ b/x/erc20/types/errors.go @@ -25,4 +25,5 @@ var ( ErrInvalidAllowance = errorsmod.Register(ModuleName, 18, "invalid allowance") ErrNegativeToken = errorsmod.Register(ModuleName, 19, "token amount is negative") ErrExpectedEvent = errorsmod.Register(ModuleName, 20, "expected event") + ErrContractAlreadyExists = errorsmod.Register(ModuleName, 21, "contract already exists") ) diff --git a/x/erc20/types/genesis.pb.go b/x/erc20/types/genesis.pb.go index 45741d13e..b923d4379 100644 --- a/x/erc20/types/genesis.pb.go +++ b/x/erc20/types/genesis.pb.go @@ -28,7 +28,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type GenesisState struct { // params are the erc20 module parameters at genesis Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - // token_pairs is a slice of the registered token pairs at genesis + // token_pairs is a slice of the registered token pairs (mappings) at genesis TokenPairs []TokenPair `protobuf:"bytes,2,rep,name=token_pairs,json=tokenPairs,proto3" json:"token_pairs"` // allowances is a slice of the registered allowances at genesis Allowances []Allowance `protobuf:"bytes,3,rep,name=allowances,proto3" json:"allowances"` diff --git a/x/erc20/types/mocks/BankKeeper.go b/x/erc20/types/mocks/BankKeeper.go index 664ff49fb..98fdbd470 100644 --- a/x/erc20/types/mocks/BankKeeper.go +++ b/x/erc20/types/mocks/BankKeeper.go @@ -1,7 +1,12 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: x/gov/testutil/expected_keepers.go - -// Package testutil is a generated GoMock package. +// Source: ./x/erc20/types/interfaces.go +// +// Generated by this command: +// +// mockgen -source=./x/erc20/types/interfaces.go -package=mocks -destination=./x/erc20/types/mocks/BankKeeper.go -exclude_interfaces=AccountKeeper,StakingKeeper,EVMKeeper,Erc20Keeper +// + +// Package mocks is a generated GoMock package. package mocks import ( @@ -9,79 +14,36 @@ import ( reflect "reflect" types "github.com/cosmos/cosmos-sdk/types" - query "github.com/cosmos/cosmos-sdk/types/query" - keeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" types0 "github.com/cosmos/cosmos-sdk/x/bank/types" gomock "go.uber.org/mock/gomock" ) -// BankKeeper is a mock of BankKeeper interface. -type BankKeeper struct { +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { ctrl *gomock.Controller recorder *MockBankKeeperMockRecorder + isgomock struct{} } // MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. type MockBankKeeperMockRecorder struct { - mock *BankKeeper + mock *MockBankKeeper } // NewMockBankKeeper creates a new mock instance. -func NewMockBankKeeper(ctrl *gomock.Controller) *BankKeeper { - mock := &BankKeeper{ctrl: ctrl} +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} mock.recorder = &MockBankKeeperMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *BankKeeper) EXPECT() *MockBankKeeperMockRecorder { +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { return m.recorder } -// AllBalances mocks base method. -func (m *BankKeeper) AllBalances(arg0 context.Context, arg1 *types0.QueryAllBalancesRequest) (*types0.QueryAllBalancesResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AllBalances", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryAllBalancesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AllBalances indicates an expected call of AllBalances. -func (mr *MockBankKeeperMockRecorder) AllBalances(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllBalances", reflect.TypeOf((*BankKeeper)(nil).AllBalances), arg0, arg1) -} - -// AppendSendRestriction mocks base method. -func (m *BankKeeper) AppendSendRestriction(restriction types0.SendRestrictionFn) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AppendSendRestriction", restriction) -} - -// AppendSendRestriction indicates an expected call of AppendSendRestriction. -func (mr *MockBankKeeperMockRecorder) AppendSendRestriction(restriction interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AppendSendRestriction", reflect.TypeOf((*BankKeeper)(nil).AppendSendRestriction), restriction) -} - -// Balance mocks base method. -func (m *BankKeeper) Balance(arg0 context.Context, arg1 *types0.QueryBalanceRequest) (*types0.QueryBalanceResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Balance", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryBalanceResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Balance indicates an expected call of Balance. -func (mr *MockBankKeeperMockRecorder) Balance(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Balance", reflect.TypeOf((*BankKeeper)(nil).Balance), arg0, arg1) -} - // BlockedAddr mocks base method. -func (m *BankKeeper) BlockedAddr(addr types.AccAddress) bool { +func (m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BlockedAddr", addr) ret0, _ := ret[0].(bool) @@ -89,13 +51,13 @@ func (m *BankKeeper) BlockedAddr(addr types.AccAddress) bool { } // BlockedAddr indicates an expected call of BlockedAddr. -func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*BankKeeper)(nil).BlockedAddr), addr) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankKeeper)(nil).BlockedAddr), addr) } // BurnCoins mocks base method. -func (m *BankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types.Coins) error { +func (m *MockBankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types.Coins) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BurnCoins", ctx, moduleName, amt) ret0, _ := ret[0].(error) @@ -103,214 +65,13 @@ func (m *BankKeeper) BurnCoins(ctx context.Context, moduleName string, amt types } // BurnCoins indicates an expected call of BurnCoins. -func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*BankKeeper)(nil).BurnCoins), ctx, moduleName, amt) -} - -// ClearSendRestriction mocks base method. -func (m *BankKeeper) ClearSendRestriction() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "ClearSendRestriction") -} - -// ClearSendRestriction indicates an expected call of ClearSendRestriction. -func (mr *MockBankKeeperMockRecorder) ClearSendRestriction() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClearSendRestriction", reflect.TypeOf((*BankKeeper)(nil).ClearSendRestriction)) -} - -// DelegateCoins mocks base method. -func (m *BankKeeper) DelegateCoins(ctx context.Context, delegatorAddr, moduleAccAddr types.AccAddress, amt types.Coins) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DelegateCoins", ctx, delegatorAddr, moduleAccAddr, amt) - ret0, _ := ret[0].(error) - return ret0 -} - -// DelegateCoins indicates an expected call of DelegateCoins. -func (mr *MockBankKeeperMockRecorder) DelegateCoins(ctx, delegatorAddr, moduleAccAddr, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelegateCoins", reflect.TypeOf((*BankKeeper)(nil).DelegateCoins), ctx, delegatorAddr, moduleAccAddr, amt) -} - -// DelegateCoinsFromAccountToModule mocks base method. -func (m *BankKeeper) DelegateCoinsFromAccountToModule(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DelegateCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt) - ret0, _ := ret[0].(error) - return ret0 -} - -// DelegateCoinsFromAccountToModule indicates an expected call of DelegateCoinsFromAccountToModule. -func (mr *MockBankKeeperMockRecorder) DelegateCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DelegateCoinsFromAccountToModule", reflect.TypeOf((*BankKeeper)(nil).DelegateCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) -} - -// DeleteSendEnabled mocks base method. -func (m *BankKeeper) DeleteSendEnabled(ctx context.Context, denoms ...string) { - m.ctrl.T.Helper() - varargs := []interface{}{ctx} - for _, a := range denoms { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "DeleteSendEnabled", varargs...) -} - -// DeleteSendEnabled indicates an expected call of DeleteSendEnabled. -func (mr *MockBankKeeperMockRecorder) DeleteSendEnabled(ctx interface{}, denoms ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, denoms...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSendEnabled", reflect.TypeOf((*BankKeeper)(nil).DeleteSendEnabled), varargs...) -} - -// DenomMetadata mocks base method. -func (m *BankKeeper) DenomMetadata(arg0 context.Context, arg1 *types0.QueryDenomMetadataRequest) (*types0.QueryDenomMetadataResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DenomMetadata", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryDenomMetadataResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DenomMetadata indicates an expected call of DenomMetadata. -func (mr *MockBankKeeperMockRecorder) DenomMetadata(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DenomMetadata", reflect.TypeOf((*BankKeeper)(nil).DenomMetadata), arg0, arg1) -} - -// DenomMetadataByQueryString mocks base method. -func (m *BankKeeper) DenomMetadataByQueryString(arg0 context.Context, arg1 *types0.QueryDenomMetadataByQueryStringRequest) (*types0.QueryDenomMetadataByQueryStringResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DenomMetadataByQueryString", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryDenomMetadataByQueryStringResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DenomMetadataByQueryString indicates an expected call of DenomMetadataByQueryString. -func (mr *MockBankKeeperMockRecorder) DenomMetadataByQueryString(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DenomMetadataByQueryString", reflect.TypeOf((*BankKeeper)(nil).DenomMetadataByQueryString), arg0, arg1) -} - -// DenomOwners mocks base method. -func (m *BankKeeper) DenomOwners(arg0 context.Context, arg1 *types0.QueryDenomOwnersRequest) (*types0.QueryDenomOwnersResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DenomOwners", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryDenomOwnersResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DenomOwners indicates an expected call of DenomOwners. -func (mr *MockBankKeeperMockRecorder) DenomOwners(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DenomOwners", reflect.TypeOf((*BankKeeper)(nil).DenomOwners), arg0, arg1) -} - -// DenomsMetadata mocks base method. -func (m *BankKeeper) DenomsMetadata(arg0 context.Context, arg1 *types0.QueryDenomsMetadataRequest) (*types0.QueryDenomsMetadataResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DenomsMetadata", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryDenomsMetadataResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DenomsMetadata indicates an expected call of DenomsMetadata. -func (mr *MockBankKeeperMockRecorder) DenomsMetadata(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DenomsMetadata", reflect.TypeOf((*BankKeeper)(nil).DenomsMetadata), arg0, arg1) -} - -// ExportGenesis mocks base method. -func (m *BankKeeper) ExportGenesis(arg0 context.Context) *types0.GenesisState { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ExportGenesis", arg0) - ret0, _ := ret[0].(*types0.GenesisState) - return ret0 -} - -// ExportGenesis indicates an expected call of ExportGenesis. -func (mr *MockBankKeeperMockRecorder) ExportGenesis(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesis", reflect.TypeOf((*BankKeeper)(nil).ExportGenesis), arg0) -} - -// GetAccountsBalances mocks base method. -func (m *BankKeeper) GetAccountsBalances(ctx context.Context) []types0.Balance { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAccountsBalances", ctx) - ret0, _ := ret[0].([]types0.Balance) - return ret0 -} - -// GetAccountsBalances indicates an expected call of GetAccountsBalances. -func (mr *MockBankKeeperMockRecorder) GetAccountsBalances(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccountsBalances", reflect.TypeOf((*BankKeeper)(nil).GetAccountsBalances), ctx) -} - -// GetAllBalances mocks base method. -func (m *BankKeeper) GetAllBalances(ctx context.Context, addr types.AccAddress) types.Coins { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr) - ret0, _ := ret[0].(types.Coins) - return ret0 -} - -// GetAllBalances indicates an expected call of GetAllBalances. -func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*BankKeeper)(nil).GetAllBalances), ctx, addr) -} - -// GetAllDenomMetaData mocks base method. -func (m *BankKeeper) GetAllDenomMetaData(ctx context.Context) []types0.Metadata { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllDenomMetaData", ctx) - ret0, _ := ret[0].([]types0.Metadata) - return ret0 -} - -// GetAllDenomMetaData indicates an expected call of GetAllDenomMetaData. -func (mr *MockBankKeeperMockRecorder) GetAllDenomMetaData(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllDenomMetaData", reflect.TypeOf((*BankKeeper)(nil).GetAllDenomMetaData), ctx) -} - -// GetAllSendEnabledEntries mocks base method. -func (m *BankKeeper) GetAllSendEnabledEntries(ctx context.Context) []types0.SendEnabled { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllSendEnabledEntries", ctx) - ret0, _ := ret[0].([]types0.SendEnabled) - return ret0 -} - -// GetAllSendEnabledEntries indicates an expected call of GetAllSendEnabledEntries. -func (mr *MockBankKeeperMockRecorder) GetAllSendEnabledEntries(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllSendEnabledEntries", reflect.TypeOf((*BankKeeper)(nil).GetAllSendEnabledEntries), ctx) -} - -// GetAuthority mocks base method. -func (m *BankKeeper) GetAuthority() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAuthority") - ret0, _ := ret[0].(string) - return ret0 -} - -// GetAuthority indicates an expected call of GetAuthority. -func (mr *MockBankKeeperMockRecorder) GetAuthority() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAuthority", reflect.TypeOf((*BankKeeper)(nil).GetAuthority)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, moduleName, amt) } // GetBalance mocks base method. -func (m *BankKeeper) GetBalance(ctx context.Context, addr types.AccAddress, denom string) types.Coin { +func (m *MockBankKeeper) GetBalance(ctx context.Context, addr types.AccAddress, denom string) types.Coin { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetBalance", ctx, addr, denom) ret0, _ := ret[0].(types.Coin) @@ -318,27 +79,13 @@ func (m *BankKeeper) GetBalance(ctx context.Context, addr types.AccAddress, deno } // GetBalance indicates an expected call of GetBalance. -func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*BankKeeper)(nil).GetBalance), ctx, addr, denom) -} - -// GetBlockedAddresses mocks base method. -func (m *BankKeeper) GetBlockedAddresses() map[string]bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetBlockedAddresses") - ret0, _ := ret[0].(map[string]bool) - return ret0 -} - -// GetBlockedAddresses indicates an expected call of GetBlockedAddresses. -func (mr *MockBankKeeperMockRecorder) GetBlockedAddresses() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockedAddresses", reflect.TypeOf((*BankKeeper)(nil).GetBlockedAddresses)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockBankKeeper)(nil).GetBalance), ctx, addr, denom) } // GetDenomMetaData mocks base method. -func (m *BankKeeper) GetDenomMetaData(ctx context.Context, denom string) (types0.Metadata, bool) { +func (m *MockBankKeeper) GetDenomMetaData(ctx context.Context, denom string) (types0.Metadata, bool) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetDenomMetaData", ctx, denom) ret0, _ := ret[0].(types0.Metadata) @@ -347,58 +94,13 @@ func (m *BankKeeper) GetDenomMetaData(ctx context.Context, denom string) (types0 } // GetDenomMetaData indicates an expected call of GetDenomMetaData. -func (mr *MockBankKeeperMockRecorder) GetDenomMetaData(ctx, denom interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDenomMetaData", reflect.TypeOf((*BankKeeper)(nil).GetDenomMetaData), ctx, denom) -} - -// GetPaginatedTotalSupply mocks base method. -func (m *BankKeeper) GetPaginatedTotalSupply(ctx context.Context, pagination *query.PageRequest) (types.Coins, *query.PageResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPaginatedTotalSupply", ctx, pagination) - ret0, _ := ret[0].(types.Coins) - ret1, _ := ret[1].(*query.PageResponse) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GetPaginatedTotalSupply indicates an expected call of GetPaginatedTotalSupply. -func (mr *MockBankKeeperMockRecorder) GetPaginatedTotalSupply(ctx, pagination interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPaginatedTotalSupply", reflect.TypeOf((*BankKeeper)(nil).GetPaginatedTotalSupply), ctx, pagination) -} - -// GetParams mocks base method. -func (m *BankKeeper) GetParams(ctx context.Context) types0.Params { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetParams", ctx) - ret0, _ := ret[0].(types0.Params) - return ret0 -} - -// GetParams indicates an expected call of GetParams. -func (mr *MockBankKeeperMockRecorder) GetParams(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParams", reflect.TypeOf((*BankKeeper)(nil).GetParams), ctx) -} - -// GetSendEnabledEntry mocks base method. -func (m *BankKeeper) GetSendEnabledEntry(ctx context.Context, denom string) (types0.SendEnabled, bool) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSendEnabledEntry", ctx, denom) - ret0, _ := ret[0].(types0.SendEnabled) - ret1, _ := ret[1].(bool) - return ret0, ret1 -} - -// GetSendEnabledEntry indicates an expected call of GetSendEnabledEntry. -func (mr *MockBankKeeperMockRecorder) GetSendEnabledEntry(ctx, denom interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) GetDenomMetaData(ctx, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSendEnabledEntry", reflect.TypeOf((*BankKeeper)(nil).GetSendEnabledEntry), ctx, denom) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDenomMetaData", reflect.TypeOf((*MockBankKeeper)(nil).GetDenomMetaData), ctx, denom) } // GetSupply mocks base method. -func (m *BankKeeper) GetSupply(ctx context.Context, denom string) types.Coin { +func (m *MockBankKeeper) GetSupply(ctx context.Context, denom string) types.Coin { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetSupply", ctx, denom) ret0, _ := ret[0].(types.Coin) @@ -406,81 +108,13 @@ func (m *BankKeeper) GetSupply(ctx context.Context, denom string) types.Coin { } // GetSupply indicates an expected call of GetSupply. -func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*BankKeeper)(nil).GetSupply), ctx, denom) -} - -// HasBalance mocks base method. -func (m *BankKeeper) HasBalance(ctx context.Context, addr types.AccAddress, amt types.Coin) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasBalance", ctx, addr, amt) - ret0, _ := ret[0].(bool) - return ret0 -} - -// HasBalance indicates an expected call of HasBalance. -func (mr *MockBankKeeperMockRecorder) HasBalance(ctx, addr, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasBalance", reflect.TypeOf((*BankKeeper)(nil).HasBalance), ctx, addr, amt) -} - -// HasDenomMetaData mocks base method. -func (m *BankKeeper) HasDenomMetaData(ctx context.Context, denom string) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasDenomMetaData", ctx, denom) - ret0, _ := ret[0].(bool) - return ret0 -} - -// HasDenomMetaData indicates an expected call of HasDenomMetaData. -func (mr *MockBankKeeperMockRecorder) HasDenomMetaData(ctx, denom interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasDenomMetaData", reflect.TypeOf((*BankKeeper)(nil).HasDenomMetaData), ctx, denom) -} - -// HasSupply mocks base method. -func (m *BankKeeper) HasSupply(ctx context.Context, denom string) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HasSupply", ctx, denom) - ret0, _ := ret[0].(bool) - return ret0 -} - -// HasSupply indicates an expected call of HasSupply. -func (mr *MockBankKeeperMockRecorder) HasSupply(ctx, denom interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasSupply", reflect.TypeOf((*BankKeeper)(nil).HasSupply), ctx, denom) -} - -// InitGenesis mocks base method. -func (m *BankKeeper) InitGenesis(arg0 context.Context, arg1 *types0.GenesisState) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "InitGenesis", arg0, arg1) -} - -// InitGenesis indicates an expected call of InitGenesis. -func (mr *MockBankKeeperMockRecorder) InitGenesis(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitGenesis", reflect.TypeOf((*BankKeeper)(nil).InitGenesis), arg0, arg1) -} - -// InputOutputCoins mocks base method. -func (m *BankKeeper) InputOutputCoins(ctx context.Context, input types0.Input, outputs []types0.Output) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InputOutputCoins", ctx, input, outputs) - ret0, _ := ret[0].(error) - return ret0 -} - -// InputOutputCoins indicates an expected call of InputOutputCoins. -func (mr *MockBankKeeperMockRecorder) InputOutputCoins(ctx, input, outputs interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InputOutputCoins", reflect.TypeOf((*BankKeeper)(nil).InputOutputCoins), ctx, input, outputs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*MockBankKeeper)(nil).GetSupply), ctx, denom) } // IsSendEnabledCoin mocks base method. -func (m *BankKeeper) IsSendEnabledCoin(ctx context.Context, coin types.Coin) bool { +func (m *MockBankKeeper) IsSendEnabledCoin(ctx context.Context, coin types.Coin) bool { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "IsSendEnabledCoin", ctx, coin) ret0, _ := ret[0].(bool) @@ -488,120 +122,37 @@ func (m *BankKeeper) IsSendEnabledCoin(ctx context.Context, coin types.Coin) boo } // IsSendEnabledCoin indicates an expected call of IsSendEnabledCoin. -func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoin(ctx, coin interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoin(ctx, coin any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoin", reflect.TypeOf((*BankKeeper)(nil).IsSendEnabledCoin), ctx, coin) -} - -// IsSendEnabledCoins mocks base method. -func (m *BankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coin) error { - m.ctrl.T.Helper() - varargs := []interface{}{ctx} - for _, a := range coins { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "IsSendEnabledCoins", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// IsSendEnabledCoins indicates an expected call of IsSendEnabledCoins. -func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, coins...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoins", reflect.TypeOf((*BankKeeper)(nil).IsSendEnabledCoins), varargs...) -} - -// IsSendEnabledDenom mocks base method. -func (m *BankKeeper) IsSendEnabledDenom(ctx context.Context, denom string) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "IsSendEnabledDenom", ctx, denom) - ret0, _ := ret[0].(bool) - return ret0 -} - -// IsSendEnabledDenom indicates an expected call of IsSendEnabledDenom. -func (mr *MockBankKeeperMockRecorder) IsSendEnabledDenom(ctx, denom interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledDenom", reflect.TypeOf((*BankKeeper)(nil).IsSendEnabledDenom), ctx, denom) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoin", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledCoin), ctx, coin) } // IterateAccountBalances mocks base method. -func (m *BankKeeper) IterateAccountBalances(ctx context.Context, addr types.AccAddress, cb func(types.Coin) bool) { +func (m *MockBankKeeper) IterateAccountBalances(ctx context.Context, account types.AccAddress, cb func(types.Coin) bool) { m.ctrl.T.Helper() - m.ctrl.Call(m, "IterateAccountBalances", ctx, addr, cb) + m.ctrl.Call(m, "IterateAccountBalances", ctx, account, cb) } // IterateAccountBalances indicates an expected call of IterateAccountBalances. -func (mr *MockBankKeeperMockRecorder) IterateAccountBalances(ctx, addr, cb interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAccountBalances", reflect.TypeOf((*BankKeeper)(nil).IterateAccountBalances), ctx, addr, cb) -} - -// IterateAllBalances mocks base method. -func (m *BankKeeper) IterateAllBalances(ctx context.Context, cb func(types.AccAddress, types.Coin) bool) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "IterateAllBalances", ctx, cb) -} - -// IterateAllBalances indicates an expected call of IterateAllBalances. -func (mr *MockBankKeeperMockRecorder) IterateAllBalances(ctx, cb interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAllBalances", reflect.TypeOf((*BankKeeper)(nil).IterateAllBalances), ctx, cb) -} - -// IterateAllDenomMetaData mocks base method. -func (m *BankKeeper) IterateAllDenomMetaData(ctx context.Context, cb func(types0.Metadata) bool) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "IterateAllDenomMetaData", ctx, cb) -} - -// IterateAllDenomMetaData indicates an expected call of IterateAllDenomMetaData. -func (mr *MockBankKeeperMockRecorder) IterateAllDenomMetaData(ctx, cb interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAllDenomMetaData", reflect.TypeOf((*BankKeeper)(nil).IterateAllDenomMetaData), ctx, cb) -} - -// IterateSendEnabledEntries mocks base method. -func (m *BankKeeper) IterateSendEnabledEntries(ctx context.Context, cb func(string, bool) bool) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "IterateSendEnabledEntries", ctx, cb) -} - -// IterateSendEnabledEntries indicates an expected call of IterateSendEnabledEntries. -func (mr *MockBankKeeperMockRecorder) IterateSendEnabledEntries(ctx, cb interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) IterateAccountBalances(ctx, account, cb any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateSendEnabledEntries", reflect.TypeOf((*BankKeeper)(nil).IterateSendEnabledEntries), ctx, cb) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAccountBalances", reflect.TypeOf((*MockBankKeeper)(nil).IterateAccountBalances), ctx, account, cb) } // IterateTotalSupply mocks base method. -func (m *BankKeeper) IterateTotalSupply(ctx context.Context, cb func(types.Coin) bool) { +func (m *MockBankKeeper) IterateTotalSupply(ctx context.Context, cb func(types.Coin) bool) { m.ctrl.T.Helper() m.ctrl.Call(m, "IterateTotalSupply", ctx, cb) } // IterateTotalSupply indicates an expected call of IterateTotalSupply. -func (mr *MockBankKeeperMockRecorder) IterateTotalSupply(ctx, cb interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateTotalSupply", reflect.TypeOf((*BankKeeper)(nil).IterateTotalSupply), ctx, cb) -} - -// LockedCoins mocks base method. -func (m *BankKeeper) LockedCoins(ctx context.Context, addr types.AccAddress) types.Coins { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LockedCoins", ctx, addr) - ret0, _ := ret[0].(types.Coins) - return ret0 -} - -// LockedCoins indicates an expected call of LockedCoins. -func (mr *MockBankKeeperMockRecorder) LockedCoins(ctx, addr interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) IterateTotalSupply(ctx, cb any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LockedCoins", reflect.TypeOf((*BankKeeper)(nil).LockedCoins), ctx, addr) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateTotalSupply", reflect.TypeOf((*MockBankKeeper)(nil).IterateTotalSupply), ctx, cb) } // MintCoins mocks base method. -func (m *BankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { +func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MintCoins", ctx, moduleName, amt) ret0, _ := ret[0].(error) @@ -609,40 +160,13 @@ func (m *BankKeeper) MintCoins(ctx context.Context, moduleName string, amt types } // MintCoins indicates an expected call of MintCoins. -func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintCoins", reflect.TypeOf((*BankKeeper)(nil).MintCoins), ctx, moduleName, amt) -} - -// Params mocks base method. -func (m *BankKeeper) Params(arg0 context.Context, arg1 *types0.QueryParamsRequest) (*types0.QueryParamsResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Params", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryParamsResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Params indicates an expected call of Params. -func (mr *MockBankKeeperMockRecorder) Params(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Params", reflect.TypeOf((*BankKeeper)(nil).Params), arg0, arg1) -} - -// PrependSendRestriction mocks base method. -func (m *BankKeeper) PrependSendRestriction(restriction types0.SendRestrictionFn) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PrependSendRestriction", restriction) -} - -// PrependSendRestriction indicates an expected call of PrependSendRestriction. -func (mr *MockBankKeeperMockRecorder) PrependSendRestriction(restriction interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrependSendRestriction", reflect.TypeOf((*BankKeeper)(nil).PrependSendRestriction), restriction) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintCoins", reflect.TypeOf((*MockBankKeeper)(nil).MintCoins), ctx, moduleName, amt) } // SendCoins mocks base method. -func (m *BankKeeper) SendCoins(ctx context.Context, fromAddr, toAddr types.AccAddress, amt types.Coins) error { +func (m *MockBankKeeper) SendCoins(ctx context.Context, fromAddr, toAddr types.AccAddress, amt types.Coins) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SendCoins", ctx, fromAddr, toAddr, amt) ret0, _ := ret[0].(error) @@ -650,13 +174,13 @@ func (m *BankKeeper) SendCoins(ctx context.Context, fromAddr, toAddr types.AccAd } // SendCoins indicates an expected call of SendCoins. -func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*BankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) } // SendCoinsFromAccountToModule mocks base method. -func (m *BankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { +func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt) ret0, _ := ret[0].(error) @@ -664,13 +188,13 @@ func (m *BankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAdd } // SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule. -func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*BankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } // SendCoinsFromModuleToAccount mocks base method. -func (m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { +func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt) ret0, _ := ret[0].(error) @@ -678,122 +202,25 @@ func (m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderMod } // SendCoinsFromModuleToAccount indicates an expected call of SendCoinsFromModuleToAccount. -func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*BankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) -} - -// SendCoinsFromModuleToModule mocks base method. -func (m *BankKeeper) SendCoinsFromModuleToModule(ctx context.Context, senderModule, recipientModule string, amt types.Coins) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendCoinsFromModuleToModule", ctx, senderModule, recipientModule, amt) - ret0, _ := ret[0].(error) - return ret0 -} - -// SendCoinsFromModuleToModule indicates an expected call of SendCoinsFromModuleToModule. -func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToModule(ctx, senderModule, recipientModule, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToModule", reflect.TypeOf((*BankKeeper)(nil).SendCoinsFromModuleToModule), ctx, senderModule, recipientModule, amt) -} - -// SendEnabled mocks base method. -func (m *BankKeeper) SendEnabled(arg0 context.Context, arg1 *types0.QuerySendEnabledRequest) (*types0.QuerySendEnabledResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendEnabled", arg0, arg1) - ret0, _ := ret[0].(*types0.QuerySendEnabledResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SendEnabled indicates an expected call of SendEnabled. -func (mr *MockBankKeeperMockRecorder) SendEnabled(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendEnabled", reflect.TypeOf((*BankKeeper)(nil).SendEnabled), arg0, arg1) -} - -// SetAllSendEnabled mocks base method. -func (m *BankKeeper) SetAllSendEnabled(ctx context.Context, sendEnableds []*types0.SendEnabled) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetAllSendEnabled", ctx, sendEnableds) -} - -// SetAllSendEnabled indicates an expected call of SetAllSendEnabled. -func (mr *MockBankKeeperMockRecorder) SetAllSendEnabled(ctx, sendEnableds interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAllSendEnabled", reflect.TypeOf((*BankKeeper)(nil).SetAllSendEnabled), ctx, sendEnableds) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } // SetDenomMetaData mocks base method. -func (m *BankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData types0.Metadata) { +func (m *MockBankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData types0.Metadata) { m.ctrl.T.Helper() m.ctrl.Call(m, "SetDenomMetaData", ctx, denomMetaData) } // SetDenomMetaData indicates an expected call of SetDenomMetaData. -func (mr *MockBankKeeperMockRecorder) SetDenomMetaData(ctx, denomMetaData interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDenomMetaData", reflect.TypeOf((*BankKeeper)(nil).SetDenomMetaData), ctx, denomMetaData) -} - -// SetParams mocks base method. -func (m *BankKeeper) SetParams(ctx context.Context, params types0.Params) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetParams", ctx, params) - ret0, _ := ret[0].(error) - return ret0 -} - -// SetParams indicates an expected call of SetParams. -func (mr *MockBankKeeperMockRecorder) SetParams(ctx, params interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetParams", reflect.TypeOf((*BankKeeper)(nil).SetParams), ctx, params) -} - -// SetSendEnabled mocks base method. -func (m *BankKeeper) SetSendEnabled(ctx context.Context, denom string, value bool) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetSendEnabled", ctx, denom, value) -} - -// SetSendEnabled indicates an expected call of SetSendEnabled. -func (mr *MockBankKeeperMockRecorder) SetSendEnabled(ctx, denom, value interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SetDenomMetaData(ctx, denomMetaData any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSendEnabled", reflect.TypeOf((*BankKeeper)(nil).SetSendEnabled), ctx, denom, value) -} - -// SpendableBalanceByDenom mocks base method. -func (m *BankKeeper) SpendableBalanceByDenom(arg0 context.Context, arg1 *types0.QuerySpendableBalanceByDenomRequest) (*types0.QuerySpendableBalanceByDenomResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpendableBalanceByDenom", arg0, arg1) - ret0, _ := ret[0].(*types0.QuerySpendableBalanceByDenomResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SpendableBalanceByDenom indicates an expected call of SpendableBalanceByDenom. -func (mr *MockBankKeeperMockRecorder) SpendableBalanceByDenom(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableBalanceByDenom", reflect.TypeOf((*BankKeeper)(nil).SpendableBalanceByDenom), arg0, arg1) -} - -// SpendableBalances mocks base method. -func (m *BankKeeper) SpendableBalances(arg0 context.Context, arg1 *types0.QuerySpendableBalancesRequest) (*types0.QuerySpendableBalancesResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpendableBalances", arg0, arg1) - ret0, _ := ret[0].(*types0.QuerySpendableBalancesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SpendableBalances indicates an expected call of SpendableBalances. -func (mr *MockBankKeeperMockRecorder) SpendableBalances(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableBalances", reflect.TypeOf((*BankKeeper)(nil).SpendableBalances), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDenomMetaData", reflect.TypeOf((*MockBankKeeper)(nil).SetDenomMetaData), ctx, denomMetaData) } // SpendableCoin mocks base method. -func (m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, denom string) types.Coin { +func (m *MockBankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, denom string) types.Coin { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SpendableCoin", ctx, addr, denom) ret0, _ := ret[0].(types.Coin) @@ -801,116 +228,7 @@ func (m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, d } // SpendableCoin indicates an expected call of SpendableCoin. -func (mr *MockBankKeeperMockRecorder) SpendableCoin(ctx, addr, denom interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*BankKeeper)(nil).SpendableCoin), ctx, addr, denom) -} - -// SpendableCoins mocks base method. -func (m *BankKeeper) SpendableCoins(ctx context.Context, addr types.AccAddress) types.Coins { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr) - ret0, _ := ret[0].(types.Coins) - return ret0 -} - -// SpendableCoins indicates an expected call of SpendableCoins. -func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*BankKeeper)(nil).SpendableCoins), ctx, addr) -} - -// SupplyOf mocks base method. -func (m *BankKeeper) SupplyOf(arg0 context.Context, arg1 *types0.QuerySupplyOfRequest) (*types0.QuerySupplyOfResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SupplyOf", arg0, arg1) - ret0, _ := ret[0].(*types0.QuerySupplyOfResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SupplyOf indicates an expected call of SupplyOf. -func (mr *MockBankKeeperMockRecorder) SupplyOf(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SupplyOf", reflect.TypeOf((*BankKeeper)(nil).SupplyOf), arg0, arg1) -} - -// TotalSupply mocks base method. -func (m *BankKeeper) TotalSupply(arg0 context.Context, arg1 *types0.QueryTotalSupplyRequest) (*types0.QueryTotalSupplyResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TotalSupply", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryTotalSupplyResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// TotalSupply indicates an expected call of TotalSupply. -func (mr *MockBankKeeperMockRecorder) TotalSupply(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalSupply", reflect.TypeOf((*BankKeeper)(nil).TotalSupply), arg0, arg1) -} - -// UndelegateCoins mocks base method. -func (m *BankKeeper) UndelegateCoins(ctx context.Context, moduleAccAddr, delegatorAddr types.AccAddress, amt types.Coins) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UndelegateCoins", ctx, moduleAccAddr, delegatorAddr, amt) - ret0, _ := ret[0].(error) - return ret0 -} - -// UndelegateCoins indicates an expected call of UndelegateCoins. -func (mr *MockBankKeeperMockRecorder) UndelegateCoins(ctx, moduleAccAddr, delegatorAddr, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SpendableCoin(ctx, addr, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UndelegateCoins", reflect.TypeOf((*BankKeeper)(nil).UndelegateCoins), ctx, moduleAccAddr, delegatorAddr, amt) -} - -// UndelegateCoinsFromModuleToAccount mocks base method. -func (m *BankKeeper) UndelegateCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UndelegateCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt) - ret0, _ := ret[0].(error) - return ret0 -} - -// UndelegateCoinsFromModuleToAccount indicates an expected call of UndelegateCoinsFromModuleToAccount. -func (mr *MockBankKeeperMockRecorder) UndelegateCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UndelegateCoinsFromModuleToAccount", reflect.TypeOf((*BankKeeper)(nil).UndelegateCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) -} - -// ValidateBalance mocks base method. -func (m *BankKeeper) ValidateBalance(ctx context.Context, addr types.AccAddress) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ValidateBalance", ctx, addr) - ret0, _ := ret[0].(error) - return ret0 -} - -// ValidateBalance indicates an expected call of ValidateBalance. -func (mr *MockBankKeeperMockRecorder) ValidateBalance(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateBalance", reflect.TypeOf((*BankKeeper)(nil).ValidateBalance), ctx, addr) -} - -// WithMintCoinsRestriction mocks base method. -func (m *BankKeeper) WithMintCoinsRestriction(arg0 types0.MintingRestrictionFn) keeper.BaseKeeper { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WithMintCoinsRestriction", arg0) - ret0, _ := ret[0].(keeper.BaseKeeper) - return ret0 -} - -// WithMintCoinsRestriction indicates an expected call of WithMintCoinsRestriction. -func (mr *MockBankKeeperMockRecorder) WithMintCoinsRestriction(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithMintCoinsRestriction", reflect.TypeOf((*BankKeeper)(nil).WithMintCoinsRestriction), arg0) -} - -// DenomOwnersByQuery mocks base method. -func (m *BankKeeper) DenomOwnersByQuery(arg0 context.Context, arg1 *types0.QueryDenomOwnersByQueryRequest) (*types0.QueryDenomOwnersByQueryResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DenomOwnersByQuery", arg0, arg1) - ret0, _ := ret[0].(*types0.QueryDenomOwnersByQueryResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoin), ctx, addr, denom) } diff --git a/x/erc20/types/mocks/README.md b/x/erc20/types/mocks/README.md index 5b7ac5750..8aa521651 100644 --- a/x/erc20/types/mocks/README.md +++ b/x/erc20/types/mocks/README.md @@ -3,31 +3,10 @@ The mocks in this folder have been generated using the [mockery](https://vektra.github.io/mockery/latest/) tool. To regenerate the mocks, run the following commands at the root of this repository: -- `BankKeeper` (from used version of Cosmos SDK): +- `BankKeeper` (reduced interface defined in ERC20 types): ```bash -# update the currently used version -COSMOS_VERSION="v0.50.9-evmos" -CUR_DIR="$(pwd)" -TMP_DIR="/tmp/tmp-sdk-mocks-$(date +%s)" - -echo "Cloning Cosmos SDK $COSMOS_VERSION into $TMP_DIR..." && -git clone --depth 1 --branch "$COSMOS_VERSION" https://github.com/evmos/cosmos-sdk.git "$TMP_DIR" && -cd "$TMP_DIR" && - -# Go into bank module and generate mock -echo "Generating mocks for bank keeper..." && -cd x/bank/keeper && -mockery --name Keeper && -sed -i '' 's/\([^a-zA-Z]\)Keeper/\1BankKeeper/g' mocks/Keeper.go && -mv mocks/Keeper.go "$CUR_DIR/x/erc20/types/mocks/BankKeeper.go" && - -# Clean up -echo "Cleaning up $TMP_DIR..." && -cd "$CUR_DIR" && -rm -rf "$TMP_DIR" - -echo "Done." +mockgen -source=./x/erc20/types/interfaces.go -package=mocks -destination=./x/erc20/types/mocks/BankKeeper.go -exclude_interfaces=AccountKeeper,StakingKeeper,EVMKeeper,Erc20Keeper ``` - `EVMKeeper` (reduced interface defined in ERC20 types): diff --git a/x/erc20/types/query.pb.go b/x/erc20/types/query.pb.go index 7c396c160..ac5fe18e8 100644 --- a/x/erc20/types/query.pb.go +++ b/x/erc20/types/query.pb.go @@ -325,40 +325,40 @@ func init() { func init() { proto.RegisterFile("cosmos/evm/erc20/v1/query.proto", fileDescriptor_f1630a6677a16bf4) } var fileDescriptor_f1630a6677a16bf4 = []byte{ - // 524 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0x41, 0x8b, 0xd3, 0x40, - 0x14, 0xc7, 0x3b, 0xbb, 0x6c, 0xa1, 0xaf, 0x27, 0x67, 0xab, 0x2e, 0x5d, 0xcd, 0xd6, 0x2c, 0xb8, - 0xa1, 0xab, 0x33, 0xdb, 0x7a, 0xd6, 0xc3, 0x1e, 0x54, 0x3c, 0xd5, 0xa2, 0x17, 0x2f, 0x3a, 0x29, - 0x43, 0x0c, 0x9a, 0x4c, 0x36, 0x33, 0x0d, 0x2e, 0x22, 0x88, 0x9f, 0x40, 0x11, 0xfc, 0x0c, 0x9e, - 0xc4, 0x9b, 0x5f, 0x61, 0x8f, 0x05, 0x2f, 0x9e, 0x44, 0x5a, 0xc1, 0xaf, 0x21, 0x99, 0x99, 0xa6, - 0x8d, 0x46, 0x5a, 0x2f, 0x25, 0xf3, 0xf8, 0xbf, 0xff, 0xff, 0xf7, 0xde, 0x0c, 0x85, 0xbd, 0x91, - 0x90, 0x91, 0x90, 0x94, 0x67, 0x11, 0xe5, 0xe9, 0xa8, 0x7f, 0x44, 0xb3, 0x1e, 0x3d, 0x19, 0xf3, - 0xf4, 0x94, 0x24, 0xa9, 0x50, 0x02, 0x6f, 0x1b, 0x01, 0xe1, 0x59, 0x44, 0xb4, 0x80, 0x64, 0xbd, - 0xf6, 0x39, 0x16, 0x85, 0xb1, 0xa0, 0xfa, 0xd7, 0xe8, 0xda, 0x5d, 0x6b, 0xe4, 0x33, 0xc9, 0x8d, - 0x01, 0xcd, 0x7a, 0x3e, 0x57, 0xac, 0x47, 0x13, 0x16, 0x84, 0x31, 0x53, 0xa1, 0x88, 0xad, 0xb6, - 0x32, 0xd4, 0x98, 0x1b, 0xc1, 0x95, 0x2a, 0x41, 0xc0, 0x63, 0x2e, 0x43, 0x69, 0x25, 0xad, 0x40, - 0x04, 0x42, 0x7f, 0xd2, 0xfc, 0xcb, 0x56, 0x2f, 0x05, 0x42, 0x04, 0xcf, 0x39, 0x65, 0x49, 0x48, - 0x59, 0x1c, 0x0b, 0xa5, 0x63, 0x6d, 0x8f, 0xfb, 0x04, 0x2e, 0xdc, 0xcf, 0xc9, 0x1e, 0x88, 0x67, - 0x3c, 0x1e, 0xb0, 0x30, 0x95, 0x43, 0x7e, 0x32, 0xe6, 0x52, 0xe1, 0xdb, 0x00, 0x0b, 0xca, 0x1d, - 0xd4, 0x41, 0x5e, 0xb3, 0x7f, 0x95, 0xd8, 0xd1, 0xf3, 0x91, 0x88, 0xd9, 0x89, 0x1d, 0x89, 0x0c, - 0x58, 0xc0, 0x6d, 0xef, 0x70, 0xa9, 0xd3, 0xfd, 0x84, 0xe0, 0xe2, 0x5f, 0x11, 0x32, 0x11, 0xb1, - 0xe4, 0xf8, 0x1e, 0x34, 0x55, 0x5e, 0x7d, 0x9c, 0xe4, 0xe5, 0x1d, 0xd4, 0xd9, 0xf4, 0x9a, 0x7d, - 0x87, 0x54, 0xec, 0x97, 0x14, 0xdd, 0xc7, 0x8d, 0xb3, 0xef, 0x7b, 0xb5, 0x8f, 0xbf, 0x3e, 0x77, - 0xd1, 0x10, 0x54, 0xe1, 0x89, 0xef, 0x94, 0x78, 0x37, 0x34, 0xef, 0xc1, 0x4a, 0x5e, 0x03, 0x52, - 0x02, 0xbe, 0x0e, 0xe7, 0xcb, 0xbc, 0xf3, 0x8d, 0xb4, 0x60, 0x4b, 0xe7, 0xe9, 0x65, 0x34, 0x86, - 0xe6, 0xe0, 0xfa, 0x7f, 0x6e, 0xb0, 0x98, 0xee, 0x2e, 0xc0, 0x62, 0x3a, 0xbb, 0xc1, 0xff, 0x18, - 0xae, 0x51, 0x0c, 0xe7, 0xb6, 0x00, 0xeb, 0x8c, 0x01, 0x4b, 0x59, 0x34, 0xbf, 0x21, 0xf7, 0x21, - 0x6c, 0x97, 0xaa, 0x36, 0xf6, 0x16, 0xd4, 0x13, 0x5d, 0xb1, 0x91, 0xbb, 0x95, 0x91, 0xa6, 0x69, - 0x39, 0xcf, 0x76, 0xf5, 0xbf, 0x6c, 0xc2, 0x96, 0xf6, 0xc5, 0xef, 0x10, 0xc0, 0xe2, 0xd6, 0xf0, - 0x61, 0xa5, 0x51, 0xf5, 0xf3, 0x69, 0x5f, 0x5b, 0x4f, 0x6c, 0x98, 0x5d, 0xef, 0xcd, 0xd7, 0x9f, - 0xef, 0x37, 0x5c, 0xdc, 0xa1, 0x55, 0xcf, 0x7c, 0xe9, 0x8d, 0xe0, 0x0f, 0x08, 0x1a, 0x85, 0x01, - 0xee, 0xae, 0x91, 0x32, 0x27, 0x3a, 0x5c, 0x4b, 0x6b, 0x81, 0x8e, 0x34, 0x50, 0x17, 0x7b, 0xab, - 0x80, 0xe8, 0x4b, 0x7d, 0x78, 0x85, 0x5f, 0x23, 0xa8, 0x9b, 0xa5, 0xe2, 0x83, 0x7f, 0x27, 0x95, - 0x6e, 0xb0, 0xed, 0xad, 0x16, 0x5a, 0x9e, 0x7d, 0xcd, 0x73, 0x19, 0xef, 0x56, 0xf2, 0x98, 0x9b, - 0x3b, 0xbe, 0x79, 0x36, 0x75, 0xd0, 0x64, 0xea, 0xa0, 0x1f, 0x53, 0x07, 0xbd, 0x9d, 0x39, 0xb5, - 0xc9, 0xcc, 0xa9, 0x7d, 0x9b, 0x39, 0xb5, 0x47, 0xfb, 0x41, 0xa8, 0x9e, 0x8e, 0x7d, 0x32, 0x12, - 0xd1, 0xb2, 0xc1, 0x0b, 0x6b, 0xa1, 0x4e, 0x13, 0x2e, 0xfd, 0xba, 0xfe, 0x4b, 0xb8, 0xf1, 0x3b, - 0x00, 0x00, 0xff, 0xff, 0xdc, 0xca, 0x86, 0x63, 0x01, 0x05, 0x00, 0x00, + // 528 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0x41, 0x6b, 0x13, 0x41, + 0x14, 0xc7, 0x33, 0x2d, 0x2d, 0xe4, 0xe5, 0xe4, 0x34, 0x6a, 0x49, 0x75, 0x1b, 0xb7, 0x60, 0xc3, + 0xc6, 0xce, 0x98, 0xf4, 0x5c, 0x0f, 0x3d, 0xa8, 0x78, 0x8a, 0x41, 0x2f, 0x5e, 0x74, 0x36, 0x0c, + 0xeb, 0xa2, 0xbb, 0xb3, 0xdd, 0x99, 0x2c, 0x16, 0x11, 0xc4, 0x4f, 0xa0, 0x78, 0xf2, 0x1b, 0x78, + 0x12, 0xcf, 0x7e, 0x82, 0x1e, 0x0b, 0x5e, 0x3c, 0x89, 0x24, 0x82, 0x5f, 0x43, 0x76, 0x66, 0xb2, + 0xc9, 0xea, 0x4a, 0xe2, 0x25, 0xec, 0x3c, 0xfe, 0xef, 0xff, 0xff, 0xbd, 0x37, 0x43, 0x60, 0x77, + 0x24, 0x64, 0x24, 0x24, 0xe5, 0x59, 0x44, 0x79, 0x3a, 0xea, 0xdf, 0xa4, 0x59, 0x8f, 0x9e, 0x8c, + 0x79, 0x7a, 0x4a, 0x92, 0x54, 0x28, 0x81, 0xb7, 0x8c, 0x80, 0xf0, 0x2c, 0x22, 0x5a, 0x40, 0xb2, + 0x5e, 0xeb, 0x02, 0x8b, 0xc2, 0x58, 0x50, 0xfd, 0x6b, 0x74, 0x2d, 0xcf, 0x1a, 0xf9, 0x4c, 0x72, + 0x63, 0x40, 0xb3, 0x9e, 0xcf, 0x15, 0xeb, 0xd1, 0x84, 0x05, 0x61, 0xcc, 0x54, 0x28, 0x62, 0xab, + 0xad, 0x0c, 0x35, 0xe6, 0x46, 0x70, 0xad, 0x4a, 0x10, 0xf0, 0x98, 0xcb, 0x50, 0x5a, 0x49, 0x33, + 0x10, 0x81, 0xd0, 0x9f, 0x34, 0xff, 0xb2, 0xd5, 0x2b, 0x81, 0x10, 0xc1, 0x73, 0x4e, 0x59, 0x12, + 0x52, 0x16, 0xc7, 0x42, 0xe9, 0x58, 0xdb, 0xe3, 0x3e, 0x81, 0x4b, 0xf7, 0x73, 0xb2, 0x07, 0xe2, + 0x19, 0x8f, 0x07, 0x2c, 0x4c, 0xe5, 0x90, 0x9f, 0x8c, 0xb9, 0x54, 0xf8, 0x36, 0xc0, 0x9c, 0x72, + 0x1b, 0xb5, 0x51, 0xa7, 0xd1, 0xbf, 0x4e, 0xec, 0xe8, 0xf9, 0x48, 0xc4, 0xec, 0xc4, 0x8e, 0x44, + 0x06, 0x2c, 0xe0, 0xb6, 0x77, 0xb8, 0xd0, 0xe9, 0x7e, 0x42, 0x70, 0xf9, 0xaf, 0x08, 0x99, 0x88, + 0x58, 0x72, 0x7c, 0x0f, 0x1a, 0x2a, 0xaf, 0x3e, 0x4e, 0xf2, 0xf2, 0x36, 0x6a, 0xaf, 0x77, 0x1a, + 0x7d, 0x87, 0x54, 0xec, 0x97, 0x14, 0xdd, 0xc7, 0xf5, 0xb3, 0xef, 0xbb, 0xb5, 0x8f, 0xbf, 0x3e, + 0x7b, 0x68, 0x08, 0xaa, 0xf0, 0xc4, 0x77, 0x4a, 0xbc, 0x6b, 0x9a, 0x77, 0x7f, 0x29, 0xaf, 0x01, + 0x29, 0x01, 0x1f, 0xc0, 0xc5, 0x32, 0xef, 0x6c, 0x23, 0x4d, 0xd8, 0xd0, 0x79, 0x7a, 0x19, 0xf5, + 0xa1, 0x39, 0xb8, 0xfe, 0x9f, 0x1b, 0x2c, 0xa6, 0xbb, 0x0b, 0x30, 0x9f, 0xce, 0x6e, 0xf0, 0x3f, + 0x86, 0xab, 0x17, 0xc3, 0xb9, 0x4d, 0xc0, 0x3a, 0x63, 0xc0, 0x52, 0x16, 0xcd, 0x6e, 0xc8, 0x7d, + 0x08, 0x5b, 0xa5, 0xaa, 0x8d, 0xbd, 0x05, 0x9b, 0x89, 0xae, 0xd8, 0xc8, 0x9d, 0xca, 0x48, 0xd3, + 0xb4, 0x98, 0x67, 0xbb, 0xfa, 0x5f, 0xd6, 0x61, 0x43, 0xfb, 0xe2, 0x77, 0x08, 0x60, 0x7e, 0x6b, + 0xb8, 0x5b, 0x69, 0x54, 0xfd, 0x7c, 0x5a, 0x37, 0x56, 0x13, 0x1b, 0x66, 0xb7, 0xf3, 0xe6, 0xeb, + 0xcf, 0xf7, 0x6b, 0x2e, 0x6e, 0xd3, 0xaa, 0x67, 0xbe, 0xf0, 0x46, 0xf0, 0x07, 0x04, 0xf5, 0xc2, + 0x00, 0x7b, 0x2b, 0xa4, 0xcc, 0x88, 0xba, 0x2b, 0x69, 0x2d, 0xd0, 0xa1, 0x06, 0x3a, 0xc0, 0xdd, + 0x65, 0x40, 0xf4, 0xa5, 0x3e, 0x1c, 0x79, 0xde, 0x2b, 0xfc, 0x1a, 0xc1, 0xa6, 0xd9, 0x2b, 0xde, + 0xff, 0x77, 0x58, 0xe9, 0x12, 0x5b, 0x9d, 0xe5, 0x42, 0x8b, 0xb4, 0xa7, 0x91, 0xae, 0xe2, 0x9d, + 0x4a, 0x24, 0x73, 0x79, 0xc7, 0x47, 0x67, 0x13, 0x07, 0x9d, 0x4f, 0x1c, 0xf4, 0x63, 0xe2, 0xa0, + 0xb7, 0x53, 0xa7, 0x76, 0x3e, 0x75, 0x6a, 0xdf, 0xa6, 0x4e, 0xed, 0xd1, 0x5e, 0x10, 0xaa, 0xa7, + 0x63, 0x9f, 0x8c, 0x44, 0xb4, 0x68, 0xf0, 0xc2, 0x5a, 0xa8, 0xd3, 0x84, 0x4b, 0x7f, 0x53, 0xff, + 0x2b, 0x1c, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xa9, 0xe7, 0x87, 0x8b, 0x04, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -373,9 +373,9 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { - // TokenPairs retrieves registered token pairs + // TokenPairs retrieves registered token pairs (mappings)x TokenPairs(ctx context.Context, in *QueryTokenPairsRequest, opts ...grpc.CallOption) (*QueryTokenPairsResponse, error) - // TokenPair retrieves a registered token pair + // TokenPair retrieves a registered token pair (mapping) TokenPair(ctx context.Context, in *QueryTokenPairRequest, opts ...grpc.CallOption) (*QueryTokenPairResponse, error) // Params retrieves the erc20 module params Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) @@ -418,9 +418,9 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . // QueryServer is the server API for Query service. type QueryServer interface { - // TokenPairs retrieves registered token pairs + // TokenPairs retrieves registered token pairs (mappings)x TokenPairs(context.Context, *QueryTokenPairsRequest) (*QueryTokenPairsResponse, error) - // TokenPair retrieves a registered token pair + // TokenPair retrieves a registered token pair (mapping) TokenPair(context.Context, *QueryTokenPairRequest) (*QueryTokenPairResponse, error) // Params retrieves the erc20 module params Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) diff --git a/x/erc20/types/query.pb.gw.go b/x/erc20/types/query.pb.gw.go index 2a3ad976b..18dafd224 100644 --- a/x/erc20/types/query.pb.gw.go +++ b/x/erc20/types/query.pb.gw.go @@ -323,7 +323,7 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie var ( pattern_Query_TokenPairs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "evm", "erc20", "v1", "token_pairs"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_TokenPair_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "evm", "erc20", "v1", "token_pairs", "token"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_TokenPair_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 3, 0, 4, 1, 5, 5}, []string{"cosmos", "evm", "erc20", "v1", "token_pairs", "token"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "evm", "erc20", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) diff --git a/x/ibc/transfer/keeper/keeper.go b/x/ibc/transfer/keeper/keeper.go index 4ec2e6249..48b150803 100644 --- a/x/ibc/transfer/keeper/keeper.go +++ b/x/ibc/transfer/keeper/keeper.go @@ -9,7 +9,6 @@ import ( corestore "cosmossdk.io/core/store" "github.com/cosmos/cosmos-sdk/codec" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) // Keeper defines the modified IBC transfer keeper that embeds the original one. @@ -26,7 +25,6 @@ type Keeper struct { func NewKeeper( cdc codec.BinaryCodec, storeService corestore.KVStoreService, - paramSpace paramtypes.Subspace, ics4Wrapper porttypes.ICS4Wrapper, channelKeeper transfertypes.ChannelKeeper, @@ -38,7 +36,7 @@ func NewKeeper( ) Keeper { // create the original IBC transfer keeper for embedding transferKeeper := keeper.NewKeeper( - cdc, storeService, paramSpace, + cdc, storeService, nil, ics4Wrapper, channelKeeper, msgRouter, authKeeper, bankKeeper, authority, ) diff --git a/x/precisebank/types/mocks/MockBankKeeper.go b/x/precisebank/types/mocks/MockBankKeeper.go index 80ee7f305..c82096a1d 100644 --- a/x/precisebank/types/mocks/MockBankKeeper.go +++ b/x/precisebank/types/mocks/MockBankKeeper.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package mocks @@ -862,8 +862,7 @@ func (_c *BankKeeper_SpendableCoin_Call) RunAndReturn(run func(context.Context, func NewBankKeeper(t interface { mock.TestingT Cleanup(func()) -}, -) *BankKeeper { +}) *BankKeeper { mock := &BankKeeper{} mock.Mock.Test(t) diff --git a/x/vm/keeper/abci.go b/x/vm/keeper/abci.go index 6833c963d..558c230be 100644 --- a/x/vm/keeper/abci.go +++ b/x/vm/keeper/abci.go @@ -31,6 +31,8 @@ func (k *Keeper) BeginBlock(ctx sdk.Context) error { ), }) } + + k.SetHeaderHash(ctx) return nil } @@ -41,7 +43,7 @@ func (k *Keeper) EndBlock(ctx sdk.Context) error { // Gas costs are handled within msg handler so costs should be ignored infCtx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) - if k.evmMempool != nil { + if k.evmMempool != nil && !k.evmMempool.HasEventBus() { k.evmMempool.GetBlockchain().NotifyNewBlock() } diff --git a/x/vm/keeper/config.go b/x/vm/keeper/config.go index dbbe308ba..c957bee34 100644 --- a/x/vm/keeper/config.go +++ b/x/vm/keeper/config.go @@ -35,10 +35,9 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress) (*s // TxConfig loads `TxConfig` from current transient storage func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig { return statedb.NewTxConfig( - common.BytesToHash(ctx.HeaderHash()), // BlockHash - txHash, // TxHash - uint(k.GetTxIndexTransient(ctx)), // TxIndex - uint(k.GetLogSizeTransient(ctx)), // LogIndex + txHash, // TxHash + uint(k.GetTxIndexTransient(ctx)), // TxIndex + uint(k.GetLogSizeTransient(ctx)), // LogIndex ) } diff --git a/x/vm/keeper/grpc_query.go b/x/vm/keeper/grpc_query.go index eb895079c..a748d29d6 100644 --- a/x/vm/keeper/grpc_query.go +++ b/x/vm/keeper/grpc_query.go @@ -251,7 +251,7 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms } msg := args.ToMessage(cfg.BaseFee, false, false) - txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig() // pass false to not commit StateDB res, err := k.ApplyMessageWithConfig(ctx, *msg, nil, false, cfg, txConfig, false) @@ -324,7 +324,7 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest nonce := k.GetNonce(ctx, args.GetFrom()) args.Nonce = (*hexutil.Uint64)(&nonce) - txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig() if args.Gas == nil { args.Gas = new(hexutil.Uint64) @@ -404,20 +404,32 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest return len(rsp.VmError) > 0, rsp, nil } - // Execute the binary search and hone in on an executable gas limit - hi, err = types.BinSearch(lo, hi, executable) - if err != nil { - return nil, err - } + // Adapted from go-ethereum gas estimator for early short-circuit and optimistic bounds: + // https://github.com/ethereum/go-ethereum/blob/v1.16.2/eth/gasestimator/gasestimator.go - // Reject the transaction as invalid if it still fails at the highest allowance - if hi == gasCap { - failed, result, err := executable(hi) - if err != nil { - return nil, err + // If the transaction is a plain value transfer, short circuit estimation and + // directly try 21000. Returning 21000 without any execution is dangerous as + // some tx field combos might bump the price up even for plain transfers (e.g. + // unused access list items). Ever so slightly wasteful, but safer overall. + if len(msg.Data) == 0 && msg.To != nil { + acct := k.GetAccountWithoutBalance(ctx, *msg.To) + if acct == nil || !acct.IsContract() { + failed, _, err := executable(ethparams.TxGas) + if err == nil && !failed { + return &types.EstimateGasResponse{Gas: ethparams.TxGas}, nil + } } + } - if failed { + // We first execute the transaction at the highest allowable gas limit, since if this fails we + // can return error immediately. + failed, result, err := executable(hi) + if err != nil { + return nil, err + } + if failed { + // Preserve Cosmos error semantics when the cap is reached + if hi == gasCap { if result != nil && result.VmError != vm.ErrOutOfGas.Error() { if result.VmError == vm.ErrExecutionReverted.Error() { return &types.EstimateGasResponse{ @@ -427,10 +439,34 @@ func (k Keeper) EstimateGasInternal(c context.Context, req *types.EthCallRequest } return nil, errors.New(result.VmError) } - // Otherwise, the specified gas cap is too low return nil, fmt.Errorf("gas required exceeds allowance (%d)", gasCap) } + // If no larger allowance is available, fail fast + return nil, fmt.Errorf("gas required exceeds allowance (%d)", hi) + } + + // There's a fairly high chance for the transaction to execute successfully + // with gasLimit set to the first execution's usedGas + gasRefund. Explicitly + // check that gas amount and use as a limit for the binary search. + optimisticGasLimit := (result.MaxUsedGas + ethparams.CallStipend) * 64 / 63 + if optimisticGasLimit < hi { + failed, _, err = executable(optimisticGasLimit) + if err != nil { + return nil, err + } + if failed { + lo = optimisticGasLimit + } else { + hi = optimisticGasLimit + } } + + // Binary search for the smallest gas limit that allows the tx to execute successfully. + hi, err = types.BinSearch(lo, hi, executable) + if err != nil { + return nil, err + } + return &types.EstimateGasResponse{Gas: hi}, nil } @@ -488,7 +524,7 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ } signer := ethtypes.MakeSigner(types.GetEthChainConfig(), big.NewInt(ctx.BlockHeight()), uint64(ctx.BlockTime().Unix())) //#nosec G115 -- int overflow is not a concern here - txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig() // gas used at this point corresponds to GetProposerAddress & CalculateBaseFee // need to reset gas meter per transaction to be consistent with tx execution @@ -582,7 +618,7 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) txsLength := len(req.Txs) results := make([]*types.TxTraceResult, 0, txsLength) - txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig() for i, tx := range req.Txs { result := types.TxTraceResult{} @@ -662,7 +698,7 @@ func (k *Keeper) traceTx( } tCtx := &tracers.Context{ - BlockHash: txConfig.BlockHash, + BlockHash: common.BytesToHash(ctx.HeaderHash()), TxIndex: int(txConfig.TxIndex), //#nosec G115 -- int overflow is not a concern here TxHash: txConfig.TxHash, } diff --git a/x/vm/keeper/keeper.go b/x/vm/keeper/keeper.go index dbed35ee6..301c0f8be 100644 --- a/x/vm/keeper/keeper.go +++ b/x/vm/keeper/keeper.go @@ -1,6 +1,7 @@ package keeper import ( + "encoding/binary" "math/big" "github.com/ethereum/go-ethereum/common" @@ -8,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/core/tracing" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/params" + ethparams "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" evmmempool "github.com/cosmos/evm/mempool" @@ -58,7 +59,7 @@ type Keeper struct { stakingKeeper types.StakingKeeper // fetch EIP1559 base fee and parameters feeMarketWrapper *wrappers.FeeMarketWrapper - // erc20Keeper interface needed to instantiate erc20 precompiles + // optional erc20Keeper interface needed to instantiate erc20 precompiles erc20Keeper types.Erc20Keeper // consensusKeeper is used to get consensus params during query contexts. // This is needed as block.gasLimit is expected to be available in eth_call, which is routed through Cosmos SDK's @@ -216,6 +217,11 @@ func (k *Keeper) PostTxProcessing( return k.hooks.PostTxProcessing(ctx, sender, msg, receipt) } +// HasHooks returns true if hooks are set +func (k *Keeper) HasHooks() bool { + return k.hooks != nil +} + // ---------------------------------------------------------------------------- // Log // ---------------------------------------------------------------------------- @@ -254,7 +260,7 @@ func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) types // ---------------------------------------------------------------------------- // Tracer return a default vm.Tracer based on current keeper state -func (k Keeper) Tracer(ctx sdk.Context, msg core.Message, ethCfg *params.ChainConfig) *tracing.Hooks { +func (k Keeper) Tracer(ctx sdk.Context, msg core.Message, ethCfg *ethparams.ChainConfig) *tracing.Hooks { return types.NewTracer(k.tracer, msg, ethCfg, ctx.BlockHeight(), uint64(ctx.BlockTime().Unix())) //#nosec G115 -- int overflow is not a concern here } @@ -401,3 +407,35 @@ func (k *Keeper) SetEvmMempool(evmMempool *evmmempool.ExperimentalEVMMempool) { func (k Keeper) GetEvmMempool() *evmmempool.ExperimentalEVMMempool { return k.evmMempool } + +// SetHeaderHash sets current block hash into EIP-2935 compatible storage contract. +func (k Keeper) SetHeaderHash(ctx sdk.Context) { + window := uint64(types.DefaultHistoryServeWindow) + params := k.GetParams(ctx) + if params.HistoryServeWindow > 0 { + window = params.HistoryServeWindow + } + + acct := k.GetAccount(ctx, ethparams.HistoryStorageAddress) + if acct != nil && acct.IsContract() { + // set current block hash in the contract storage, compatible with EIP-2935 + ringIndex := uint64(ctx.BlockHeight()) % window //nolint:gosec // G115 // won't exceed uint64 + var key common.Hash + binary.BigEndian.PutUint64(key[24:], ringIndex) + k.SetState(ctx, ethparams.HistoryStorageAddress, key, ctx.HeaderHash()) + } +} + +// GetHeaderHash sets block hash into EIP-2935 compatible storage contract. +func (k Keeper) GetHeaderHash(ctx sdk.Context, height uint64) common.Hash { + window := uint64(types.DefaultHistoryServeWindow) + params := k.GetParams(ctx) + if params.HistoryServeWindow > 0 { + window = params.HistoryServeWindow + } + + ringIndex := height % window + var key common.Hash + binary.BigEndian.PutUint64(key[24:], ringIndex) + return k.GetState(ctx, ethparams.HistoryStorageAddress, key) +} diff --git a/x/vm/keeper/keeper_test.go b/x/vm/keeper/keeper_test.go index 00197db39..7e2a2f42f 100644 --- a/x/vm/keeper/keeper_test.go +++ b/x/vm/keeper/keeper_test.go @@ -33,7 +33,6 @@ import ( distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -59,7 +58,7 @@ func (suite *KeeperTestSuite) SetupTest() { keys := storetypes.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.StoreKey, + govtypes.StoreKey, consensusparamtypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, authzkeeper.StoreKey, // ibc keys ibcexported.StoreKey, ibctransfertypes.StoreKey, diff --git a/x/vm/keeper/msg_server.go b/x/vm/keeper/msg_server.go index 3165fe69a..27cebf57a 100644 --- a/x/vm/keeper/msg_server.go +++ b/x/vm/keeper/msg_server.go @@ -3,7 +3,6 @@ package keeper import ( "context" "encoding/hex" - "encoding/json" "fmt" "strconv" @@ -99,25 +98,12 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyEthereumTxFailed, response.VmError)) } - txLogAttrs := make([]sdk.Attribute, len(response.Logs)) - for i, log := range response.Logs { - value, err := json.Marshal(log) - if err != nil { - return nil, errorsmod.Wrap(err, "failed to encode log") - } - txLogAttrs[i] = sdk.NewAttribute(types.AttributeKeyTxLog, string(value)) - } - // emit events ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeEthereumTx, attrs..., ), - sdk.NewEvent( - types.EventTypeTxLog, - txLogAttrs..., - ), sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), diff --git a/x/vm/keeper/precompiles.go b/x/vm/keeper/precompiles.go index a730b834b..10db8b57f 100644 --- a/x/vm/keeper/precompiles.go +++ b/x/vm/keeper/precompiles.go @@ -33,6 +33,11 @@ func (k *Keeper) GetPrecompileInstance( }, found, nil } + // Since erc20Keeper is optional, we check if it is nil, in which case we just return that we didn't find the precompile + if k.erc20Keeper == nil { + return nil, false, nil + } + // Get the precompile from the dynamic precompiles precompile, found, err := k.erc20Keeper.GetERC20PrecompileInstance(ctx, address) if err != nil || !found { diff --git a/x/vm/keeper/state_transition.go b/x/vm/keeper/state_transition.go index e03e922e7..fafa49463 100644 --- a/x/vm/keeper/state_transition.go +++ b/x/vm/keeper/state_transition.go @@ -112,23 +112,11 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { return common.BytesToHash(headerHash) case ctx.BlockHeight() > h: - // Case 2: if the chain is not the current height we need to retrieve the hash from the store for the - // current chain epoch. This only applies if the current height is greater than the requested height. - histInfo, err := k.stakingKeeper.GetHistoricalInfo(ctx, h) - if err != nil { - k.Logger(ctx).Debug("error while getting historical info", "height", h, "error", err.Error()) - return common.Hash{} - } - - header, err := cmttypes.HeaderFromProto(&histInfo.Header) - if err != nil { - k.Logger(ctx).Error("failed to cast CometBFT header from proto", "error", err) - return common.Hash{} - } - - return common.BytesToHash(header.Hash()) + // Case 2: The requested height is historical, query EIP-2935 contract storage for that + // see: https://github.com/cosmos/evm/issues/406 + return k.GetHeaderHash(ctx, height) default: - // Case 3: heights greater than the current one returns an empty hash. + // Case 3: The requested height is greater than the latest one, return empty hash return common.Hash{} } } @@ -205,36 +193,54 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t ethLogs := types.LogsToEthereum(res.Logs) _, bloomReceipt := k.initializeBloomFromLogs(ctx, ethLogs) - if !res.Failed() { - var contractAddr common.Address - if msg.To == nil { - contractAddr = crypto.CreateAddress(msg.From, msg.Nonce) - } + var contractAddr common.Address + if msg.To == nil { + contractAddr = crypto.CreateAddress(msg.From, msg.Nonce) + } - receipt := ðtypes.Receipt{ - Type: tx.Type(), - PostState: nil, - CumulativeGasUsed: calculateCumulativeGasFromEthResponse(ctx.GasMeter(), res), - Bloom: bloomReceipt, - Logs: ethLogs, - TxHash: txConfig.TxHash, - ContractAddress: contractAddr, - GasUsed: res.GasUsed, - BlockHash: txConfig.BlockHash, - BlockNumber: big.NewInt(ctx.BlockHeight()), - TransactionIndex: txConfig.TxIndex, - } + receipt := ðtypes.Receipt{ + Type: tx.Type(), + PostState: nil, + CumulativeGasUsed: calculateCumulativeGasFromEthResponse(ctx.GasMeter(), res), + Bloom: bloomReceipt, + Logs: ethLogs, + TxHash: txConfig.TxHash, + ContractAddress: contractAddr, + GasUsed: res.GasUsed, + BlockHash: common.BytesToHash(ctx.HeaderHash()), + BlockNumber: big.NewInt(ctx.BlockHeight()), + TransactionIndex: txConfig.TxIndex, + } - signerAddr, err := signer.Sender(tx) - if err != nil { - return nil, errorsmod.Wrap(err, "failed to extract sender address from ethereum transaction") - } + if res.Failed() { + receipt.Status = ethtypes.ReceiptStatusFailed - eventsLen := len(tmpCtx.EventManager().Events()) + // If the tx failed we discard the old context and create a new one, so + // PostTxProcessing can persist data even if the tx fails. + tmpCtx, commitFn = ctx.CacheContext() + } else { + receipt.Status = ethtypes.ReceiptStatusSuccessful + } + + signerAddr, err := signer.Sender(tx) + if err != nil { + return nil, errorsmod.Wrap(err, "failed to extract sender address from ethereum transaction") + } + + eventsLen := len(tmpCtx.EventManager().Events()) + // Only call PostTxProcessing if there are hooks set, to avoid calling commitFn unnecessarily + if !k.HasHooks() { + // If there are no hooks, we can commit the state immediately if the tx is successful + if commitFn != nil && !res.Failed() { + commitFn() + } + } else { // Note: PostTxProcessing hooks currently do not charge for gas - // and function similar to EndBlockers in abci, but for EVM transactions - if err = k.PostTxProcessing(tmpCtx, signerAddr, *msg, receipt); err != nil { + // and function similar to EndBlockers in abci, but for EVM transactions. + // It will persist data even if the tx fails. + err = k.PostTxProcessing(tmpCtx, signerAddr, *msg, receipt) + if err != nil { // If hooks returns an error, revert the whole tx. res.VmError = errorsmod.Wrap(err, "failed to execute post transaction processing").Error() k.Logger(ctx).Error("tx post processing failed", "error", err) @@ -243,11 +249,20 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t res.Logs = nil receipt.Logs = nil receipt.Bloom = ethtypes.Bloom{} // Clear bloom filter - } else if commitFn != nil { - commitFn() + } else { + if commitFn != nil { + commitFn() + } // Since the post-processing can alter the log, we need to update the result - res.Logs = types.NewLogsFromEth(receipt.Logs) + if res.Failed() { + res.Logs = nil + receipt.Logs = nil + receipt.Bloom = ethtypes.Bloom{} + } else { + res.Logs = types.NewLogsFromEth(receipt.Logs) + } + events := tmpCtx.EventManager().Events() if len(events) > eventsLen { ctx.EventManager().EmitEvents(events[eventsLen:]) @@ -293,7 +308,7 @@ func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer *tracing return nil, errorsmod.Wrap(err, "failed to load evm config") } - txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig() return k.ApplyMessageWithConfig(ctx, msg, tracer, commit, cfg, txConfig, internal) } @@ -379,7 +394,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, trace return nil, errorsmod.Wrap(core.ErrIntrinsicGas, "apply message") } // Gas limit suffices for the floor data cost (EIP-7623) - rules := ethCfg.Rules(big.NewInt(ctx.BlockHeight()), true, uint64(ctx.BlockTime().Unix())) //#nosec G115 -- int overflow is not a concern here + rules := ethCfg.Rules(evm.Context.BlockNumber, true, evm.Context.Time) if rules.IsPrague { floorDataGas, err := core.FloorDataGas(msg.Data) if err != nil { @@ -445,12 +460,12 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, trace return nil, errorsmod.Wrap(types.ErrGasOverflow, "apply message") } // refund gas - temporaryGasUsed := msg.GasLimit - leftoverGas - refund := GasToRefund(stateDB.GetRefund(), temporaryGasUsed, refundQuotient) + maxUsedGas := msg.GasLimit - leftoverGas + refund := GasToRefund(stateDB.GetRefund(), maxUsedGas, refundQuotient) // update leftoverGas and temporaryGasUsed with refund amount leftoverGas += refund - temporaryGasUsed -= refund + temporaryGasUsed := maxUsedGas - refund // EVM execution error needs to be available for the JSON-RPC client var vmError string @@ -491,13 +506,15 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, trace if vmError == vm.ErrExecutionReverted.Error() { ret = evm.Interpreter().ReturnData() } - return &types.MsgEthereumTxResponse{ - GasUsed: gasUsed.TruncateInt().Uint64(), - VmError: vmError, - Ret: ret, - Logs: types.NewLogsFromEth(stateDB.Logs()), - Hash: txConfig.TxHash.Hex(), + GasUsed: gasUsed.TruncateInt().Uint64(), + MaxUsedGas: maxUsedGas, + VmError: vmError, + Ret: ret, + Logs: types.NewLogsFromEth(stateDB.Logs()), + Hash: txConfig.TxHash.Hex(), + BlockHash: ctx.HeaderHash(), + BlockTimestamp: evm.Context.Time, }, nil } diff --git a/x/vm/statedb/config.go b/x/vm/statedb/config.go index e92152efa..c7bc3f351 100644 --- a/x/vm/statedb/config.go +++ b/x/vm/statedb/config.go @@ -10,30 +10,27 @@ import ( // TxConfig encapulates the readonly information of current tx for `StateDB`. type TxConfig struct { - BlockHash common.Hash // hash of current block - TxHash common.Hash // hash of current tx - TxIndex uint // the index of current transaction - LogIndex uint // the index of next log within current block + TxHash common.Hash // hash of current tx + TxIndex uint // the index of current transaction + LogIndex uint // the index of next log within current block } // NewTxConfig returns a TxConfig -func NewTxConfig(bhash, thash common.Hash, txIndex, logIndex uint) TxConfig { +func NewTxConfig(thash common.Hash, txIndex, logIndex uint) TxConfig { return TxConfig{ - BlockHash: bhash, - TxHash: thash, - TxIndex: txIndex, - LogIndex: logIndex, + TxHash: thash, + TxIndex: txIndex, + LogIndex: logIndex, } } // NewEmptyTxConfig construct an empty TxConfig, // used in context where there's no transaction, e.g. `eth_call`/`eth_estimateGas`. -func NewEmptyTxConfig(bhash common.Hash) TxConfig { +func NewEmptyTxConfig() TxConfig { return TxConfig{ - BlockHash: bhash, - TxHash: common.Hash{}, - TxIndex: 0, - LogIndex: 0, + TxHash: common.Hash{}, + TxIndex: 0, + LogIndex: 0, } } diff --git a/x/vm/statedb/state_object.go b/x/vm/statedb/state_object.go index a85bcb4df..876142c9b 100644 --- a/x/vm/statedb/state_object.go +++ b/x/vm/statedb/state_object.go @@ -8,8 +8,6 @@ import ( "github.com/holiman/uint256" "github.com/cosmos/evm/x/vm/types" - - sdk "github.com/cosmos/cosmos-sdk/types" ) // Account is the Ethereum consensus representation of accounts. @@ -136,16 +134,6 @@ func (s *stateObject) SetBalance(amount *uint256.Int) uint256.Int { return prev } -// AddPrecompileFn appends to the journal an entry -// with a snapshot of the multi-store and events -// previous to the precompile call -func (s *stateObject) AddPrecompileFn(snapshot int, events sdk.Events) { - s.db.journal.append(precompileCallChange{ - snapshot: snapshot, - events: events, - }) -} - func (s *stateObject) setBalance(amount *uint256.Int) { s.account.Balance = amount } diff --git a/x/vm/statedb/statedb.go b/x/vm/statedb/statedb.go index cce997d66..1c4a7395d 100644 --- a/x/vm/statedb/statedb.go +++ b/x/vm/statedb/statedb.go @@ -104,6 +104,15 @@ func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash { return sr.Hash() } +func (s *StateDB) IsStorageEmpty(addr common.Address) bool { + empty := true + s.keeper.ForEachStorage(s.ctx, addr, func(key, value common.Hash) bool { + empty = false + return false + }) + return empty +} + /* PointCache, Witness, and AccessEvents are all utilized for verkle trees. For now, we just return nil and verkle trees are not supported. @@ -209,8 +218,6 @@ func (s *StateDB) cache() error { func (s *StateDB) AddLog(log *ethtypes.Log) { s.journal.append(addLogChange{}) - log.TxHash = s.txConfig.TxHash - log.BlockHash = s.txConfig.BlockHash log.TxIndex = s.txConfig.TxIndex log.Index = s.txConfig.LogIndex + uint(len(s.logs)) s.logs = append(s.logs, log) @@ -425,12 +432,11 @@ func (s *StateDB) setStateObject(object *stateObject) { // AddPrecompileFn adds a precompileCall journal entry // with a snapshot of the multi-store and events previous // to the precompile call. -func (s *StateDB) AddPrecompileFn(addr common.Address, snapshot int, events sdk.Events) error { - stateObject := s.getOrNewStateObject(addr) - if stateObject == nil { - return fmt.Errorf("could not add precompile call to address %s. State object not found", addr) - } - stateObject.AddPrecompileFn(snapshot, events) +func (s *StateDB) AddPrecompileFn(snapshot int, events sdk.Events) error { + s.journal.append(precompileCallChange{ + snapshot: snapshot, + events: events, + }) s.precompileCallsCounter++ if s.precompileCallsCounter > types.MaxPrecompileCalls { return fmt.Errorf("max calls to precompiles (%d) reached", types.MaxPrecompileCalls) diff --git a/x/vm/statedb/statedb_test.go b/x/vm/statedb/statedb_test.go index 07b54bf1c..cb75eb25a 100644 --- a/x/vm/statedb/statedb_test.go +++ b/x/vm/statedb/statedb_test.go @@ -24,8 +24,7 @@ var ( address common.Address = common.BigToAddress(big.NewInt(101)) address2 common.Address = common.BigToAddress(big.NewInt(102)) address3 common.Address = common.BigToAddress(big.NewInt(103)) - blockHash common.Hash = common.BigToHash(big.NewInt(9999)) - emptyTxConfig statedb.TxConfig = statedb.NewEmptyTxConfig(blockHash) + emptyTxConfig statedb.TxConfig = statedb.NewEmptyTxConfig() ) type StateDBTestSuite struct { @@ -587,7 +586,6 @@ func (suite *StateDBTestSuite) TestLog() { txHash := common.BytesToHash([]byte("tx")) // use a non-default tx config txConfig := statedb.NewTxConfig( - blockHash, txHash, 1, 1, ) @@ -605,8 +603,6 @@ func (suite *StateDBTestSuite) TestLog() { Topics: []common.Hash{}, Data: data, BlockNumber: 1, - BlockHash: blockHash, - TxHash: txHash, TxIndex: 1, Index: 1, } diff --git a/x/vm/types/call.go b/x/vm/types/call.go index 957084736..7c665180d 100644 --- a/x/vm/types/call.go +++ b/x/vm/types/call.go @@ -12,4 +12,4 @@ const ( // MaxPrecompileCalls is the maximum number of precompile // calls within a transaction. We want to limit this because // for each precompile tx we're creating a cached context -const MaxPrecompileCalls uint8 = 7 +const MaxPrecompileCalls uint8 = 20 diff --git a/x/vm/types/events.go b/x/vm/types/events.go index c54531cb1..fa0aab740 100644 --- a/x/vm/types/events.go +++ b/x/vm/types/events.go @@ -4,7 +4,6 @@ package types const ( EventTypeEthereumTx = TypeMsgEthereumTx EventTypeBlockBloom = "block_bloom" - EventTypeTxLog = "tx_log" EventTypeFeeMarket = "evm_fee_market" AttributeKeyBaseFee = "base_fee" diff --git a/x/vm/types/evm.pb.go b/x/vm/types/evm.pb.go index 567e4d472..e472085c9 100644 --- a/x/vm/types/evm.pb.go +++ b/x/vm/types/evm.pb.go @@ -64,9 +64,6 @@ type Params struct { EvmDenom string `protobuf:"bytes,1,opt,name=evm_denom,json=evmDenom,proto3" json:"evm_denom,omitempty" yaml:"evm_denom"` // extra_eips defines the additional EIPs for the vm.Config ExtraEIPs []int64 `protobuf:"varint,4,rep,packed,name=extra_eips,json=extraEips,proto3" json:"extra_eips,omitempty" yaml:"extra_eips"` - // allow_unprotected_txs defines if replay-protected (i.e non EIP155 - // signed) transactions can be executed on the state machine. - AllowUnprotectedTxs bool `protobuf:"varint,5,opt,name=allow_unprotected_txs,json=allowUnprotectedTxs,proto3" json:"allow_unprotected_txs,omitempty"` // evm_channels is the list of channel identifiers from EVM compatible chains EVMChannels []string `protobuf:"bytes,7,rep,name=evm_channels,json=evmChannels,proto3" json:"evm_channels,omitempty"` // access_control defines the permission policy of the EVM @@ -74,6 +71,7 @@ type Params struct { // active_static_precompiles defines the slice of hex addresses of the // precompiled contracts that are active ActiveStaticPrecompiles []string `protobuf:"bytes,9,rep,name=active_static_precompiles,json=activeStaticPrecompiles,proto3" json:"active_static_precompiles,omitempty"` + HistoryServeWindow uint64 `protobuf:"varint,10,opt,name=history_serve_window,json=historyServeWindow,proto3" json:"history_serve_window,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -123,13 +121,6 @@ func (m *Params) GetExtraEIPs() []int64 { return nil } -func (m *Params) GetAllowUnprotectedTxs() bool { - if m != nil { - return m.AllowUnprotectedTxs - } - return false -} - func (m *Params) GetEVMChannels() []string { if m != nil { return m.EVMChannels @@ -151,6 +142,13 @@ func (m *Params) GetActiveStaticPrecompiles() []string { return nil } +func (m *Params) GetHistoryServeWindow() uint64 { + if m != nil { + return m.HistoryServeWindow + } + return 0 +} + // AccessControl defines the permission policy of the EVM // for creating and calling contracts type AccessControl struct { @@ -531,6 +529,8 @@ type Log struct { // reorganisation. You must pay attention to this field if you receive logs // through a filter query. Removed bool `protobuf:"varint,9,opt,name=removed,proto3" json:"removed,omitempty"` + // block_timestamp is the timestamp of the block in which the transaction was + BlockTimestamp uint64 `protobuf:"varint,10,opt,name=block_timestamp,json=blockTimestamp,proto3" json:"blockTimestamp"` } func (m *Log) Reset() { *m = Log{} } @@ -629,6 +629,13 @@ func (m *Log) GetRemoved() bool { return false } +func (m *Log) GetBlockTimestamp() uint64 { + if m != nil { + return m.BlockTimestamp + } + return 0 +} + // TxResult stores results of Tx execution. type TxResult struct { // contract_address contains the ethereum address of the created contract (if @@ -942,132 +949,133 @@ func init() { func init() { proto.RegisterFile("cosmos/evm/vm/v1/evm.proto", fileDescriptor_d1129b8db63d55c7) } var fileDescriptor_d1129b8db63d55c7 = []byte{ - // 1988 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0x5d, 0x6f, 0x1b, 0xc7, - 0xd5, 0x16, 0xc5, 0x95, 0xb4, 0x1c, 0x52, 0xd4, 0x7a, 0x44, 0xc9, 0x34, 0xed, 0x68, 0xf9, 0xee, - 0xdb, 0x0b, 0xd5, 0x48, 0x25, 0x4b, 0x8e, 0x5a, 0xc3, 0xe9, 0x07, 0x44, 0x99, 0x69, 0xa5, 0xda, - 0x0e, 0x31, 0x54, 0x12, 0xa4, 0x68, 0xb1, 0x18, 0xee, 0x8e, 0x97, 0x1b, 0xee, 0xee, 0x10, 0x3b, - 0x4b, 0x86, 0xea, 0x2f, 0x08, 0x7c, 0x95, 0xfe, 0x00, 0x03, 0x01, 0x7a, 0x93, 0x4b, 0xff, 0x84, - 0x5e, 0x06, 0xbd, 0xca, 0x65, 0x51, 0xa0, 0x8b, 0x82, 0xbe, 0x08, 0xa0, 0x4b, 0xfd, 0x82, 0x62, - 0x3e, 0xf8, 0x29, 0x85, 0x55, 0x01, 0xc1, 0x9e, 0xe7, 0xcc, 0x39, 0xcf, 0x73, 0x66, 0xe6, 0xec, - 0xec, 0x59, 0x82, 0x8a, 0x43, 0x59, 0x48, 0xd9, 0x3e, 0xe9, 0x87, 0xfb, 0xfc, 0xef, 0x80, 0x8f, - 0xf6, 0xba, 0x31, 0x4d, 0x28, 0x34, 0xe4, 0xdc, 0x1e, 0xb7, 0xf0, 0xbf, 0x83, 0xca, 0x1d, 0x1c, - 0xfa, 0x11, 0xdd, 0x17, 0xff, 0x4a, 0xa7, 0x4a, 0xc9, 0xa3, 0x1e, 0x15, 0xc3, 0x7d, 0x3e, 0x92, - 0x56, 0xeb, 0x6d, 0x16, 0xac, 0x36, 0x70, 0x8c, 0x43, 0x06, 0x0f, 0x40, 0x8e, 0xf4, 0x43, 0xdb, - 0x25, 0x11, 0x0d, 0xcb, 0x99, 0x6a, 0x66, 0x37, 0x57, 0x2b, 0x5d, 0xa5, 0xa6, 0x71, 0x81, 0xc3, - 0xe0, 0xa9, 0x35, 0x9e, 0xb2, 0x90, 0x4e, 0xfa, 0xe1, 0x33, 0x3e, 0x84, 0xc7, 0x00, 0x90, 0x41, - 0x12, 0x63, 0x9b, 0xf8, 0x5d, 0x56, 0xd6, 0xaa, 0xd9, 0xdd, 0x6c, 0xcd, 0x1a, 0xa6, 0x66, 0xae, - 0xce, 0xad, 0xf5, 0xd3, 0x06, 0xbb, 0x4a, 0xcd, 0x3b, 0x8a, 0x60, 0xec, 0x68, 0xa1, 0x9c, 0x00, - 0x75, 0xbf, 0xcb, 0xe0, 0x21, 0xd8, 0xc2, 0x41, 0x40, 0xbf, 0xb4, 0x7b, 0x11, 0xcf, 0x88, 0x38, - 0x09, 0x71, 0xed, 0x64, 0xc0, 0xca, 0x2b, 0xd5, 0xcc, 0xae, 0x8e, 0x36, 0xc5, 0xe4, 0x27, 0x93, - 0xb9, 0xf3, 0x01, 0x8f, 0x29, 0xf0, 0x74, 0x9c, 0x36, 0x8e, 0x22, 0x12, 0xb0, 0xf2, 0x5a, 0x35, - 0xbb, 0x9b, 0xab, 0x6d, 0x0c, 0x53, 0x33, 0x5f, 0xff, 0xf4, 0xc5, 0x89, 0x32, 0xa3, 0x3c, 0xe9, - 0x87, 0x23, 0x00, 0xff, 0x04, 0x8a, 0xd8, 0x71, 0x08, 0x63, 0xb6, 0x43, 0xa3, 0x24, 0xa6, 0x41, - 0x59, 0xaf, 0x66, 0x76, 0xf3, 0x87, 0xe6, 0xde, 0xfc, 0xe6, 0xed, 0x1d, 0x0b, 0xbf, 0x13, 0xe9, - 0x56, 0xdb, 0xfa, 0x2e, 0x35, 0x97, 0x86, 0xa9, 0xb9, 0x3e, 0x63, 0x46, 0xeb, 0x78, 0x1a, 0xc2, - 0xa7, 0xe0, 0x1e, 0x76, 0x12, 0xbf, 0x4f, 0x6c, 0x96, 0xe0, 0xc4, 0x77, 0xec, 0x6e, 0x4c, 0x1c, - 0x1a, 0x76, 0xfd, 0x80, 0xb0, 0x72, 0x8e, 0xe7, 0x87, 0xee, 0x4a, 0x87, 0xa6, 0x98, 0x6f, 0x4c, - 0xa6, 0x9f, 0xde, 0x7f, 0xfd, 0xc3, 0xdb, 0x87, 0xdb, 0x53, 0xe7, 0x3b, 0xe0, 0x27, 0x2c, 0x4f, - 0xe5, 0x4c, 0xd3, 0x97, 0x8d, 0xec, 0x99, 0xa6, 0x67, 0x0d, 0xed, 0x4c, 0xd3, 0x57, 0x8d, 0x35, - 0xeb, 0x2f, 0x19, 0x30, 0x9b, 0x0b, 0x3c, 0x06, 0xab, 0x4e, 0x4c, 0x70, 0x42, 0xc4, 0xb1, 0xe5, - 0x0f, 0xff, 0xff, 0xbf, 0xac, 0xe9, 0xfc, 0xa2, 0x4b, 0x6a, 0x1a, 0x5f, 0x17, 0x52, 0x81, 0xf0, - 0x57, 0x40, 0x73, 0x70, 0x10, 0x94, 0x97, 0xff, 0x57, 0x02, 0x11, 0x66, 0xfd, 0x2b, 0x03, 0xee, - 0x5c, 0xf3, 0x80, 0x0e, 0xc8, 0xab, 0x3d, 0x4f, 0x2e, 0xba, 0x32, 0xb9, 0xe2, 0xe1, 0x83, 0x1f, - 0xe3, 0x16, 0xa4, 0x3f, 0x19, 0xa6, 0x26, 0x98, 0xe0, 0xab, 0xd4, 0x84, 0xb2, 0x7c, 0xa6, 0x88, - 0x2c, 0x04, 0xf0, 0xd8, 0x03, 0x3a, 0x60, 0x73, 0xf6, 0x60, 0xed, 0xc0, 0x67, 0x49, 0x79, 0x59, - 0xd4, 0xc4, 0xe3, 0x61, 0x6a, 0xce, 0x26, 0xf6, 0xdc, 0x67, 0xc9, 0x55, 0x6a, 0x56, 0x66, 0x58, - 0xa7, 0x23, 0x2d, 0x74, 0x07, 0xcf, 0x07, 0x58, 0xdf, 0x1a, 0x20, 0x7f, 0xd2, 0xc6, 0x7e, 0x74, - 0x42, 0xa3, 0x57, 0xbe, 0x07, 0xff, 0x08, 0x36, 0xda, 0x34, 0x24, 0x2c, 0x21, 0xd8, 0xb5, 0x5b, - 0x01, 0x75, 0x3a, 0xea, 0x89, 0x79, 0xfc, 0xcf, 0xd4, 0xdc, 0x92, 0x0b, 0x64, 0x6e, 0x67, 0xcf, - 0xa7, 0xfb, 0x21, 0x4e, 0xda, 0x7b, 0xa7, 0x11, 0x17, 0xdd, 0x96, 0xa2, 0x73, 0x91, 0x16, 0x2a, - 0x8e, 0x2d, 0x35, 0x6e, 0x80, 0x6d, 0x50, 0x74, 0x31, 0xb5, 0x5f, 0xd1, 0xb8, 0xa3, 0xc8, 0x97, - 0x05, 0x79, 0xed, 0x47, 0xc9, 0x87, 0xa9, 0x59, 0x78, 0x76, 0xfc, 0xf1, 0x47, 0x34, 0xee, 0x08, - 0x8a, 0xab, 0xd4, 0xdc, 0x92, 0x62, 0xb3, 0x44, 0x16, 0x2a, 0xb8, 0x98, 0x8e, 0xdd, 0xe0, 0x67, - 0xc0, 0x18, 0x3b, 0xb0, 0x5e, 0xb7, 0x4b, 0xe3, 0xa4, 0x9c, 0xe5, 0x0f, 0x5e, 0xed, 0x67, 0xc3, - 0xd4, 0x2c, 0x2a, 0xca, 0xa6, 0x9c, 0xb9, 0x4a, 0xcd, 0xbb, 0x73, 0xa4, 0x2a, 0xc6, 0x42, 0x45, - 0x45, 0xab, 0x5c, 0x61, 0x0b, 0x14, 0x88, 0xdf, 0x3d, 0x38, 0x7a, 0xa4, 0x16, 0xa0, 0x89, 0x05, - 0xfc, 0x66, 0xd1, 0x02, 0xf2, 0xf5, 0xd3, 0xc6, 0xc1, 0xd1, 0xa3, 0x51, 0xfe, 0x9b, 0xea, 0xda, - 0x98, 0x62, 0xb1, 0x50, 0x5e, 0x42, 0x99, 0xfc, 0x48, 0xe3, 0x48, 0x69, 0xac, 0xde, 0x56, 0xe3, - 0xe8, 0x26, 0x8d, 0xa3, 0x59, 0x8d, 0xa3, 0x59, 0x8d, 0x27, 0x4a, 0x63, 0xed, 0xb6, 0x1a, 0x4f, - 0x6e, 0xd2, 0x78, 0x32, 0xab, 0x21, 0x7d, 0x78, 0x31, 0xb5, 0x2e, 0xfe, 0x8c, 0xa3, 0xc4, 0xef, - 0x85, 0x4a, 0x46, 0xbf, 0x75, 0x31, 0xcd, 0x45, 0x5a, 0xa8, 0x38, 0xb6, 0x48, 0xf6, 0x0e, 0x28, - 0x39, 0x34, 0x62, 0x09, 0xb7, 0x45, 0xb4, 0x1b, 0x10, 0x25, 0x91, 0x13, 0x12, 0x4f, 0x16, 0x49, - 0xdc, 0x97, 0x12, 0x37, 0x85, 0x5b, 0x68, 0x73, 0xd6, 0x2c, 0xc5, 0x6c, 0x60, 0x74, 0x49, 0x42, - 0x62, 0xd6, 0xea, 0xc5, 0x9e, 0x12, 0x02, 0x42, 0xe8, 0x83, 0x45, 0x42, 0xaa, 0xac, 0xe6, 0x43, - 0x2d, 0xb4, 0x31, 0x31, 0x49, 0x81, 0xcf, 0x41, 0xd1, 0xe7, 0xaa, 0xad, 0x5e, 0xa0, 0xe8, 0xf3, - 0x82, 0xfe, 0x70, 0x11, 0xbd, 0x7a, 0x14, 0x66, 0x03, 0x2d, 0xb4, 0x3e, 0x32, 0x48, 0x6a, 0x17, - 0xc0, 0xb0, 0xe7, 0xc7, 0xb6, 0x17, 0x60, 0xc7, 0x27, 0xb1, 0xa2, 0x2f, 0x08, 0xfa, 0x9f, 0x2f, - 0xa2, 0xbf, 0x27, 0xe9, 0xaf, 0x07, 0x5b, 0xc8, 0xe0, 0xc6, 0xdf, 0x4a, 0x9b, 0x54, 0x69, 0x82, - 0x42, 0x8b, 0xc4, 0x81, 0x1f, 0x29, 0xfe, 0x75, 0xc1, 0xff, 0x68, 0x11, 0xbf, 0xaa, 0xa0, 0xe9, - 0x30, 0x0b, 0xe5, 0x25, 0x1c, 0x93, 0x06, 0x34, 0x72, 0xe9, 0x88, 0xf4, 0xce, 0xad, 0x49, 0xa7, - 0xc3, 0x2c, 0x94, 0x97, 0x50, 0x92, 0x7a, 0x60, 0x13, 0xc7, 0x31, 0xfd, 0x72, 0x6e, 0x43, 0xa0, - 0xe0, 0xfe, 0xc5, 0x22, 0xee, 0xd1, 0xe5, 0x7a, 0x3d, 0x9a, 0x5f, 0xae, 0xdc, 0x3a, 0xb3, 0x25, - 0x2e, 0x80, 0x5e, 0x8c, 0x2f, 0xe6, 0x74, 0x4a, 0xb7, 0xde, 0xf8, 0xeb, 0xc1, 0x16, 0x32, 0xb8, - 0x71, 0x46, 0xe5, 0x0b, 0x50, 0x0a, 0x49, 0xec, 0x11, 0x3b, 0x22, 0x09, 0xeb, 0x06, 0x7e, 0xa2, - 0x74, 0xb6, 0x6e, 0xfd, 0x1c, 0xdc, 0x14, 0x6e, 0x21, 0x28, 0xcc, 0x2f, 0x95, 0x55, 0x6a, 0xdd, - 0x03, 0xba, 0xc3, 0xdf, 0x16, 0xb6, 0xef, 0x96, 0xcb, 0xd5, 0xcc, 0xae, 0x86, 0xd6, 0x04, 0x3e, - 0x75, 0x61, 0x09, 0xac, 0xc8, 0x0e, 0xeb, 0x1e, 0xd7, 0x45, 0x12, 0xc0, 0x0a, 0xd0, 0x5d, 0xe2, - 0xf8, 0x21, 0x0e, 0x58, 0xb9, 0x22, 0x02, 0xc6, 0x18, 0x7e, 0x0a, 0xd6, 0x59, 0x1b, 0x47, 0x5e, - 0x1b, 0xfb, 0x76, 0xe2, 0x87, 0xa4, 0x7c, 0x5f, 0x64, 0x7c, 0xb0, 0x28, 0xe3, 0x92, 0xcc, 0x78, - 0x26, 0xce, 0x42, 0x85, 0x11, 0x3e, 0xf7, 0x43, 0x02, 0x1b, 0x20, 0xef, 0xe0, 0xc8, 0xe9, 0x45, - 0x92, 0xf5, 0x81, 0x60, 0xdd, 0x5f, 0xc4, 0xaa, 0x5e, 0xc5, 0x53, 0x51, 0x16, 0x02, 0x12, 0x8d, - 0x18, 0xbb, 0x31, 0xf6, 0x7a, 0x44, 0x32, 0xbe, 0x77, 0x6b, 0xc6, 0xa9, 0x28, 0x0b, 0x01, 0x89, - 0x46, 0x8c, 0x7d, 0x12, 0x77, 0x02, 0xc5, 0xb8, 0x73, 0x6b, 0xc6, 0xa9, 0x28, 0x0b, 0x01, 0x89, - 0x04, 0xe3, 0x0b, 0x00, 0x28, 0xc3, 0x1d, 0x2c, 0x09, 0x4d, 0x41, 0xb8, 0xb7, 0x88, 0x50, 0xb5, - 0xaf, 0x93, 0x20, 0x0b, 0xe5, 0x04, 0xe0, 0x74, 0x67, 0x9a, 0xbe, 0x62, 0xac, 0x9e, 0x69, 0xfa, - 0xb6, 0x71, 0xf7, 0x4c, 0xd3, 0xef, 0x1a, 0x65, 0x6b, 0x1f, 0xac, 0xf0, 0x16, 0x8f, 0x40, 0x03, - 0x64, 0x3b, 0xe4, 0x42, 0xf6, 0x05, 0x88, 0x0f, 0xf9, 0xd9, 0xf7, 0x71, 0xd0, 0x23, 0xf2, 0x75, - 0x8e, 0x24, 0xb0, 0x1a, 0x60, 0xe3, 0x3c, 0xc6, 0x11, 0xe3, 0xed, 0x21, 0x8d, 0x9e, 0x53, 0x8f, - 0x41, 0x08, 0xb4, 0x36, 0x66, 0x6d, 0x15, 0x2b, 0xc6, 0xf0, 0xa7, 0x40, 0x0b, 0xa8, 0xc7, 0x44, - 0x63, 0x93, 0x3f, 0xdc, 0xba, 0xde, 0x45, 0x3d, 0xa7, 0x1e, 0x12, 0x2e, 0xd6, 0xdf, 0x97, 0x41, - 0xf6, 0x39, 0xf5, 0x60, 0x19, 0xac, 0x61, 0xd7, 0x8d, 0x09, 0x63, 0x8a, 0x69, 0x04, 0xe1, 0x36, - 0x58, 0x4d, 0x68, 0xd7, 0x77, 0x24, 0x5d, 0x0e, 0x29, 0xc4, 0x85, 0x5d, 0x9c, 0x60, 0xd1, 0x03, - 0x14, 0x90, 0x18, 0xf3, 0x6e, 0x5b, 0x94, 0xba, 0x1d, 0xf5, 0xc2, 0x16, 0x89, 0xc5, 0xab, 0x5c, - 0xab, 0x6d, 0x5c, 0xa6, 0x66, 0x5e, 0xd8, 0x5f, 0x0a, 0x33, 0x9a, 0x06, 0xf0, 0x7d, 0xb0, 0x96, - 0x0c, 0x6c, 0xb1, 0x86, 0x15, 0xb1, 0xc5, 0x9b, 0x97, 0xa9, 0xb9, 0x91, 0x4c, 0x96, 0xf9, 0x3b, - 0xcc, 0xda, 0x68, 0x35, 0x19, 0xf0, 0xff, 0xe1, 0x3e, 0xd0, 0x93, 0x81, 0xed, 0x47, 0x2e, 0x19, - 0x88, 0x97, 0xb8, 0x56, 0x2b, 0x5d, 0xa6, 0xa6, 0x31, 0xe5, 0x7e, 0xca, 0xe7, 0xd0, 0x5a, 0x32, - 0x10, 0x03, 0xf8, 0x3e, 0x00, 0x32, 0x25, 0xa1, 0x20, 0xdf, 0xc9, 0xeb, 0x97, 0xa9, 0x99, 0x13, - 0x56, 0xc1, 0x3d, 0x19, 0x42, 0x0b, 0xac, 0x48, 0x6e, 0x5d, 0x70, 0x17, 0x2e, 0x53, 0x53, 0x0f, - 0xa8, 0x27, 0x39, 0xe5, 0x14, 0xdf, 0xaa, 0x98, 0x84, 0xb4, 0x4f, 0x5c, 0xf1, 0x62, 0xd4, 0xd1, - 0x08, 0x5a, 0x5f, 0x2f, 0x03, 0xfd, 0x7c, 0x80, 0x08, 0xeb, 0x05, 0x09, 0xfc, 0x08, 0x18, 0xa2, - 0x57, 0xc4, 0x4e, 0x62, 0xcf, 0x6c, 0x6d, 0xed, 0xfe, 0xe4, 0x35, 0x36, 0xef, 0x61, 0xa1, 0x8d, - 0x91, 0xe9, 0x58, 0xed, 0x7f, 0x09, 0xac, 0xb4, 0x02, 0x4a, 0x43, 0x51, 0x09, 0x05, 0x24, 0x01, - 0xfc, 0x4c, 0xec, 0x9a, 0x38, 0xe5, 0xac, 0xe8, 0xc3, 0xff, 0xef, 0xfa, 0x29, 0xcf, 0x95, 0x4a, - 0xed, 0x3e, 0xef, 0xc2, 0xaf, 0x52, 0xb3, 0x28, 0xb5, 0x55, 0xbc, 0xf5, 0xed, 0x0f, 0x6f, 0x1f, - 0x66, 0xf8, 0x06, 0x8b, 0x7a, 0x32, 0x40, 0x36, 0x26, 0x89, 0x38, 0xb9, 0x02, 0xe2, 0x43, 0x7e, - 0xe1, 0xc4, 0xa4, 0x4f, 0xe2, 0x84, 0xb8, 0xea, 0x4b, 0x6b, 0x8c, 0xf9, 0xed, 0xe5, 0x61, 0x66, - 0xf7, 0x18, 0x71, 0xe5, 0x71, 0xa0, 0x35, 0x0f, 0xb3, 0x4f, 0x18, 0x71, 0x9f, 0x6a, 0x5f, 0x7d, - 0x63, 0x2e, 0x59, 0x18, 0xe4, 0x55, 0x8b, 0xde, 0xeb, 0x06, 0x64, 0x41, 0x99, 0x1d, 0x82, 0x02, - 0x4b, 0x68, 0x8c, 0x3d, 0x62, 0x77, 0xc8, 0x85, 0x2a, 0x36, 0x59, 0x3a, 0xca, 0xfe, 0x7b, 0x72, - 0xc1, 0xd0, 0x34, 0x50, 0x12, 0xdf, 0x68, 0x20, 0x7f, 0x1e, 0x63, 0x87, 0xa8, 0x86, 0x9b, 0x17, - 0x2c, 0x87, 0xb1, 0x92, 0x50, 0x88, 0x6b, 0xf3, 0x67, 0x92, 0xf6, 0x12, 0xf5, 0x50, 0x8d, 0x20, - 0x8f, 0x88, 0x09, 0x19, 0x10, 0x47, 0xec, 0xa5, 0x86, 0x14, 0x82, 0x47, 0x60, 0xdd, 0xf5, 0x19, - 0x6e, 0x05, 0xe2, 0x53, 0xcd, 0xe9, 0xc8, 0xe5, 0xd7, 0x8c, 0xcb, 0xd4, 0x2c, 0xa8, 0x89, 0x26, - 0xb7, 0xa3, 0x19, 0x04, 0x3f, 0x04, 0x1b, 0x93, 0x30, 0x91, 0xad, 0xd8, 0x1b, 0xbd, 0x06, 0x2f, - 0x53, 0xb3, 0x38, 0x76, 0x15, 0x33, 0x68, 0x0e, 0xcb, 0x4b, 0xbf, 0xd5, 0xf3, 0x44, 0x05, 0xea, - 0x48, 0x02, 0x6e, 0x0d, 0xfc, 0xd0, 0x4f, 0x44, 0xc5, 0xad, 0x20, 0x09, 0xe0, 0x87, 0x20, 0x47, - 0xfb, 0x24, 0x8e, 0x7d, 0x97, 0x30, 0xd1, 0x3b, 0xe5, 0x0f, 0xdf, 0xbb, 0x5e, 0x06, 0x53, 0x1f, - 0x23, 0x68, 0xe2, 0xcf, 0x17, 0x47, 0x22, 0x91, 0x64, 0x48, 0x42, 0x1a, 0x5f, 0x88, 0xee, 0x48, - 0x2d, 0x4e, 0x4e, 0xbc, 0x10, 0x76, 0x34, 0x83, 0x60, 0x0d, 0x40, 0x15, 0x16, 0x93, 0xa4, 0x17, - 0x47, 0xb6, 0xb8, 0x04, 0x0a, 0x22, 0x56, 0x3c, 0x8a, 0x72, 0x16, 0x89, 0xc9, 0x67, 0x38, 0xc1, - 0xe8, 0x9a, 0x05, 0xfe, 0x1a, 0x40, 0x79, 0x26, 0xf6, 0x17, 0x8c, 0x46, 0xfc, 0x93, 0xea, 0x95, - 0xef, 0xa9, 0xf6, 0x46, 0xe8, 0xcb, 0x59, 0x95, 0xb3, 0x21, 0xd1, 0x19, 0xa3, 0x6a, 0x15, 0x67, - 0x9a, 0xae, 0x19, 0x2b, 0x67, 0x9a, 0xbe, 0x66, 0xe8, 0xe3, 0xfd, 0x53, 0xab, 0x40, 0x9b, 0x23, - 0x3c, 0x95, 0x9e, 0xf5, 0x12, 0x80, 0x46, 0x4c, 0x7c, 0xde, 0x84, 0x06, 0x01, 0xbf, 0xb9, 0x22, - 0x1c, 0x92, 0xd1, 0x95, 0xc9, 0xc7, 0xd3, 0x85, 0xb9, 0x3c, 0x5b, 0x98, 0x10, 0x68, 0x0e, 0x75, - 0x89, 0x28, 0x8d, 0x1c, 0x12, 0xe3, 0x87, 0x7f, 0xcb, 0x80, 0xa9, 0x2f, 0x4f, 0xf8, 0x4b, 0x50, - 0x39, 0x3e, 0x39, 0xa9, 0x37, 0x9b, 0xf6, 0xf9, 0xe7, 0x8d, 0xba, 0xdd, 0xa8, 0xa3, 0x17, 0xa7, - 0xcd, 0xe6, 0xe9, 0xc7, 0x2f, 0x9f, 0xd7, 0x9b, 0x4d, 0x63, 0xa9, 0xf2, 0xe0, 0xf5, 0x9b, 0x6a, - 0x79, 0xe2, 0xdf, 0x20, 0x71, 0xe8, 0x33, 0xe6, 0xd3, 0x28, 0xe0, 0x02, 0x1f, 0x80, 0xed, 0xe9, - 0x68, 0x54, 0x6f, 0x9e, 0xa3, 0xd3, 0x93, 0xf3, 0xfa, 0x33, 0x23, 0x53, 0x29, 0xbf, 0x7e, 0x53, - 0x2d, 0x4d, 0x22, 0x11, 0x61, 0x49, 0xec, 0x3b, 0xfc, 0xc9, 0x7b, 0x02, 0xca, 0x37, 0x6b, 0xd6, - 0x9f, 0x19, 0xcb, 0x95, 0xca, 0xeb, 0x37, 0xd5, 0xed, 0x9b, 0x14, 0x89, 0x5b, 0xd1, 0xbe, 0xfa, - 0xeb, 0xce, 0x52, 0xed, 0xe9, 0x77, 0xc3, 0x9d, 0xcc, 0xf7, 0xc3, 0x9d, 0xcc, 0xbf, 0x87, 0x3b, - 0x99, 0xaf, 0xdf, 0xed, 0x2c, 0x7d, 0xff, 0x6e, 0x67, 0xe9, 0x1f, 0xef, 0x76, 0x96, 0xfe, 0x50, - 0xf5, 0xfc, 0xa4, 0xdd, 0x6b, 0xed, 0x39, 0x34, 0xdc, 0x9f, 0xff, 0xa5, 0x81, 0x7f, 0x53, 0xb3, - 0xd6, 0xaa, 0xf8, 0x41, 0xe8, 0xf1, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x92, 0xb6, 0x78, 0x1a, - 0x69, 0x12, 0x00, 0x00, + // 2007 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x58, 0x4d, 0x6f, 0x1b, 0xc7, + 0x19, 0x16, 0xc5, 0x95, 0xb4, 0x1c, 0x52, 0xd2, 0x7a, 0x44, 0xcb, 0x34, 0xed, 0x68, 0xd5, 0x6d, + 0x0f, 0xaa, 0x91, 0x4a, 0x96, 0x1c, 0xb5, 0x86, 0xd3, 0x0f, 0x88, 0x32, 0xd3, 0x4a, 0xb5, 0x1d, + 0x61, 0xa8, 0xc6, 0x48, 0xd1, 0x62, 0x31, 0xdc, 0x1d, 0x2f, 0x37, 0xda, 0xdd, 0x21, 0x66, 0x96, + 0xb4, 0xd8, 0x3f, 0xd0, 0xc0, 0xa7, 0xf4, 0x07, 0x18, 0x08, 0xd0, 0x4b, 0x8e, 0x39, 0xf4, 0x07, + 0xf4, 0x98, 0x63, 0x8e, 0x45, 0x81, 0x2e, 0x0a, 0xfa, 0x10, 0x40, 0x47, 0xfd, 0x82, 0x62, 0x3e, + 0xf8, 0x29, 0x85, 0x55, 0x00, 0xc1, 0x9e, 0xe7, 0xfd, 0x78, 0x9e, 0xf9, 0x78, 0x77, 0xe7, 0x5d, + 0x82, 0xaa, 0x47, 0x79, 0x4c, 0xf9, 0x0e, 0xe9, 0xc6, 0x3b, 0xe2, 0x6f, 0x57, 0x8c, 0xb6, 0xdb, + 0x8c, 0xa6, 0x14, 0x5a, 0xca, 0xb7, 0x2d, 0x2c, 0xe2, 0x6f, 0xb7, 0x7a, 0x0b, 0xc7, 0x61, 0x42, + 0x77, 0xe4, 0xbf, 0x2a, 0xa8, 0x5a, 0x0e, 0x68, 0x40, 0xe5, 0x70, 0x47, 0x8c, 0x94, 0xd5, 0xf9, + 0x47, 0x1e, 0x2c, 0x9e, 0x60, 0x86, 0x63, 0x0e, 0x77, 0x41, 0x81, 0x74, 0x63, 0xd7, 0x27, 0x09, + 0x8d, 0x2b, 0xb9, 0xcd, 0xdc, 0x56, 0xa1, 0x56, 0xbe, 0xcc, 0x6c, 0xab, 0x87, 0xe3, 0xe8, 0x89, + 0x33, 0x74, 0x39, 0xc8, 0x24, 0xdd, 0xf8, 0xa9, 0x18, 0xc2, 0x03, 0x00, 0xc8, 0x79, 0xca, 0xb0, + 0x4b, 0xc2, 0x36, 0xaf, 0x18, 0x9b, 0xf9, 0xad, 0x7c, 0xcd, 0xe9, 0x67, 0x76, 0xa1, 0x2e, 0xac, + 0xf5, 0xa3, 0x13, 0x7e, 0x99, 0xd9, 0xb7, 0x34, 0xc1, 0x30, 0xd0, 0x41, 0x05, 0x09, 0xea, 0x61, + 0x9b, 0xc3, 0x3d, 0x50, 0x12, 0xd4, 0x5e, 0x0b, 0x27, 0x09, 0x89, 0x78, 0x65, 0x69, 0x33, 0xbf, + 0x55, 0xa8, 0xad, 0xf6, 0x33, 0xbb, 0x58, 0xff, 0xe4, 0xf9, 0xa1, 0x36, 0xa3, 0x22, 0xe9, 0xc6, + 0x03, 0x00, 0xff, 0x0c, 0x56, 0xb0, 0xe7, 0x11, 0xce, 0x5d, 0x8f, 0x26, 0x29, 0xa3, 0x51, 0xc5, + 0xdc, 0xcc, 0x6d, 0x15, 0xf7, 0xec, 0xed, 0xe9, 0x8d, 0xd8, 0x3e, 0x90, 0x71, 0x87, 0x2a, 0xac, + 0x76, 0xfb, 0x9b, 0xcc, 0x9e, 0xeb, 0x67, 0xf6, 0xf2, 0x84, 0x19, 0x2d, 0xe3, 0x71, 0x08, 0x9f, + 0x80, 0xbb, 0xd8, 0x4b, 0xc3, 0x2e, 0x71, 0x79, 0x8a, 0xd3, 0xd0, 0x73, 0xdb, 0x8c, 0x78, 0x34, + 0x6e, 0x87, 0x11, 0xe1, 0x95, 0x82, 0x98, 0x1f, 0xba, 0xa3, 0x02, 0x1a, 0xd2, 0x7f, 0x32, 0x72, + 0xc3, 0x87, 0xa0, 0xdc, 0x0a, 0x79, 0x4a, 0x59, 0xcf, 0xe5, 0x84, 0x75, 0x89, 0xfb, 0x3a, 0x4c, + 0x7c, 0xfa, 0xba, 0x02, 0x36, 0x73, 0x5b, 0x06, 0x82, 0xda, 0xd7, 0x10, 0xae, 0x97, 0xd2, 0xf3, + 0xe4, 0xde, 0x9b, 0xef, 0xbe, 0x7e, 0xb0, 0x3e, 0x76, 0xba, 0xe7, 0xe2, 0x7c, 0xd5, 0x99, 0x1c, + 0x1b, 0xe6, 0xbc, 0x95, 0x3f, 0x36, 0xcc, 0xbc, 0x65, 0x1c, 0x1b, 0xe6, 0x82, 0xb5, 0x78, 0x6c, + 0x98, 0x8b, 0xd6, 0x92, 0xf3, 0xb7, 0x1c, 0x98, 0x5c, 0x03, 0x3c, 0x00, 0x8b, 0x1e, 0x23, 0x38, + 0x25, 0xf2, 0xe8, 0x8a, 0x7b, 0x3f, 0xfe, 0x3f, 0x7b, 0x71, 0xda, 0x6b, 0x93, 0x9a, 0x21, 0xf6, + 0x03, 0xe9, 0x44, 0xf8, 0x2b, 0x60, 0x78, 0x38, 0x8a, 0x2a, 0xf3, 0x3f, 0x94, 0x40, 0xa6, 0x39, + 0xff, 0xc9, 0x81, 0x5b, 0x57, 0x22, 0xa0, 0x07, 0x8a, 0xfa, 0xac, 0xd2, 0x5e, 0x5b, 0x4d, 0x6e, + 0x65, 0xef, 0xfe, 0xf7, 0x71, 0x4b, 0xd2, 0x9f, 0xf4, 0x33, 0x1b, 0x8c, 0xf0, 0x65, 0x66, 0x43, + 0x55, 0x42, 0x63, 0x44, 0x0e, 0x02, 0x78, 0x18, 0x01, 0x3d, 0xb0, 0x36, 0x59, 0x10, 0x6e, 0x14, + 0xf2, 0xb4, 0x32, 0x2f, 0x6b, 0xe9, 0x51, 0x3f, 0xb3, 0x27, 0x27, 0xf6, 0x2c, 0xe4, 0xe9, 0x65, + 0x66, 0x57, 0x27, 0x58, 0xc7, 0x33, 0x1d, 0x74, 0x0b, 0x4f, 0x27, 0x38, 0x5f, 0x59, 0xa0, 0x78, + 0xd8, 0xc2, 0x61, 0x72, 0x48, 0x93, 0x57, 0x61, 0x00, 0xff, 0x04, 0x56, 0x5b, 0x34, 0x26, 0x3c, + 0x25, 0xd8, 0x77, 0x9b, 0x11, 0xf5, 0xce, 0xf4, 0x53, 0xf3, 0xe8, 0xdf, 0x99, 0x7d, 0x5b, 0x2d, + 0x90, 0xfb, 0x67, 0xdb, 0x21, 0xdd, 0x89, 0x71, 0xda, 0xda, 0x3e, 0x4a, 0x84, 0xe8, 0xba, 0x12, + 0x9d, 0xca, 0x74, 0xd0, 0xca, 0xd0, 0x52, 0x13, 0x06, 0xd8, 0x02, 0x2b, 0x3e, 0xa6, 0xee, 0x2b, + 0xca, 0xce, 0x34, 0xf9, 0xbc, 0x24, 0xaf, 0x7d, 0x2f, 0x79, 0x3f, 0xb3, 0x4b, 0x4f, 0x0f, 0x3e, + 0xfe, 0x88, 0xb2, 0x33, 0x49, 0x71, 0x99, 0xd9, 0xb7, 0x95, 0xd8, 0x24, 0x91, 0x83, 0x4a, 0x3e, + 0xa6, 0xc3, 0x30, 0xf8, 0x12, 0x58, 0xc3, 0x00, 0xde, 0x69, 0xb7, 0x29, 0x4b, 0x2b, 0xf9, 0xcd, + 0xdc, 0x96, 0x59, 0xfb, 0x59, 0x3f, 0xb3, 0x57, 0x34, 0x65, 0x43, 0x79, 0x2e, 0x33, 0xfb, 0xce, + 0x14, 0xa9, 0xce, 0x71, 0xd0, 0x8a, 0xa6, 0xd5, 0xa1, 0xb0, 0x09, 0x4a, 0x24, 0x6c, 0xef, 0xee, + 0x3f, 0xd4, 0x0b, 0x30, 0xe4, 0x02, 0x7e, 0x33, 0x6b, 0x01, 0xc5, 0xfa, 0xd1, 0xc9, 0xee, 0xfe, + 0xc3, 0xc1, 0xfc, 0xd7, 0xf4, 0xab, 0x63, 0x8c, 0xc5, 0x41, 0x45, 0x05, 0xd5, 0xe4, 0x07, 0x1a, + 0xfb, 0x5a, 0x63, 0xf1, 0xa6, 0x1a, 0xfb, 0xd7, 0x69, 0xec, 0x4f, 0x6a, 0xec, 0x4f, 0x6a, 0x3c, + 0xd6, 0x1a, 0x4b, 0x37, 0xd5, 0x78, 0x7c, 0x9d, 0xc6, 0xe3, 0x49, 0x0d, 0x15, 0x23, 0x8a, 0xa9, + 0xd9, 0xfb, 0x0b, 0x4e, 0xd2, 0xb0, 0x13, 0x6b, 0x19, 0xf3, 0xc6, 0xc5, 0x34, 0x95, 0xe9, 0xa0, + 0x95, 0xa1, 0x45, 0xb1, 0x9f, 0x81, 0xb2, 0x47, 0x13, 0x9e, 0x0a, 0x5b, 0x42, 0xdb, 0x11, 0xd1, + 0x12, 0x05, 0x29, 0xf1, 0x78, 0x96, 0xc4, 0x3d, 0x25, 0x71, 0x5d, 0xba, 0x83, 0xd6, 0x26, 0xcd, + 0x4a, 0xcc, 0x05, 0x56, 0x9b, 0xa4, 0x84, 0xf1, 0x66, 0x87, 0x05, 0x5a, 0x08, 0x48, 0xa1, 0x0f, + 0x66, 0x09, 0xe9, 0xb2, 0x9a, 0x4e, 0x75, 0xd0, 0xea, 0xc8, 0xa4, 0x04, 0x3e, 0x05, 0x2b, 0xa1, + 0x50, 0x6d, 0x76, 0x22, 0x4d, 0x5f, 0x94, 0xf4, 0x7b, 0xb3, 0xe8, 0xf5, 0xa3, 0x30, 0x99, 0xe8, + 0xa0, 0xe5, 0x81, 0x41, 0x51, 0xfb, 0x00, 0xc6, 0x9d, 0x90, 0xb9, 0x41, 0x84, 0xbd, 0x90, 0x30, + 0x4d, 0x5f, 0x92, 0xf4, 0x3f, 0x9f, 0x45, 0x7f, 0x57, 0xd1, 0x5f, 0x4d, 0x76, 0x90, 0x25, 0x8c, + 0xbf, 0x55, 0x36, 0xa5, 0xd2, 0x00, 0xa5, 0x26, 0x61, 0x51, 0x98, 0x68, 0xfe, 0x65, 0xc9, 0xff, + 0x70, 0x16, 0xbf, 0xae, 0xa0, 0xf1, 0x34, 0x07, 0x15, 0x15, 0x1c, 0x92, 0x46, 0x34, 0xf1, 0xe9, + 0x80, 0xf4, 0xd6, 0x8d, 0x49, 0xc7, 0xd3, 0x1c, 0x54, 0x54, 0x50, 0x91, 0x06, 0x60, 0x0d, 0x33, + 0x46, 0x5f, 0x4f, 0x6d, 0x08, 0x94, 0xdc, 0xbf, 0x98, 0xc5, 0x3d, 0x78, 0xb9, 0x5e, 0xcd, 0x16, + 0x2f, 0x57, 0x61, 0x9d, 0xd8, 0x12, 0x1f, 0xc0, 0x80, 0xe1, 0xde, 0x94, 0x4e, 0xf9, 0xc6, 0x1b, + 0x7f, 0x35, 0xd9, 0x41, 0x96, 0x30, 0x4e, 0xa8, 0x7c, 0x06, 0xca, 0x31, 0x61, 0x01, 0x71, 0x13, + 0x92, 0xf2, 0x76, 0x14, 0xa6, 0x5a, 0xe7, 0xf6, 0x8d, 0x9f, 0x83, 0xeb, 0xd2, 0x1d, 0x04, 0xa5, + 0xf9, 0x85, 0xb6, 0x2a, 0xad, 0xbb, 0xc0, 0xf4, 0xc4, 0x6d, 0xe1, 0x86, 0x7e, 0xa5, 0x22, 0x6f, + 0xff, 0x25, 0x89, 0x8f, 0x7c, 0x58, 0x06, 0x0b, 0xaa, 0xcb, 0xba, 0x2b, 0x74, 0x91, 0x02, 0xb0, + 0x0a, 0x4c, 0x9f, 0x78, 0x61, 0x8c, 0x23, 0x5e, 0xa9, 0xca, 0x84, 0x21, 0x86, 0x9f, 0x80, 0x65, + 0xde, 0xc2, 0x49, 0xd0, 0xc2, 0xa1, 0x9b, 0x86, 0x31, 0xa9, 0xdc, 0x93, 0x33, 0xde, 0x9d, 0x35, + 0xe3, 0xb2, 0x9a, 0xf1, 0x44, 0x9e, 0x83, 0x4a, 0x03, 0x7c, 0x1a, 0xc6, 0x04, 0x9e, 0x80, 0xa2, + 0x87, 0x13, 0xaf, 0x93, 0x28, 0xd6, 0xfb, 0x92, 0x75, 0x67, 0x16, 0xab, 0xbe, 0x8a, 0xc7, 0xb2, + 0x1c, 0x04, 0x14, 0x1a, 0x30, 0xb6, 0x19, 0x0e, 0x3a, 0x44, 0x31, 0xbe, 0x77, 0x63, 0xc6, 0xb1, + 0x2c, 0x07, 0x01, 0x85, 0x06, 0x8c, 0x5d, 0xc2, 0xce, 0x22, 0xcd, 0xb8, 0x71, 0x63, 0xc6, 0xb1, + 0x2c, 0x07, 0x01, 0x85, 0x24, 0xe3, 0x73, 0x00, 0x28, 0xc7, 0x67, 0x58, 0x11, 0xda, 0x92, 0x70, + 0x7b, 0x16, 0xa1, 0x6e, 0x61, 0x47, 0x49, 0x0e, 0x2a, 0x48, 0x20, 0xe8, 0x86, 0x8d, 0xd9, 0xba, + 0x75, 0xe7, 0xd8, 0x30, 0xef, 0x58, 0x15, 0x67, 0x07, 0x2c, 0x88, 0xd6, 0x90, 0x40, 0x0b, 0xe4, + 0xcf, 0x48, 0x4f, 0xf5, 0x05, 0x48, 0x0c, 0xc5, 0xd9, 0x77, 0x71, 0xd4, 0x21, 0xea, 0x3a, 0x47, + 0x0a, 0x38, 0x27, 0x60, 0xf5, 0x94, 0xe1, 0x84, 0x8b, 0xb6, 0x92, 0x26, 0xcf, 0x68, 0xc0, 0x21, + 0x04, 0x46, 0x0b, 0xf3, 0x96, 0xce, 0x95, 0x63, 0xf8, 0x53, 0x60, 0x44, 0x34, 0xe0, 0xb2, 0xb1, + 0x29, 0xee, 0xdd, 0xbe, 0xda, 0x45, 0x3d, 0xa3, 0x01, 0x92, 0x21, 0xce, 0x5f, 0xf3, 0x20, 0xff, + 0x8c, 0x06, 0xb0, 0x02, 0x96, 0xb0, 0xef, 0x33, 0xc2, 0xb9, 0x66, 0x1a, 0x40, 0xb8, 0x0e, 0x16, + 0x53, 0xda, 0x0e, 0x3d, 0x45, 0x57, 0x40, 0x1a, 0x09, 0x61, 0x1f, 0xa7, 0x58, 0xf6, 0x00, 0x25, + 0x24, 0xc7, 0xa2, 0x4b, 0x97, 0xa5, 0xee, 0x26, 0x9d, 0xb8, 0x49, 0x98, 0xbc, 0xca, 0x8d, 0xda, + 0xea, 0x45, 0x66, 0x17, 0xa5, 0xfd, 0x85, 0x34, 0xa3, 0x71, 0x00, 0xdf, 0x07, 0x4b, 0xe9, 0xb9, + 0x2b, 0xd7, 0xb0, 0x20, 0xb7, 0x78, 0xed, 0x22, 0xb3, 0x57, 0xd3, 0xd1, 0x32, 0x7f, 0x87, 0x79, + 0x0b, 0x2d, 0xa6, 0xe7, 0xe2, 0x7f, 0xb8, 0x03, 0xcc, 0xf4, 0xdc, 0x0d, 0x13, 0x9f, 0x9c, 0xcb, + 0x4b, 0xdc, 0xa8, 0x95, 0x2f, 0x32, 0xdb, 0x1a, 0x0b, 0x3f, 0x12, 0x3e, 0xb4, 0x94, 0x9e, 0xcb, + 0x01, 0x7c, 0x1f, 0x00, 0x35, 0x25, 0xa9, 0xa0, 0xee, 0xe4, 0xe5, 0x8b, 0xcc, 0x2e, 0x48, 0xab, + 0xe4, 0x1e, 0x0d, 0xa1, 0x03, 0x16, 0x14, 0xb7, 0x29, 0xb9, 0x4b, 0x17, 0x99, 0x6d, 0x46, 0x34, + 0x50, 0x9c, 0xca, 0x25, 0xb6, 0x8a, 0x91, 0x98, 0x76, 0x89, 0x2f, 0x2f, 0x46, 0x13, 0x0d, 0x20, + 0xfc, 0x10, 0xac, 0x2a, 0x2d, 0x71, 0xf6, 0x3c, 0xc5, 0x71, 0x5b, 0x35, 0xf4, 0x35, 0x78, 0x91, + 0xd9, 0x2b, 0xd2, 0x75, 0x3a, 0xf0, 0xa0, 0x29, 0xec, 0x7c, 0x31, 0x0f, 0xcc, 0xd3, 0x73, 0x44, + 0x78, 0x27, 0x4a, 0xe1, 0x47, 0xc0, 0x92, 0x8d, 0x26, 0xf6, 0x52, 0x77, 0xe2, 0x5c, 0x6a, 0xf7, + 0x46, 0x77, 0xe0, 0x74, 0x84, 0x83, 0x56, 0x07, 0xa6, 0x03, 0x7d, 0x78, 0x65, 0xb0, 0xd0, 0x8c, + 0x28, 0x8d, 0x65, 0x19, 0x95, 0x90, 0x02, 0xf0, 0xa5, 0xdc, 0x72, 0x59, 0x22, 0x79, 0xd9, 0xc4, + 0xff, 0xe8, 0x6a, 0x89, 0x4c, 0xd5, 0x59, 0xed, 0x9e, 0x68, 0xe1, 0x2f, 0x33, 0x7b, 0x45, 0x69, + 0xeb, 0x7c, 0xe7, 0xab, 0xef, 0xbe, 0x7e, 0x90, 0x13, 0xa7, 0x23, 0x8b, 0xd1, 0x02, 0x79, 0x46, + 0x52, 0x79, 0xec, 0x25, 0x24, 0x86, 0xe2, 0x6d, 0xc5, 0x48, 0x97, 0xb0, 0x94, 0xf8, 0xf2, 0x78, + 0x4d, 0x34, 0xc4, 0xe2, 0xd5, 0x17, 0x60, 0xee, 0x76, 0x38, 0xf1, 0xd5, 0x59, 0xa2, 0xa5, 0x00, + 0xf3, 0x3f, 0x70, 0xe2, 0x3f, 0x31, 0x3e, 0xff, 0xd2, 0x9e, 0x73, 0x30, 0x28, 0xea, 0xfe, 0xbe, + 0xd3, 0x8e, 0xc8, 0x8c, 0x1a, 0xdd, 0x03, 0x25, 0xf1, 0xc1, 0x84, 0x03, 0xe2, 0x9e, 0x91, 0x9e, + 0xae, 0x54, 0x55, 0x77, 0xda, 0xfe, 0x7b, 0xd2, 0xe3, 0x68, 0x1c, 0x68, 0x89, 0x2f, 0x0d, 0x50, + 0x3c, 0x65, 0xd8, 0x23, 0xba, 0x5b, 0x17, 0xd5, 0x2e, 0x20, 0xd3, 0x12, 0x1a, 0x09, 0x6d, 0x71, + 0xa8, 0xb4, 0x93, 0xea, 0x27, 0x72, 0x00, 0x45, 0x06, 0x23, 0xe4, 0x9c, 0x78, 0x72, 0x2f, 0x0d, + 0xa4, 0x11, 0xdc, 0x07, 0xcb, 0x7e, 0xc8, 0x71, 0x33, 0x92, 0xdf, 0x87, 0xde, 0x99, 0x5a, 0x7e, + 0xcd, 0xba, 0xc8, 0xec, 0x92, 0x76, 0x34, 0x84, 0x1d, 0x4d, 0x20, 0x51, 0x43, 0xa3, 0x34, 0x39, + 0x5b, 0xb9, 0x37, 0xa6, 0xaa, 0xa1, 0x61, 0xa8, 0xf4, 0xa0, 0x29, 0xac, 0x6e, 0x8c, 0x66, 0x27, + 0x90, 0xe5, 0x6b, 0x22, 0x05, 0x84, 0x35, 0x0a, 0xe3, 0x30, 0x95, 0xe5, 0xba, 0x80, 0x14, 0x80, + 0x1f, 0x82, 0x02, 0xed, 0x12, 0xc6, 0x42, 0x9f, 0x70, 0x59, 0xa6, 0xc5, 0xbd, 0xf7, 0xae, 0x96, + 0xc1, 0xd8, 0x97, 0x0c, 0x1a, 0xc5, 0x8b, 0xc5, 0x91, 0x44, 0x4e, 0x32, 0x26, 0x31, 0x65, 0x3d, + 0xd9, 0x5a, 0xe9, 0xc5, 0x29, 0xc7, 0x73, 0x69, 0x47, 0x13, 0x08, 0xd6, 0x00, 0xd4, 0x69, 0x8c, + 0xa4, 0x1d, 0x96, 0xb8, 0xf2, 0x0d, 0x52, 0x92, 0xb9, 0xf2, 0x39, 0x56, 0x5e, 0x24, 0x9d, 0x4f, + 0x71, 0x8a, 0xd1, 0x15, 0x0b, 0xfc, 0x35, 0x80, 0xea, 0x4c, 0xdc, 0xcf, 0x38, 0x4d, 0xc4, 0xf7, + 0xd8, 0xab, 0x30, 0xd0, 0xbd, 0x91, 0xd4, 0x57, 0x5e, 0x3d, 0x67, 0x4b, 0xa1, 0x63, 0x4e, 0xf5, + 0x2a, 0x8e, 0x0d, 0xd3, 0xb0, 0x16, 0x8e, 0x0d, 0x73, 0xc9, 0x32, 0x87, 0xfb, 0xa7, 0x57, 0x81, + 0xd6, 0x06, 0x78, 0x6c, 0x7a, 0xce, 0x0b, 0x00, 0x4e, 0x18, 0x09, 0x45, 0x07, 0x1b, 0x45, 0xe2, + 0xb5, 0x97, 0xe0, 0x98, 0x0c, 0xde, 0xb7, 0x62, 0x3c, 0x5e, 0x98, 0xf3, 0x93, 0x85, 0x09, 0x81, + 0xe1, 0x51, 0x9f, 0xc8, 0xd2, 0x28, 0x20, 0x39, 0x7e, 0xf0, 0xcf, 0x1c, 0x18, 0xfb, 0x6c, 0x85, + 0xbf, 0x04, 0xd5, 0x83, 0xc3, 0xc3, 0x7a, 0xa3, 0xe1, 0x9e, 0x7e, 0x7a, 0x52, 0x77, 0x4f, 0xea, + 0xe8, 0xf9, 0x51, 0xa3, 0x71, 0xf4, 0xf1, 0x8b, 0x67, 0xf5, 0x46, 0xc3, 0x9a, 0xab, 0xde, 0x7f, + 0xf3, 0x76, 0xb3, 0x32, 0x8a, 0x3f, 0x21, 0x2c, 0x0e, 0x39, 0x0f, 0x69, 0x12, 0x09, 0x81, 0x0f, + 0xc0, 0xfa, 0x78, 0x36, 0xaa, 0x37, 0x4e, 0xd1, 0xd1, 0xe1, 0x69, 0xfd, 0xa9, 0x95, 0xab, 0x56, + 0xde, 0xbc, 0xdd, 0x2c, 0x8f, 0x32, 0x11, 0xe1, 0x29, 0x0b, 0x3d, 0xf1, 0xe4, 0x3d, 0x06, 0x95, + 0xeb, 0x35, 0xeb, 0x4f, 0xad, 0xf9, 0x6a, 0xf5, 0xcd, 0xdb, 0xcd, 0xf5, 0xeb, 0x14, 0x89, 0x5f, + 0x35, 0x3e, 0xff, 0xfb, 0xc6, 0x5c, 0xed, 0xc9, 0x37, 0xfd, 0x8d, 0xdc, 0xb7, 0xfd, 0x8d, 0xdc, + 0x7f, 0xfb, 0x1b, 0xb9, 0x2f, 0xde, 0x6d, 0xcc, 0x7d, 0xfb, 0x6e, 0x63, 0xee, 0x5f, 0xef, 0x36, + 0xe6, 0xfe, 0xb8, 0x19, 0x84, 0x69, 0xab, 0xd3, 0xdc, 0xf6, 0x68, 0xbc, 0x33, 0xfd, 0x63, 0x85, + 0xf8, 0x20, 0xe7, 0xcd, 0x45, 0xf9, 0x8b, 0xd2, 0xa3, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xc6, + 0x17, 0xe6, 0x54, 0xaa, 0x12, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -1090,6 +1098,11 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.HistoryServeWindow != 0 { + i = encodeVarintEvm(dAtA, i, uint64(m.HistoryServeWindow)) + i-- + dAtA[i] = 0x50 + } if len(m.ActiveStaticPrecompiles) > 0 { for iNdEx := len(m.ActiveStaticPrecompiles) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.ActiveStaticPrecompiles[iNdEx]) @@ -1118,16 +1131,6 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x3a } } - if m.AllowUnprotectedTxs { - i-- - if m.AllowUnprotectedTxs { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x28 - } if len(m.ExtraEIPs) > 0 { dAtA3 := make([]byte, len(m.ExtraEIPs)*10) var j2 int @@ -1652,6 +1655,11 @@ func (m *Log) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.BlockTimestamp != 0 { + i = encodeVarintEvm(dAtA, i, uint64(m.BlockTimestamp)) + i-- + dAtA[i] = 0x50 + } if m.Removed { i-- if m.Removed { @@ -2013,9 +2021,6 @@ func (m *Params) Size() (n int) { } n += 1 + sovEvm(uint64(l)) + l } - if m.AllowUnprotectedTxs { - n += 2 - } if len(m.EVMChannels) > 0 { for _, s := range m.EVMChannels { l = len(s) @@ -2030,6 +2035,9 @@ func (m *Params) Size() (n int) { n += 1 + l + sovEvm(uint64(l)) } } + if m.HistoryServeWindow != 0 { + n += 1 + sovEvm(uint64(m.HistoryServeWindow)) + } return n } @@ -2242,6 +2250,9 @@ func (m *Log) Size() (n int) { if m.Removed { n += 2 } + if m.BlockTimestamp != 0 { + n += 1 + sovEvm(uint64(m.BlockTimestamp)) + } return n } @@ -2503,26 +2514,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { } else { return fmt.Errorf("proto: wrong wireType = %d for field ExtraEIPs", wireType) } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowUnprotectedTxs", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowEvm - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.AllowUnprotectedTxs = bool(v != 0) case 7: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field EVMChannels", wireType) @@ -2620,6 +2611,25 @@ func (m *Params) Unmarshal(dAtA []byte) error { } m.ActiveStaticPrecompiles = append(m.ActiveStaticPrecompiles, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HistoryServeWindow", wireType) + } + m.HistoryServeWindow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvm + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HistoryServeWindow |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipEvm(dAtA[iNdEx:]) @@ -4216,6 +4226,25 @@ func (m *Log) Unmarshal(dAtA []byte) error { } } m.Removed = bool(v != 0) + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockTimestamp", wireType) + } + m.BlockTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvm + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipEvm(dAtA[iNdEx:]) diff --git a/x/vm/types/logs.go b/x/vm/types/logs.go index 85f029ca6..5409a2097 100644 --- a/x/vm/types/logs.go +++ b/x/vm/types/logs.go @@ -114,14 +114,15 @@ func NewLogFromEth(log *ethtypes.Log) *Log { } return &Log{ - Address: log.Address.String(), - Topics: topics, - Data: log.Data, - BlockNumber: log.BlockNumber, - TxHash: log.TxHash.String(), - TxIndex: uint64(log.TxIndex), - Index: uint64(log.Index), - BlockHash: log.BlockHash.String(), - Removed: log.Removed, + Address: log.Address.String(), + Topics: topics, + Data: log.Data, + BlockNumber: log.BlockNumber, + BlockHash: log.BlockHash.String(), + BlockTimestamp: log.BlockTimestamp, + TxHash: log.TxHash.String(), + TxIndex: uint64(log.TxIndex), + Index: uint64(log.Index), + Removed: log.Removed, } } diff --git a/x/vm/types/mocks/BankKeeper.go b/x/vm/types/mocks/BankKeeper.go index 0e57f8d13..31c4ba983 100644 --- a/x/vm/types/mocks/BankKeeper.go +++ b/x/vm/types/mocks/BankKeeper.go @@ -1,13 +1,15 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. +// Code generated by mockery v2.53.5. DO NOT EDIT. package mocks import ( context "context" - types "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + mock "github.com/stretchr/testify/mock" + + types "github.com/cosmos/cosmos-sdk/types" ) // BankKeeper is an autogenerated mock type for the BankKeeper type @@ -51,6 +53,52 @@ func (_m *BankKeeper) GetBalance(ctx context.Context, addr types.AccAddress, den return r0 } +// GetDenomMetaData provides a mock function with given fields: ctx, denom +func (_m *BankKeeper) GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) { + ret := _m.Called(ctx, denom) + + if len(ret) == 0 { + panic("no return value specified for GetDenomMetaData") + } + + var r0 banktypes.Metadata + var r1 bool + if rf, ok := ret.Get(0).(func(context.Context, string) (banktypes.Metadata, bool)); ok { + return rf(ctx, denom) + } + if rf, ok := ret.Get(0).(func(context.Context, string) banktypes.Metadata); ok { + r0 = rf(ctx, denom) + } else { + r0 = ret.Get(0).(banktypes.Metadata) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) bool); ok { + r1 = rf(ctx, denom) + } else { + r1 = ret.Get(1).(bool) + } + + return r0, r1 +} + +// GetSupply provides a mock function with given fields: ctx, denom +func (_m *BankKeeper) GetSupply(ctx context.Context, denom string) types.Coin { + ret := _m.Called(ctx, denom) + + if len(ret) == 0 { + panic("no return value specified for GetSupply") + } + + var r0 types.Coin + if rf, ok := ret.Get(0).(func(context.Context, string) types.Coin); ok { + r0 = rf(ctx, denom) + } else { + r0 = ret.Get(0).(types.Coin) + } + + return r0 +} + // IsSendEnabledCoins provides a mock function with given fields: ctx, coins func (_m *BankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coin) error { _va := make([]interface{}, len(coins)) @@ -76,6 +124,16 @@ func (_m *BankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coi return r0 } +// IterateAccountBalances provides a mock function with given fields: ctx, account, cb +func (_m *BankKeeper) IterateAccountBalances(ctx context.Context, account types.AccAddress, cb func(types.Coin) bool) { + _m.Called(ctx, account, cb) +} + +// IterateTotalSupply provides a mock function with given fields: ctx, cb +func (_m *BankKeeper) IterateTotalSupply(ctx context.Context, cb func(types.Coin) bool) { + _m.Called(ctx, cb) +} + // MintCoins provides a mock function with given fields: ctx, moduleName, amt func (_m *BankKeeper) MintCoins(ctx context.Context, moduleName string, amt types.Coins) error { ret := _m.Called(ctx, moduleName, amt) @@ -148,47 +206,9 @@ func (_m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderMo return r0 } -// NewBankKeeper creates a new instance of BankKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewBankKeeper(t interface { - mock.TestingT - Cleanup(func()) -}, -) *BankKeeper { - mock := &BankKeeper{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} - -// GetDenomMetaData provides a mock function with given fields: ctx, denom -func (_m *BankKeeper) GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) { - ret := _m.Called(ctx, denom) - - if len(ret) == 0 { - panic("no return value specified for GetDenomMetaData") - } - - var r0 banktypes.Metadata - var r1 bool - if rf, ok := ret.Get(0).(func(context.Context, string) (banktypes.Metadata, bool)); ok { - return rf(ctx, denom) - } - if rf, ok := ret.Get(0).(func(context.Context, string) banktypes.Metadata); ok { - r0 = rf(ctx, denom) - } else { - r0 = ret.Get(0).(banktypes.Metadata) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) bool); ok { - r1 = rf(ctx, denom) - } else { - r1 = ret.Get(1).(bool) - } - - return r0, r1 +// SetDenomMetaData provides a mock function with given fields: ctx, denomMetaData +func (_m *BankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) { + _m.Called(ctx, denomMetaData) } // SpendableCoin provides a mock function with given fields: ctx, addr, denom @@ -209,112 +229,16 @@ func (_m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, return r0 } -// IterateAccountBalances provides a mock function with given fields: ctx, account, cb -func (_m *BankKeeper) IterateAccountBalances(ctx context.Context, account types.AccAddress, cb func(coin types.Coin) bool) { - _m.Called(ctx, account, cb) -} - -// IterateTotalSupply provides a mock function with given fields: ctx, cb -func (_m *BankKeeper) IterateTotalSupply(ctx context.Context, cb func(coin types.Coin) bool) { - _m.Called(ctx, cb) -} - -// GetSupply provides a mock function with given fields: ctx, denom -func (_m *BankKeeper) GetSupply(ctx context.Context, denom string) types.Coin { - ret := _m.Called(ctx, denom) - - if len(ret) == 0 { - panic("no return value specified for GetSupply") - } - - var r0 types.Coin - if rf, ok := ret.Get(0).(func(context.Context, string) types.Coin); ok { - r0 = rf(ctx, denom) - } else { - r0 = ret.Get(0).(types.Coin) - } - - return r0 -} - -// SetDenomMetaData provides a mock function with given fields: ctx, denomMetaData -func (_m *BankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) { - _m.Called(ctx, denomMetaData) -} - -// IsSendEnabledCoin provides a mock function with given fields: ctx, coin -func (_m *BankKeeper) IsSendEnabledCoin(ctx context.Context, coin types.Coin) bool { - ret := _m.Called(ctx, coin) - - if len(ret) == 0 { - panic("no return value specified for IsSendEnabledCoin") - } - - var r0 bool - if rf, ok := ret.Get(0).(func(context.Context, types.Coin) bool); ok { - r0 = rf(ctx, coin) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// GetAllBalances provides a mock function with given fields: ctx, addr -func (_m *BankKeeper) GetAllBalances(ctx context.Context, addr types.AccAddress) types.Coins { - ret := _m.Called(ctx, addr) - - if len(ret) == 0 { - panic("no return value specified for GetAllBalances") - } - - var r0 types.Coins - if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress) types.Coins); ok { - r0 = rf(ctx, addr) - } else { - r0 = ret.Get(0).(types.Coins) - } - - return r0 -} - -// BlockedAddr provides a mock function with given fields: addr -func (_m *BankKeeper) BlockedAddr(addr types.AccAddress) bool { - ret := _m.Called(addr) - - if len(ret) == 0 { - panic("no return value specified for BlockedAddr") - } - - var r0 bool - if rf, ok := ret.Get(0).(func(types.AccAddress) bool); ok { - r0 = rf(addr) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// SendCoinsFromModuleToModule provides a mock function with given fields: ctx, senderModule, recipientModule, amt -func (_m *BankKeeper) SendCoinsFromModuleToModule(ctx context.Context, senderModule string, recipientModule string, amt types.Coins) error { - ret := _m.Called(ctx, senderModule, recipientModule, amt) - - if len(ret) == 0 { - panic("no return value specified for SendCoinsFromModuleToModule") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, types.Coins) error); ok { - r0 = rf(ctx, senderModule, recipientModule, amt) - } else { - r0 = ret.Error(0) - } +// NewBankKeeper creates a new instance of BankKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBankKeeper(t interface { + mock.TestingT + Cleanup(func()) +}) *BankKeeper { + mock := &BankKeeper{} + mock.Mock.Test(t) - return r0 -} + t.Cleanup(func() { mock.AssertExpectations(t) }) -// IterateAllBalances provides a mock function with given fields: ctx, cb -func (_m *BankKeeper) IterateAllBalances(ctx context.Context, cb func(address types.AccAddress, coin types.Coin) (stop bool)) { - _m.Called(ctx, cb) + return mock } diff --git a/x/vm/types/params.go b/x/vm/types/params.go index 8cd10b4a5..5b3e8d400 100644 --- a/x/vm/types/params.go +++ b/x/vm/types/params.go @@ -23,8 +23,6 @@ var ( DefaultEVMChainID = "cosmos_262144-1" // DefaultEVMDecimals is the default value for the evm denom decimal precision DefaultEVMDecimals uint64 = 18 - // DefaultAllowUnprotectedTxs rejects all unprotected txs (i.e false) - DefaultAllowUnprotectedTxs = false // DefaultStaticPrecompiles defines the default active precompiles. DefaultStaticPrecompiles []string // DefaultExtraEIPs defines the default extra EIPs to be included. @@ -45,16 +43,16 @@ var ( } ) +const DefaultHistoryServeWindow = 8192 // same as EIP-2935 + // NewParams creates a new Params instance func NewParams( - allowUnprotectedTxs bool, extraEIPs []int64, activeStaticPrecompiles, evmChannels []string, accessControl AccessControl, ) Params { return Params{ - AllowUnprotectedTxs: allowUnprotectedTxs, ExtraEIPs: extraEIPs, ActiveStaticPrecompiles: activeStaticPrecompiles, EVMChannels: evmChannels, @@ -67,10 +65,10 @@ func DefaultParams() Params { return Params{ EvmDenom: DefaultEVMDenom, ExtraEIPs: DefaultExtraEIPs, - AllowUnprotectedTxs: DefaultAllowUnprotectedTxs, ActiveStaticPrecompiles: DefaultStaticPrecompiles, EVMChannels: DefaultEVMChannels, AccessControl: DefaultAccessControl, + HistoryServeWindow: DefaultHistoryServeWindow, } } @@ -98,10 +96,6 @@ func (p Params) Validate() error { return err } - if err := validateBool(p.AllowUnprotectedTxs); err != nil { - return err - } - if err := ValidatePrecompiles(p.ActiveStaticPrecompiles); err != nil { return err } @@ -180,14 +174,6 @@ func validateAllowlistAddresses(i interface{}) error { return nil } -func validateBool(i interface{}) error { - _, ok := i.(bool) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - return nil -} - func validateEIPs(i interface{}) error { eips, ok := i.([]int64) if !ok { diff --git a/x/vm/types/params_legacy.go b/x/vm/types/params_legacy.go deleted file mode 100644 index e221fd66b..000000000 --- a/x/vm/types/params_legacy.go +++ /dev/null @@ -1,32 +0,0 @@ -package types - -import paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" - -// Parameter keys -var ( - ParamStoreKeyEVMDenom = []byte("EVMDenom") - ParamStoreKeyEnableCreate = []byte("EnableCreate") - ParamStoreKeyEnableCall = []byte("EnableCall") - ParamStoreKeyExtraEIPs = []byte("EnableExtraEIPs") - ParamStoreKeyChainConfig = []byte("ChainConfig") - ParamStoreKeyAllowUnprotectedTxs = []byte("AllowUnprotectedTxs") -) - -// Deprecated: ParamKeyTable returns the parameter key table. -// Usage of x/params to manage parameters is deprecated in favor of x/gov -// controlled execution of MsgUpdateParams messages. These types remain solely -// for migration purposes and will be removed in a future release. -func ParamKeyTable() paramtypes.KeyTable { - return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) -} - -// Deprecated: ParamSetPairs returns the parameter set pairs. -// Usage of x/params to manage parameters is deprecated in favor of x/gov -// controlled execution of MsgUpdateParams messages. These types remain solely -// for migration purposes and will be removed in a future release. -func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{ - paramtypes.NewParamSetPair(ParamStoreKeyExtraEIPs, &p.ExtraEIPs, validateEIPs), - paramtypes.NewParamSetPair(ParamStoreKeyAllowUnprotectedTxs, &p.AllowUnprotectedTxs, validateBool), - } -} diff --git a/x/vm/types/params_test.go b/x/vm/types/params_test.go index 47c10f4d8..23e8dc007 100644 --- a/x/vm/types/params_test.go +++ b/x/vm/types/params_test.go @@ -24,7 +24,7 @@ func TestParamsValidate(t *testing.T) { }, { name: "valid", - params: NewParams(false, extraEips, nil, nil, DefaultAccessControl), + params: NewParams(extraEips, nil, nil, DefaultAccessControl), expPass: true, }, { @@ -77,15 +77,13 @@ func TestParamsValidate(t *testing.T) { func TestParamsEIPs(t *testing.T) { extraEips := []int64{2929, 1884, 1344} - params := NewParams(false, extraEips, nil, nil, DefaultAccessControl) + params := NewParams(extraEips, nil, nil, DefaultAccessControl) actual := params.EIPs() require.Equal(t, []int{2929, 1884, 1344}, actual) } func TestParamsValidatePriv(t *testing.T) { - require.Error(t, validateBool("")) - require.NoError(t, validateBool(true)) require.Error(t, validateEIPs("")) require.NoError(t, validateEIPs([]int64{1884})) require.ErrorContains(t, validateEIPs([]int64{1884, 1884, 1885}), "duplicate EIP: 1884") diff --git a/x/vm/types/preinstall.go b/x/vm/types/preinstall.go index d11ac31f2..76dd298a0 100644 --- a/x/vm/types/preinstall.go +++ b/x/vm/types/preinstall.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) var DefaultPreinstalls = []Preinstall{ @@ -30,6 +31,11 @@ var DefaultPreinstalls = []Preinstall{ Address: "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7", Code: "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3", }, + { + Name: "EIP-2935 - Serve historical block hashes from state", + Address: params.HistoryStorageAddress.String(), + Code: common.Bytes2Hex(params.HistoryStorageCode), + }, } // Validate performs basic validation checks on the Preinstall diff --git a/x/vm/types/tracer.go b/x/vm/types/tracer.go index 902d679f4..426835b87 100644 --- a/x/vm/types/tracer.go +++ b/x/vm/types/tracer.go @@ -28,8 +28,10 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height switch tracer { case TracerAccessList: - blockAddrs := map[common.Address]struct{}{ - *msg.To: {}, msg.From: {}, + blockAddrs := make(map[common.Address]struct{}) + blockAddrs[msg.From] = struct{}{} + if msg.To != nil { + blockAddrs[*msg.To] = struct{}{} } precompiles := vm.ActivePrecompiles(cfg.Rules(big.NewInt(height), cfg.MergeNetsplitBlock != nil, timestamp)) for _, addr := range precompiles { @@ -43,7 +45,7 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height case TracerStruct: return logger.NewStructLogger(logCfg).Hooks() default: - return nil + return NewNoOpTracer() } } diff --git a/x/vm/types/tx.pb.go b/x/vm/types/tx.pb.go index 3dd000bf8..096775978 100644 --- a/x/vm/types/tx.pb.go +++ b/x/vm/types/tx.pb.go @@ -128,6 +128,12 @@ type MsgEthereumTxResponse struct { VmError string `protobuf:"bytes,4,opt,name=vm_error,json=vmError,proto3" json:"vm_error,omitempty"` // gas_used specifies how much gas was consumed by the transaction GasUsed uint64 `protobuf:"varint,5,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` + // max_used_gas specifies the gas consumed by the transaction, not including refunds + MaxUsedGas uint64 `protobuf:"varint,6,opt,name=max_used_gas,json=maxUsedGas,proto3" json:"max_used_gas,omitempty"` + // include the block hash for json-rpc to use + BlockHash []byte `protobuf:"bytes,7,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` + // include the block timestamp for json-rpc to use + BlockTimestamp uint64 `protobuf:"varint,8,opt,name=block_timestamp,json=blockTimestamp,proto3" json:"block_timestamp,omitempty"` } func (m *MsgEthereumTxResponse) Reset() { *m = MsgEthereumTxResponse{} } @@ -363,50 +369,53 @@ func init() { func init() { proto.RegisterFile("cosmos/evm/vm/v1/tx.proto", fileDescriptor_77a8ac5e8c9c4850) } var fileDescriptor_77a8ac5e8c9c4850 = []byte{ - // 678 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x4f, 0x6b, 0x13, 0x41, - 0x1c, 0xcd, 0x66, 0xb7, 0x6d, 0x3a, 0xad, 0x18, 0xc7, 0xd6, 0x6e, 0x97, 0xba, 0x49, 0x17, 0xff, - 0xa4, 0x05, 0xb3, 0x36, 0x82, 0x60, 0x3c, 0x19, 0xe8, 0xc1, 0x60, 0xb0, 0xac, 0xf6, 0x22, 0x42, - 0x98, 0x36, 0xe3, 0x64, 0x21, 0xbb, 0xb3, 0xce, 0x4c, 0x62, 0x7a, 0x10, 0xa4, 0x78, 0x10, 0x4f, - 0x82, 0x5f, 0xc0, 0x83, 0x07, 0x8f, 0x3d, 0x78, 0xf2, 0x13, 0xf4, 0x58, 0x14, 0x44, 0x44, 0x8a, - 0xb4, 0x42, 0xbf, 0x86, 0xcc, 0xee, 0xb6, 0xd9, 0x34, 0x0b, 0x15, 0x61, 0x09, 0xb3, 0xf3, 0xde, - 0xef, 0xfd, 0x7e, 0x6f, 0xde, 0x64, 0xc1, 0xfc, 0x26, 0xe5, 0x1e, 0xe5, 0x36, 0xee, 0x79, 0xb6, - 0x7c, 0x56, 0x6c, 0xd1, 0x2f, 0x07, 0x8c, 0x0a, 0x0a, 0xf3, 0x11, 0x54, 0xc6, 0x3d, 0xaf, 0x2c, - 0x9f, 0x15, 0xe3, 0x02, 0xf2, 0x5c, 0x9f, 0xda, 0xe1, 0x6f, 0x44, 0x32, 0x8c, 0x91, 0x7a, 0x49, - 0x8f, 0xb0, 0xb9, 0x18, 0xf3, 0x38, 0x91, 0x80, 0xc7, 0x49, 0x0c, 0xc4, 0x4d, 0x9b, 0xe1, 0x9b, - 0x1d, 0xb7, 0x89, 0xa0, 0x19, 0x42, 0x09, 0x8d, 0xf6, 0xe5, 0x2a, 0xde, 0x5d, 0x20, 0x94, 0x92, - 0x0e, 0xb6, 0x51, 0xe0, 0xda, 0xc8, 0xf7, 0xa9, 0x40, 0xc2, 0xa5, 0x7e, 0x5c, 0x63, 0xbd, 0x56, - 0xc0, 0xb9, 0x06, 0x27, 0xab, 0xa2, 0x8d, 0x19, 0xee, 0x7a, 0x8f, 0xfb, 0x10, 0x02, 0xed, 0x19, - 0xa3, 0x9e, 0x3e, 0x56, 0x54, 0x4a, 0xd3, 0x4e, 0xb8, 0x86, 0x57, 0x80, 0xca, 0xd0, 0x0b, 0x7d, - 0x5c, 0x6e, 0xd5, 0xe0, 0xee, 0x7e, 0x21, 0xf3, 0x73, 0xbf, 0x00, 0x06, 0x45, 0x8e, 0x84, 0xab, - 0x8b, 0x6f, 0x3e, 0x14, 0x32, 0x6f, 0x8f, 0x76, 0x96, 0xf5, 0x84, 0xb1, 0x21, 0xf1, 0xba, 0x96, - 0x53, 0xf2, 0xd9, 0xba, 0x96, 0xcb, 0xe6, 0xd5, 0xba, 0x96, 0x53, 0xf3, 0x5a, 0x5d, 0xcb, 0x69, - 0xf9, 0x31, 0xcb, 0x02, 0xc6, 0x6a, 0x5f, 0x60, 0x9f, 0xbb, 0xd4, 0x7f, 0x18, 0x84, 0x03, 0x0e, - 0xaa, 0xaa, 0x9a, 0x14, 0xb6, 0x3e, 0x2a, 0x60, 0x76, 0x48, 0xcd, 0xc1, 0x3c, 0xa0, 0x3e, 0xc7, - 0x72, 0xe4, 0x36, 0xe2, 0x6d, 0x5d, 0x29, 0x2a, 0xa5, 0x49, 0x27, 0x5c, 0xc3, 0x25, 0xa0, 0x75, - 0x28, 0xe1, 0x7a, 0xb6, 0xa8, 0x96, 0xa6, 0x2a, 0xb3, 0xe5, 0xd3, 0x81, 0x94, 0x1f, 0x50, 0xe2, - 0x84, 0x14, 0x98, 0x07, 0x2a, 0xc3, 0x42, 0x57, 0x43, 0xc3, 0x72, 0x09, 0xe7, 0x41, 0xae, 0xe7, - 0x35, 0x31, 0x63, 0x94, 0xe9, 0x5a, 0x28, 0x3a, 0xd1, 0xf3, 0x56, 0xe5, 0xab, 0x84, 0x08, 0xe2, - 0xcd, 0x2e, 0xc7, 0xad, 0xf0, 0x88, 0x34, 0x67, 0x82, 0x20, 0xbe, 0xce, 0x71, 0x2b, 0x1e, 0xf3, - 0x8b, 0x02, 0xce, 0x37, 0x38, 0x59, 0x0f, 0x5a, 0x48, 0xe0, 0x35, 0xc4, 0x90, 0xc7, 0xe1, 0x6d, - 0x30, 0x89, 0xba, 0xa2, 0x4d, 0x99, 0x2b, 0xb6, 0xa2, 0x29, 0x6b, 0xfa, 0xd7, 0xcf, 0x37, 0x66, - 0xe2, 0xa1, 0xee, 0xb5, 0x5a, 0x0c, 0x73, 0xfe, 0x48, 0x30, 0xd7, 0x27, 0xce, 0x80, 0x0a, 0xef, - 0x82, 0xf1, 0x20, 0x54, 0xd0, 0xb3, 0x45, 0xa5, 0x34, 0x55, 0xd1, 0x47, 0x6d, 0x44, 0x1d, 0x6a, - 0x93, 0x32, 0x94, 0x4f, 0x47, 0x3b, 0xcb, 0x8a, 0x13, 0x97, 0x54, 0x2b, 0xdb, 0x47, 0x3b, 0xcb, - 0x03, 0x31, 0x19, 0x4c, 0x21, 0x11, 0x4c, 0xdf, 0x8e, 0xd2, 0x49, 0x0e, 0x6a, 0xcd, 0x83, 0xb9, - 0x53, 0x5b, 0xc7, 0x87, 0x6c, 0x7d, 0x57, 0xc0, 0xa5, 0x06, 0x27, 0x0e, 0x26, 0x2e, 0x17, 0x98, - 0xad, 0x31, 0xec, 0xfa, 0x5c, 0xa0, 0x4e, 0xe7, 0xff, 0xed, 0xdd, 0x07, 0x53, 0xc1, 0x40, 0x26, - 0x8e, 0x6a, 0x21, 0xc5, 0xe3, 0x09, 0x29, 0xe9, 0x33, 0x59, 0x5b, 0xbd, 0x33, 0x6a, 0xf6, 0x5a, - 0x8a, 0xd9, 0x94, 0xe9, 0xad, 0x22, 0x30, 0xd3, 0x91, 0x63, 0xeb, 0x95, 0x5f, 0x59, 0xa0, 0x36, - 0x38, 0x81, 0x2f, 0x41, 0xe2, 0xce, 0xc3, 0xc2, 0xe8, 0xa0, 0x43, 0xd7, 0xd3, 0xb8, 0x7e, 0x06, - 0xe1, 0xe4, 0x68, 0xaf, 0x6e, 0x7f, 0xfb, 0xf3, 0x3e, 0x5b, 0xb0, 0x2e, 0xdb, 0xa3, 0x5f, 0x84, - 0x98, 0xdd, 0x14, 0x7d, 0xf8, 0x14, 0x4c, 0x0f, 0xdd, 0xaa, 0xc5, 0x54, 0xfd, 0x24, 0xc5, 0x58, - 0x3a, 0x93, 0x72, 0xf2, 0x27, 0x7a, 0x0e, 0x2e, 0xa6, 0x65, 0x5b, 0x4a, 0x55, 0x48, 0x61, 0x1a, - 0x37, 0xff, 0x95, 0x79, 0xdc, 0xd2, 0x18, 0x7b, 0x25, 0x83, 0xac, 0x55, 0x77, 0x0f, 0x4c, 0x65, - 0xef, 0xc0, 0x54, 0x7e, 0x1f, 0x98, 0xca, 0xbb, 0x43, 0x33, 0xb3, 0x77, 0x68, 0x66, 0x7e, 0x1c, - 0x9a, 0x99, 0x27, 0x45, 0xe2, 0x8a, 0x76, 0x77, 0xa3, 0xbc, 0x49, 0x3d, 0xfb, 0x74, 0x9a, 0x62, - 0x2b, 0xc0, 0x7c, 0x63, 0x3c, 0xfc, 0x8c, 0xdd, 0xfa, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x48, - 0x3b, 0x6f, 0x8c, 0x05, 0x00, 0x00, + // 736 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x4d, 0x6b, 0x13, 0x41, + 0x18, 0xce, 0x26, 0xdb, 0x36, 0x99, 0x56, 0x1b, 0xd7, 0xd6, 0x6e, 0x97, 0x36, 0x49, 0x17, 0xb5, + 0x69, 0xc1, 0xac, 0x8d, 0x20, 0x18, 0x4f, 0x06, 0x8a, 0x1a, 0x0c, 0x96, 0xb5, 0xbd, 0x88, 0x10, + 0xa6, 0xcd, 0x38, 0x59, 0xcc, 0xec, 0xac, 0x3b, 0x93, 0x98, 0x1e, 0x04, 0x29, 0x1e, 0xc4, 0x83, + 0x08, 0xfe, 0x01, 0x8f, 0x1e, 0x7b, 0xf0, 0xe4, 0x2f, 0xe8, 0xb1, 0x28, 0x88, 0x88, 0x14, 0x69, + 0x85, 0xfe, 0x0d, 0x99, 0xd9, 0x4d, 0x93, 0x34, 0x0b, 0x15, 0x61, 0x59, 0x66, 0xdf, 0xe7, 0x79, + 0x9f, 0xf7, 0x73, 0x16, 0xcc, 0x6e, 0x51, 0x46, 0x28, 0xb3, 0x50, 0x9b, 0x58, 0xe2, 0x59, 0xb1, + 0x78, 0xa7, 0xe0, 0xf9, 0x94, 0x53, 0x2d, 0x1d, 0x40, 0x05, 0xd4, 0x26, 0x05, 0xf1, 0xac, 0x18, + 0x17, 0x20, 0x71, 0x5c, 0x6a, 0xc9, 0x77, 0x40, 0x32, 0x8c, 0x21, 0x7f, 0x41, 0x0f, 0xb0, 0x99, + 0x10, 0x23, 0x0c, 0x0b, 0x80, 0x30, 0x1c, 0x02, 0x61, 0xd0, 0x9a, 0xfc, 0xb2, 0xc2, 0x30, 0x01, + 0x34, 0x85, 0x29, 0xa6, 0x81, 0x5d, 0x9c, 0x42, 0xeb, 0x1c, 0xa6, 0x14, 0x37, 0x91, 0x05, 0x3d, + 0xc7, 0x82, 0xae, 0x4b, 0x39, 0xe4, 0x0e, 0x75, 0x43, 0x1f, 0xf3, 0xb5, 0x02, 0xce, 0x55, 0x19, + 0x5e, 0xe5, 0x0d, 0xe4, 0xa3, 0x16, 0x59, 0xef, 0x68, 0x1a, 0x50, 0x9f, 0xfa, 0x94, 0xe8, 0x23, + 0x39, 0x25, 0x3f, 0x61, 0xcb, 0xb3, 0x76, 0x19, 0x24, 0x7c, 0xf8, 0x42, 0x1f, 0x15, 0xa6, 0xb2, + 0xb6, 0x77, 0x90, 0x8d, 0xfd, 0x3c, 0xc8, 0x82, 0x9e, 0x93, 0x2d, 0xe0, 0xd2, 0xc2, 0x9b, 0x8f, + 0xd9, 0xd8, 0xdb, 0xe3, 0xdd, 0x65, 0xbd, 0xaf, 0xb0, 0x01, 0xf1, 0x8a, 0x9a, 0x54, 0xd2, 0xf1, + 0x8a, 0x9a, 0x8c, 0xa7, 0x13, 0x15, 0x35, 0x99, 0x48, 0xab, 0x15, 0x35, 0xa9, 0xa6, 0x47, 0x4c, + 0x13, 0x18, 0xab, 0x1d, 0x8e, 0x5c, 0xe6, 0x50, 0xf7, 0xa1, 0x27, 0x13, 0xec, 0x79, 0x95, 0x54, + 0x21, 0x6c, 0xbe, 0x8b, 0x83, 0xe9, 0x01, 0x35, 0x1b, 0x31, 0x8f, 0xba, 0x0c, 0x89, 0x94, 0x1b, + 0x90, 0x35, 0x74, 0x25, 0xa7, 0xe4, 0x53, 0xb6, 0x3c, 0x6b, 0x4b, 0x40, 0x6d, 0x52, 0xcc, 0xf4, + 0x78, 0x2e, 0x91, 0x1f, 0x2f, 0x4e, 0x17, 0x4e, 0x0f, 0xa4, 0xf0, 0x80, 0x62, 0x5b, 0x52, 0xb4, + 0x34, 0x48, 0xf8, 0x88, 0xeb, 0x09, 0x59, 0xb0, 0x38, 0x6a, 0xb3, 0x20, 0xd9, 0x26, 0x35, 0xe4, + 0xfb, 0xd4, 0xd7, 0x55, 0x29, 0x3a, 0xd6, 0x26, 0xab, 0xe2, 0x53, 0x40, 0x18, 0xb2, 0x5a, 0x8b, + 0xa1, 0xba, 0x6c, 0x91, 0x6a, 0x8f, 0x61, 0xc8, 0x36, 0x18, 0xaa, 0x6b, 0x39, 0x30, 0x41, 0x60, + 0x47, 0x42, 0x35, 0x0c, 0x99, 0x6c, 0x97, 0x6a, 0x03, 0x02, 0x3b, 0x02, 0xbe, 0x0b, 0x99, 0x36, + 0x0f, 0xc0, 0x66, 0x93, 0x6e, 0x3d, 0xab, 0xc9, 0x74, 0xc7, 0x64, 0xc0, 0x94, 0xb4, 0xdc, 0x13, + 0x39, 0x2f, 0x82, 0xc9, 0x00, 0xe6, 0x0e, 0x41, 0x8c, 0x43, 0xe2, 0xe9, 0x49, 0xa9, 0x71, 0x5e, + 0x9a, 0xd7, 0xbb, 0xd6, 0xb0, 0x21, 0x5f, 0x14, 0x30, 0x59, 0x65, 0x78, 0xc3, 0xab, 0x43, 0x8e, + 0xd6, 0xa0, 0x0f, 0x09, 0xd3, 0x6e, 0x82, 0x14, 0x6c, 0xf1, 0x06, 0xf5, 0x1d, 0xbe, 0x1d, 0xf4, + 0xa3, 0xac, 0x7f, 0xfd, 0x7c, 0x6d, 0x2a, 0x2c, 0xff, 0x4e, 0xbd, 0xee, 0x23, 0xc6, 0x1e, 0x71, + 0xdf, 0x71, 0xb1, 0xdd, 0xa3, 0x6a, 0xb7, 0xc1, 0xa8, 0x27, 0x15, 0xf4, 0x78, 0x4e, 0xc9, 0x8f, + 0x17, 0xf5, 0xe1, 0x86, 0x05, 0x11, 0xca, 0x29, 0x31, 0xfe, 0x4f, 0xc7, 0xbb, 0xcb, 0x8a, 0x1d, + 0xba, 0x94, 0x8a, 0x3b, 0xc7, 0xbb, 0xcb, 0x3d, 0x31, 0xb1, 0x02, 0xd9, 0xbe, 0x15, 0xe8, 0x58, + 0xc1, 0x1e, 0xf4, 0x27, 0x6a, 0xce, 0x82, 0x99, 0x53, 0xa6, 0xee, 0x38, 0xcd, 0xef, 0x0a, 0xb8, + 0x54, 0x65, 0xd8, 0x46, 0xd8, 0x61, 0x1c, 0xf9, 0x6b, 0x3e, 0x72, 0x5c, 0xc6, 0x61, 0xb3, 0xf9, + 0xff, 0xe5, 0xdd, 0x07, 0xe3, 0x5e, 0x4f, 0x26, 0x5c, 0x8a, 0xb9, 0x88, 0x1a, 0x4f, 0x48, 0xfd, + 0x75, 0xf6, 0xfb, 0x96, 0x6e, 0x0d, 0x17, 0x7b, 0x35, 0xa2, 0xd8, 0x88, 0xec, 0xcd, 0x1c, 0xc8, + 0x44, 0x23, 0xdd, 0xd2, 0x8b, 0xbf, 0xe2, 0x20, 0x51, 0x65, 0x58, 0x7b, 0x09, 0xfa, 0x6e, 0x97, + 0x96, 0x1d, 0x4e, 0x74, 0xe0, 0x22, 0x18, 0x8b, 0x67, 0x10, 0x4e, 0x5a, 0x7b, 0x65, 0xe7, 0xdb, + 0x9f, 0x0f, 0xf1, 0xac, 0x39, 0x6f, 0x0d, 0xff, 0x7b, 0x42, 0x76, 0x8d, 0x77, 0xb4, 0x27, 0x60, + 0x62, 0x60, 0xab, 0x16, 0x22, 0xf5, 0xfb, 0x29, 0xc6, 0xd2, 0x99, 0x94, 0x93, 0xeb, 0xfa, 0x1c, + 0x5c, 0x8c, 0x9a, 0x6d, 0x3e, 0x52, 0x21, 0x82, 0x69, 0x5c, 0xff, 0x57, 0x66, 0x37, 0xa4, 0x31, + 0xf2, 0x4a, 0x0c, 0xb2, 0x5c, 0xda, 0x3b, 0xcc, 0x28, 0xfb, 0x87, 0x19, 0xe5, 0xf7, 0x61, 0x46, + 0x79, 0x7f, 0x94, 0x89, 0xed, 0x1f, 0x65, 0x62, 0x3f, 0x8e, 0x32, 0xb1, 0xc7, 0x39, 0xec, 0xf0, + 0x46, 0x6b, 0xb3, 0xb0, 0x45, 0x89, 0x75, 0x7a, 0x9a, 0x7c, 0xdb, 0x43, 0x6c, 0x73, 0x54, 0xfe, + 0x30, 0x6f, 0xfc, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xb8, 0x53, 0x9d, 0xf6, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -658,6 +667,23 @@ func (m *MsgEthereumTxResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.BlockTimestamp != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.BlockTimestamp)) + i-- + dAtA[i] = 0x40 + } + if len(m.BlockHash) > 0 { + i -= len(m.BlockHash) + copy(dAtA[i:], m.BlockHash) + i = encodeVarintTx(dAtA, i, uint64(len(m.BlockHash))) + i-- + dAtA[i] = 0x3a + } + if m.MaxUsedGas != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.MaxUsedGas)) + i-- + dAtA[i] = 0x30 + } if m.GasUsed != 0 { i = encodeVarintTx(dAtA, i, uint64(m.GasUsed)) i-- @@ -893,6 +919,16 @@ func (m *MsgEthereumTxResponse) Size() (n int) { if m.GasUsed != 0 { n += 1 + sovTx(uint64(m.GasUsed)) } + if m.MaxUsedGas != 0 { + n += 1 + sovTx(uint64(m.MaxUsedGas)) + } + l = len(m.BlockHash) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.BlockTimestamp != 0 { + n += 1 + sovTx(uint64(m.BlockTimestamp)) + } return n } @@ -1301,6 +1337,78 @@ func (m *MsgEthereumTxResponse) Unmarshal(dAtA []byte) error { break } } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxUsedGas", wireType) + } + m.MaxUsedGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxUsedGas |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BlockHash = append(m.BlockHash[:0], dAtA[iNdEx:postIndex]...) + if m.BlockHash == nil { + m.BlockHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockTimestamp", wireType) + } + m.BlockTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockTimestamp |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/vm/types/utils.go b/x/vm/types/utils.go index 74b287a26..07cbefb26 100644 --- a/x/vm/types/utils.go +++ b/x/vm/types/utils.go @@ -3,7 +3,6 @@ package types import ( "bytes" "encoding/hex" - "encoding/json" "fmt" "math/big" "sort" @@ -12,8 +11,6 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/gogoproto/proto" errorsmod "cosmossdk.io/errors" @@ -85,50 +82,31 @@ func logsFromTxResponse(dst []*ethtypes.Log, rsp *MsgEthereumTxResponse, blockNu l := log.ToEthereum() l.TxHash = txHash l.BlockNumber = blockNumber + if len(rsp.BlockHash) > 0 { + l.BlockHash = common.BytesToHash(rsp.BlockHash) + } + if rsp.BlockTimestamp > 0 { + l.BlockTimestamp = rsp.BlockTimestamp + } dst = append(dst, l) } return dst } -// TxLogsFromEvents parses ethereum logs from cosmos events for specific msg index -func TxLogsFromEvents(events []abci.Event, msgIndex int) ([]*ethtypes.Log, error) { - index := msgIndex - for _, event := range events { - if event.Type != EventTypeTxLog { - continue - } - - if msgIndex > 0 { - // not the eth tx we want - msgIndex-- - continue - } - - return ParseTxLogsFromEvent(event) +// DecodeMsgLogs decodes a protobuf-encoded byte slice into ethereum logs, for a single message. +func DecodeMsgLogs(in []byte, msgIndex int, blockNumber uint64) ([]*ethtypes.Log, error) { + txResponses, err := DecodeTxResponses(in) + if err != nil { + return nil, err } - return nil, fmt.Errorf("eth tx logs not found for message index %d", index) -} - -// ParseTxLogsFromEvent parse tx logs from one event -func ParseTxLogsFromEvent(event abci.Event) ([]*ethtypes.Log, error) { - logs := make([]*Log, 0, len(event.Attributes)) - for _, attr := range event.Attributes { - if attr.Key != AttributeKeyTxLog { - continue - } - - var log Log - if err := json.Unmarshal([]byte(attr.Value), &log); err != nil { - return nil, err - } - - logs = append(logs, &log) + if msgIndex >= len(txResponses) { + return nil, fmt.Errorf("invalid message index: %d", msgIndex) } - return LogsToEthereum(logs), nil + return logsFromTxResponse(nil, txResponses[msgIndex], blockNumber), nil } -// DecodeTxLogsFromEvents decodes a protobuf-encoded byte slice into ethereum logs -func DecodeTxLogsFromEvents(in []byte, events []abci.Event, blockNumber uint64) ([]*ethtypes.Log, error) { +// DecodeTxLogs decodes a protobuf-encoded byte slice into ethereum logs +func DecodeTxLogs(in []byte, blockNumber uint64) ([]*ethtypes.Log, error) { txResponses, err := DecodeTxResponses(in) if err != nil { return nil, err @@ -137,18 +115,6 @@ func DecodeTxLogsFromEvents(in []byte, events []abci.Event, blockNumber uint64) for _, response := range txResponses { logs = logsFromTxResponse(logs, response, blockNumber) } - if len(logs) == 0 { - for _, event := range events { - if event.Type != EventTypeTxLog { - continue - } - txLogs, err := ParseTxLogsFromEvent(event) - if err != nil { - return nil, err - } - logs = append(logs, txLogs...) - } - } return logs, nil } diff --git a/x/vm/types/utils_test.go b/x/vm/types/utils_test.go index 7f6e691a9..bb348fd3a 100644 --- a/x/vm/types/utils_test.go +++ b/x/vm/types/utils_test.go @@ -1,9 +1,7 @@ package types_test import ( - "encoding/json" "errors" - "fmt" "math/big" "testing" @@ -11,8 +9,6 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/evm/encoding" utiltx "github.com/cosmos/evm/testutil/tx" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -151,128 +147,119 @@ func TestDecodeTxResponse(t *testing.T) { } } +func createTxResponseData(t *testing.T, key string) ([]byte, []*evmtypes.MsgEthereumTxResponse) { + t.Helper() + switch key { + case "multiple": + // 1st response + data1 := &evmtypes.MsgEthereumTxResponse{ + Hash: common.BytesToHash([]byte("hash1")).String(), + Logs: []*evmtypes.Log{createLog(t, testAddress, []string{testTopic}, 0, 0)}, + Ret: []byte{0x1}, + } + // 2nd response + data2 := &evmtypes.MsgEthereumTxResponse{ + Hash: common.BytesToHash([]byte("hash2")).String(), + Logs: []*evmtypes.Log{createLog(t, testAddress, []string{testTopic}, 0, 0)}, + Ret: []byte{0x2}, + } + anyData1 := codectypes.UnsafePackAny(data1) + anyData2 := codectypes.UnsafePackAny(data2) + txData := &sdk.TxMsgData{ + MsgResponses: []*codectypes.Any{anyData1, anyData2}, + } + txDataBz, _ := proto.Marshal(txData) + return txDataBz, []*evmtypes.MsgEthereumTxResponse{data1, data2} + case "single": + data := &evmtypes.MsgEthereumTxResponse{ + Hash: common.BytesToHash([]byte("hash")).String(), + Logs: []*evmtypes.Log{createLog(t, testAddress, []string{testTopic}, 0, 0)}, + Ret: []byte{0x5, 0x8}, + } + anyData := codectypes.UnsafePackAny(data) + txData := &sdk.TxMsgData{ + MsgResponses: []*codectypes.Any{anyData}, + } + txDataBz, _ := proto.Marshal(txData) + return txDataBz, []*evmtypes.MsgEthereumTxResponse{data} + case "empty": + txData := &sdk.TxMsgData{ + MsgResponses: []*codectypes.Any{}, + } + txDataBz, _ := proto.Marshal(txData) + return txDataBz, []*evmtypes.MsgEthereumTxResponse{} + case "mixed": + // EVM response + evmData := &evmtypes.MsgEthereumTxResponse{ + Hash: common.BytesToHash([]byte("evm_hash")).String(), + Ret: []byte{0x99}, + } + evmAnyData := codectypes.UnsafePackAny(evmData) + // Non-EVM response + bankData := &codectypes.Any{ + TypeUrl: "/cosmos.bank.v1beta1.MsgSendResponse", + Value: []byte("bank response"), + } + txData := &sdk.TxMsgData{ + MsgResponses: []*codectypes.Any{evmAnyData, bankData}, + } + txDataBz, _ := proto.Marshal(txData) + return txDataBz, []*evmtypes.MsgEthereumTxResponse{evmData} + case "invalid": + return []byte("invalid protobuf data"), nil + case "nil": + return nil, nil + default: + return []byte{}, nil + } +} + func TestDecodeTxResponses(t *testing.T) { testCases := []struct { name string - setupData func() []byte + txDataKey string expectError bool expectLength int expectNil bool }{ { - name: "multiple tx responses", - setupData: func() []byte { - // 1st response - data1 := &evmtypes.MsgEthereumTxResponse{ - Hash: common.BytesToHash([]byte("hash1")).String(), - Logs: []*evmtypes.Log{{ - Address: common.HexToAddress("0x1111").String(), - Data: []byte{1, 2}, - BlockNumber: 10, - }}, - Ret: []byte{0x1}, - } - // 2nd response - data2 := &evmtypes.MsgEthereumTxResponse{ - Hash: common.BytesToHash([]byte("hash2")).String(), - Logs: []*evmtypes.Log{{ - Address: common.HexToAddress("0x2222").String(), - Data: []byte{3, 4}, - BlockNumber: 11, - }}, - Ret: []byte{0x2}, - } - anyData1 := codectypes.UnsafePackAny(data1) - anyData2 := codectypes.UnsafePackAny(data2) - txData := &sdk.TxMsgData{ - MsgResponses: []*codectypes.Any{anyData1, anyData2}, - } - txDataBz, _ := proto.Marshal(txData) - return txDataBz - }, + name: "multiple tx responses", + txDataKey: "multiple", expectError: false, expectLength: 2, expectNil: false, }, { - name: "single tx response", - setupData: func() []byte { - ret := []byte{0x5, 0x8} - data := &evmtypes.MsgEthereumTxResponse{ - Hash: common.BytesToHash([]byte("hash")).String(), - Logs: []*evmtypes.Log{{ - Data: []byte{1, 2, 3, 4}, - BlockNumber: 17, - }}, - Ret: ret, - } - - anyData := codectypes.UnsafePackAny(data) - txData := &sdk.TxMsgData{ - MsgResponses: []*codectypes.Any{anyData}, - } - - txDataBz, _ := proto.Marshal(txData) - return txDataBz - }, + name: "single tx response", + txDataKey: "single", expectError: false, expectLength: 1, expectNil: false, }, { - name: "empty responses", - setupData: func() []byte { - txData := &sdk.TxMsgData{ - MsgResponses: []*codectypes.Any{}, - } - txDataBz, _ := proto.Marshal(txData) - return txDataBz - }, + name: "empty responses", + txDataKey: "empty", expectError: false, expectLength: 0, expectNil: false, }, { - name: "mixed response types", - setupData: func() []byte { - // EVM response - evmData := &evmtypes.MsgEthereumTxResponse{ - Hash: common.BytesToHash([]byte("evm_hash")).String(), - Ret: []byte{0x99}, - } - evmAnyData := codectypes.UnsafePackAny(evmData) - - // Non-EVM response - bankData := &codectypes.Any{ - TypeUrl: "/cosmos.bank.v1beta1.MsgSendResponse", - Value: []byte("bank response"), - } - - txData := &sdk.TxMsgData{ - MsgResponses: []*codectypes.Any{evmAnyData, bankData}, - } - - txDataBz, _ := proto.Marshal(txData) - return txDataBz - }, + name: "mixed response types", + txDataKey: "mixed", expectError: false, expectLength: 1, // Only EVM responses are included expectNil: false, }, { - name: "invalid protobuf data", - setupData: func() []byte { - return []byte("completely invalid data") - }, + name: "invalid protobuf data", + txDataKey: "invalid", expectError: true, expectLength: 0, expectNil: true, }, { - name: "nil input", - setupData: func() []byte { - return nil - }, + name: "nil input", + txDataKey: "nil", expectError: false, expectLength: 0, expectNil: true, @@ -281,9 +268,8 @@ func TestDecodeTxResponses(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - data := tc.setupData() - - results, err := evmtypes.DecodeTxResponses(data) + txDataBz, _ := createTxResponseData(t, tc.txDataKey) + results, err := evmtypes.DecodeTxResponses(txDataBz) if tc.expectError { require.Error(t, err) @@ -309,7 +295,7 @@ func TestDecodeTxResponses(t *testing.T) { require.Equal(t, common.BytesToHash([]byte("hash")).String(), results[0].Hash) require.Equal(t, []byte{0x5, 0x8}, results[0].Ret) require.Len(t, results[0].Logs, 1) - require.Equal(t, []byte{1, 2, 3, 4}, results[0].Logs[0].Data) + require.Equal(t, []byte(testData), results[0].Logs[0].Data) } if tc.name == "mixed response types" { @@ -321,514 +307,25 @@ func TestDecodeTxResponses(t *testing.T) { } } -func TestTxLogsFromEvents(t *testing.T) { - address := "0xc5570e6B97044960be06962E13248EC6b13107AE" - topic := "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" - - testCases := []struct { - name string - events []abci.Event - msgIndex int - expectNotFoundErr bool - expectParseErr bool - expectLogs int - validate func(t *testing.T, logs []*ethtypes.Log) - }{ - { - name: "logs found at index 0", - events: []abci.Event{ - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 0, 0), - }, - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0xd09f7c8c4529cb5d387aa17e33d707c529a6f694", []string{"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"}, 0, 1), - }, - }, - }, - }, - msgIndex: 0, - expectNotFoundErr: false, - expectLogs: 2, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Equal(t, common.HexToAddress("0xd09f7c8c4529cb5d387aa17e33d707c529a6f694"), logs[1].Address) - require.Equal(t, common.HexToHash(topic), logs[0].Topics[0]) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - }, - }, - { - name: "logs found at index 1 - skips first event", - events: []abci.Event{ - // First event (index 0) - should be skipped - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0x1111111111111111111111111111111111111111", []string{"0x1111111111111111111111111111111111111111111111111111111111111111"}, 0, 0), - }, - }, - }, - // Second event (index 1) - should be returned - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 1, 0), - }, - }, - }, - }, - msgIndex: 1, - expectNotFoundErr: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Equal(t, common.HexToHash(topic), logs[0].Topics[0]) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - require.Equal(t, uint(1), logs[0].TxIndex) - }, - }, - { - name: "logs found at index 2 - skips multiple events", - events: []abci.Event{ - // Event index 0 - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0x1111111111111111111111111111111111111111", []string{"0x1111111111111111111111111111111111111111111111111111111111111111"}, 0, 0), - }, - }, - }, - // Event index 1 - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0x2222222222222222222222222222222222222222", []string{"0x2222222222222222222222222222222222222222222222222222222222222222"}, 1, 0), - }, - }, - }, - // Event index 2 - target - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 2, 0), - }, - }, - }, - }, - msgIndex: 2, - expectNotFoundErr: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - require.Equal(t, uint(2), logs[0].TxIndex) - }, - }, - { - name: "mixed event types - only tx log events count", - events: []abci.Event{ - // Non-tx log event - should be ignored - { - Type: "other_event_type", - Attributes: []abci.EventAttribute{ - {Key: "irrelevant", Value: "data"}, - }, - }, - // Tx log event index 0 - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 0, 0), - }, - }, - }, - // Another non-tx log event - should be ignored - { - Type: "another_event", - Attributes: []abci.EventAttribute{ - {Key: "more", Value: "irrelevant"}, - }, - }, - }, - msgIndex: 0, - expectNotFoundErr: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - }, - }, - { - name: "no tx log events found", - events: []abci.Event{ - { - Type: "other_event_type", - Attributes: []abci.EventAttribute{ - {Key: "key", Value: "value"}, - }, - }, - { - Type: "another_event_type", - Attributes: []abci.EventAttribute{ - {Key: "key2", Value: "value2"}, - }, - }, - }, - msgIndex: 0, - expectNotFoundErr: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - { - name: "msg index out of range", - events: []abci.Event{ - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 0, 0), - }, - }, - }, - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0x2222222222222222222222222222222222222222", []string{"0x2222222222222222222222222222222222222222222222222222222222222222"}, 1, 0), - }, - }, - }, - }, - msgIndex: 5, // Only 2 events available, asking for index 5 - expectNotFoundErr: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - { - name: "empty events slice", - events: []abci.Event{}, - msgIndex: 0, - expectNotFoundErr: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - { - name: "event with invalid JSON log - should propagate error from ParseTxLogsFromEvent", - events: []abci.Event{ - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: "invalid json data", - }, - }, - }, - }, - msgIndex: 0, - expectNotFoundErr: true, - expectParseErr: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - { - name: "event with empty topics and data", - events: []abci.Event{ - { - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{}, 0, 0), - }, - }, - }, - }, - msgIndex: 0, - expectNotFoundErr: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Len(t, logs[0].Topics, 0) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - }, - }, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - logs, err := evmtypes.TxLogsFromEvents(tc.events, tc.msgIndex) - if tc.expectNotFoundErr { - require.Error(t, err) - require.Nil(t, logs) - if tc.expectParseErr { - require.Contains(t, err.Error(), "invalid character") - } else { - require.Contains(t, err.Error(), fmt.Sprintf("eth tx logs not found for message index %d", tc.msgIndex)) - } - } else { - require.NoError(t, err) - require.NotNil(t, logs) - require.Len(t, logs, tc.expectLogs) - for _, log := range logs { - require.NotNil(t, log) - require.IsType(t, ðtypes.Log{}, log) - require.NotNil(t, log.Address) - require.NotNil(t, log.Topics) - require.NotNil(t, log.Data) - } - tc.validate(t, logs) - } - }) - } -} - -const testBlockNumber = uint64(3) +const ( + testAddress = "0xc5570e6B97044960be06962E13248EC6b13107AE" + testTopic = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + testData = "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo=" +) -// createLogEventValue creates a JSON string representation of an EVM log event -func createLogEventValue(t *testing.T, address string, topics []string, txIndex, logIndex uint64) string { +func createLog(t *testing.T, address string, topics []string, txIndex, logIndex uint64) *evmtypes.Log { t.Helper() - log := &evmtypes.Log{ + return &evmtypes.Log{ Address: address, Topics: topics, - Data: []byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo="), - BlockNumber: testBlockNumber, + Data: []byte(testData), + BlockNumber: uint64(3), TxHash: "0x0eb002bd8fa02c0b0d549acfca70f7aab5fa745af118c76dda60a1f4329d0de1", TxIndex: txIndex, BlockHash: "0xa7a5ee692701bb2f971b9d1a1ab4bbf10599b0ce3814ea2b60c59a4a4a1d2e4c", Index: logIndex, Removed: false, } - jsonBytes, err := json.Marshal(log) - require.NoError(t, err) - return string(jsonBytes) -} - -func TestParseTxLogsFromEvent(t *testing.T) { - address := "0xc5570e6B97044960be06962E13248EC6b13107AE" - topic := "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" - - testCases := []struct { - name string - event abci.Event - expectError bool - expectLogs int - validate func(t *testing.T, logs []*ethtypes.Log) - }{ - { - name: "single valid log", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{ - topic, - "0x000000000000000000000000378c50d9264c63f3f92b806d4ee56e9d86ffb3ec", - "0x000000000000000000000000d09f7c8c4529cb5d387aa17e33d707c529a6f694", - }, 0, 0), - }, - }, - }, - expectError: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - log := logs[0] - require.Equal(t, common.HexToAddress(address), log.Address) - require.Len(t, log.Topics, 3) - require.Equal(t, common.HexToHash(topic), log.Topics[0]) - require.Equal(t, testBlockNumber, log.BlockNumber) - require.Equal(t, uint(0), log.TxIndex) - require.Equal(t, uint(0), log.Index) - require.False(t, log.Removed) - }, - }, - { - name: "multiple valid logs", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 0, 0), - }, - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0xd09f7c8c4529cb5d387aa17e33d707c529a6f694", []string{"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"}, 1, 1), - }, - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, "0x378c50d9264c63f3f92b806d4ee56e9d86ffb3ec", []string{"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}, 2, 2), - }, - }, - }, - expectError: false, - expectLogs: 3, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Equal(t, common.HexToAddress("0xd09f7c8c4529cb5d387aa17e33d707c529a6f694"), logs[1].Address) - require.Equal(t, common.HexToAddress("0x378c50d9264c63f3f92b806d4ee56e9d86ffb3ec"), logs[2].Address) - require.Equal(t, uint(0), logs[0].TxIndex) - require.Equal(t, uint(1), logs[1].TxIndex) - require.Equal(t, uint(2), logs[2].TxIndex) - }, - }, - { - name: "event with non-log attributes", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - {Key: "other_attribute", Value: "some value"}, - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 0, 0), - }, - {Key: "another_attribute", Value: "another value"}, - }, - }, - expectError: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Equal(t, common.HexToAddress(address), logs[0].Address) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - }, - }, - { - name: "event with no log attributes", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - {Key: "not_a_log", Value: "some value"}, - {Key: "another_non_log", Value: "another value"}, - }, - }, - expectError: false, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, // No validation needed for empty - }, - { - name: "invalid JSON in log attribute", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - {Key: evmtypes.AttributeKeyTxLog, Value: "invalid json format"}, - }, - }, - expectError: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, // No validation for error case - }, - { - name: "malformed JSON structure", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - {Key: evmtypes.AttributeKeyTxLog, Value: `{"address": "incomplete`}, - }, - }, - expectError: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - { - name: "empty log attribute value", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - {Key: evmtypes.AttributeKeyTxLog, Value: ""}, - }, - }, - expectError: true, - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - { - name: "log with empty topics array", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{}, 0, 0), - }, - }, - }, - expectError: false, - expectLogs: 1, - validate: func(t *testing.T, logs []*ethtypes.Log) { - t.Helper() - require.Len(t, logs[0].Topics, 0) - require.Equal(t, testBlockNumber, logs[0].BlockNumber) - }, - }, - { - name: "mixed valid and invalid log attributes", - event: abci.Event{ - Type: evmtypes.EventTypeTxLog, - Attributes: []abci.EventAttribute{ - { - Key: evmtypes.AttributeKeyTxLog, - Value: createLogEventValue(t, address, []string{topic}, 0, 0), - }, - {Key: evmtypes.AttributeKeyTxLog, Value: "invalid json"}, - }, - }, - expectError: true, // Should fail on the invalid JSON - expectLogs: 0, - validate: func(t *testing.T, logs []*ethtypes.Log) { t.Helper() }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - logs, err := evmtypes.ParseTxLogsFromEvent(tc.event) - if tc.expectError { - require.Error(t, err) - require.Nil(t, logs) - return - } - require.NoError(t, err) - if tc.expectLogs == 0 { - require.Empty(t, logs) - } else { - require.NotNil(t, logs) - require.Len(t, logs, tc.expectLogs) - for _, log := range logs { - require.NotNil(t, log) - require.IsType(t, ðtypes.Log{}, log) - require.NotNil(t, log.Address) - require.NotNil(t, log.Topics) - require.NotNil(t, log.Data) - } - tc.validate(t, logs) - } - }) - } } func TestUnwrapEthererumMsg(t *testing.T) { @@ -909,3 +406,144 @@ func TestTransactionLogsEncodeDecode(t *testing.T) { require.Nil(t, decodeErr) require.Equal(t, txLogs, txLogsEncodedDecoded) } + +func TestDecodeMsgLogs(t *testing.T) { + testCases := []struct { + name string + txDataKey string + msgIndex int + blockNum uint64 + expectError bool + }{ + { + name: "multiple tx responses, valid msgIndex 0", + txDataKey: "multiple", + msgIndex: 0, + blockNum: 12, + }, + { + name: "multiple tx responses, valid msgIndex 1", + txDataKey: "multiple", + msgIndex: 1, + blockNum: 12, + }, + { + name: "single tx response, valid msgIndex 0", + txDataKey: "single", + msgIndex: 0, + blockNum: 34, + }, + { + name: "single tx response, invalid msgIndex", + txDataKey: "single", + msgIndex: 1, + blockNum: 34, + expectError: true, + }, + { + name: "mixed response types, valid msgIndex 0", + txDataKey: "mixed", + msgIndex: 0, + blockNum: 56, + }, + { + name: "invalid protobuf data", + txDataKey: "invalid", + msgIndex: 0, + blockNum: 78, + expectError: true, + }, + { + name: "nil input", + txDataKey: "nil", + msgIndex: 0, + blockNum: 9, + expectError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + txMsgData, resps := createTxResponseData(t, tc.txDataKey) + logsOut, err := evmtypes.DecodeMsgLogs(txMsgData, tc.msgIndex, tc.blockNum) + if tc.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.NotNil(t, logsOut) + require.Greater(t, len(resps), tc.msgIndex) + expResp := resps[tc.msgIndex] + require.Len(t, logsOut, len(expResp.Logs)) + for i, log := range expResp.Logs { + ethLog := log.ToEthereum() + ethLog.TxHash = common.HexToHash(expResp.Hash) + ethLog.BlockNumber = tc.blockNum + require.Equal(t, ethLog.Address, logsOut[i].Address) + require.Equal(t, ethLog.BlockNumber, logsOut[i].BlockNumber) + } + } + }) + } +} + +func TestDecodeTxLogs(t *testing.T) { + testCases := []struct { + name string + txDataKey string + blockNum uint64 + expectError bool + }{ + { + name: "multiple tx responses, valid msgIndex", + txDataKey: "multiple", + blockNum: 12, + }, + { + name: "single tx response", + txDataKey: "single", + blockNum: 34, + }, + { + name: "mixed response types", + txDataKey: "mixed", + blockNum: 56, + }, + { + name: "invalid protobuf data", + txDataKey: "invalid", + blockNum: 78, + expectError: true, + }, + { + name: "nil input", + txDataKey: "nil", + blockNum: 9, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + txMsgData, resps := createTxResponseData(t, tc.txDataKey) + logsOut, err := evmtypes.DecodeTxLogs(txMsgData, tc.blockNum) + if tc.expectError { + require.Error(t, err) + } else { + require.NoError(t, err) + expLogs := make([]*ethtypes.Log, 0) + for _, resp := range resps { + for _, log := range resp.Logs { + ethLog := log.ToEthereum() + ethLog.TxHash = common.HexToHash(resp.Hash) + ethLog.BlockNumber = tc.blockNum + expLogs = append(expLogs, ethLog) + } + } + require.Equal(t, len(logsOut), len(expLogs)) + for i := range logsOut { + require.Equal(t, expLogs[i].Address, logsOut[i].Address) + require.Equal(t, expLogs[i].BlockNumber, logsOut[i].BlockNumber) + } + } + }) + } +} diff --git a/x/vm/wrappers/testutil/mock.go b/x/vm/wrappers/testutil/mock.go index 0f1710955..ff3ce949f 100644 --- a/x/vm/wrappers/testutil/mock.go +++ b/x/vm/wrappers/testutil/mock.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./x/vm/types/interfaces.go +// +// Generated by this command: +// +// mockgen -source=./x/vm/types/interfaces.go -package=testutil -destination=./x/vm/wrappers/testutil/mock.go -exclude_interfaces=ConsensusParamsKeeper +// // Package testutil is a generated GoMock package. package testutil @@ -28,6 +33,7 @@ import ( type MockAccountKeeper struct { ctrl *gomock.Controller recorder *MockAccountKeeperMockRecorder + isgomock struct{} } // MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. @@ -70,7 +76,7 @@ func (m *MockAccountKeeper) GetAccount(ctx context.Context, addr types.AccAddres } // GetAccount indicates an expected call of GetAccount. -func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr) } @@ -84,7 +90,7 @@ func (m *MockAccountKeeper) GetModuleAddress(moduleName string) types.AccAddress } // GetModuleAddress indicates an expected call of GetModuleAddress. -func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(moduleName interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(moduleName any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), moduleName) } @@ -98,7 +104,7 @@ func (m *MockAccountKeeper) GetParams(ctx context.Context) types0.Params { } // GetParams indicates an expected call of GetParams. -func (mr *MockAccountKeeperMockRecorder) GetParams(ctx interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) GetParams(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParams", reflect.TypeOf((*MockAccountKeeper)(nil).GetParams), ctx) } @@ -113,11 +119,25 @@ func (m *MockAccountKeeper) GetSequence(ctx context.Context, account types.AccAd } // GetSequence indicates an expected call of GetSequence. -func (mr *MockAccountKeeperMockRecorder) GetSequence(ctx, account interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) GetSequence(ctx, account any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSequence", reflect.TypeOf((*MockAccountKeeper)(nil).GetSequence), ctx, account) } +// HasAccount mocks base method. +func (m *MockAccountKeeper) HasAccount(ctx context.Context, addr types.AccAddress) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HasAccount", ctx, addr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// HasAccount indicates an expected call of HasAccount. +func (mr *MockAccountKeeperMockRecorder) HasAccount(ctx, addr any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasAccount", reflect.TypeOf((*MockAccountKeeper)(nil).HasAccount), ctx, addr) +} + // NewAccountWithAddress mocks base method. func (m *MockAccountKeeper) NewAccountWithAddress(ctx context.Context, addr types.AccAddress) types.AccountI { m.ctrl.T.Helper() @@ -127,7 +147,7 @@ func (m *MockAccountKeeper) NewAccountWithAddress(ctx context.Context, addr type } // NewAccountWithAddress indicates an expected call of NewAccountWithAddress. -func (mr *MockAccountKeeperMockRecorder) NewAccountWithAddress(ctx, addr interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) NewAccountWithAddress(ctx, addr any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccountWithAddress", reflect.TypeOf((*MockAccountKeeper)(nil).NewAccountWithAddress), ctx, addr) } @@ -139,7 +159,7 @@ func (m *MockAccountKeeper) RemoveAccount(ctx context.Context, account types.Acc } // RemoveAccount indicates an expected call of RemoveAccount. -func (mr *MockAccountKeeperMockRecorder) RemoveAccount(ctx, account interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) RemoveAccount(ctx, account any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveAccount", reflect.TypeOf((*MockAccountKeeper)(nil).RemoveAccount), ctx, account) } @@ -153,7 +173,7 @@ func (m *MockAccountKeeper) RemoveExpiredUnorderedNonces(ctx types.Context) erro } // RemoveExpiredUnorderedNonces indicates an expected call of RemoveExpiredUnorderedNonces. -func (mr *MockAccountKeeperMockRecorder) RemoveExpiredUnorderedNonces(ctx interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) RemoveExpiredUnorderedNonces(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveExpiredUnorderedNonces", reflect.TypeOf((*MockAccountKeeper)(nil).RemoveExpiredUnorderedNonces), ctx) } @@ -165,7 +185,7 @@ func (m *MockAccountKeeper) SetAccount(ctx context.Context, account types.Accoun } // SetAccount indicates an expected call of SetAccount. -func (mr *MockAccountKeeperMockRecorder) SetAccount(ctx, account interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) SetAccount(ctx, account any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetAccount), ctx, account) } @@ -179,7 +199,7 @@ func (m *MockAccountKeeper) TryAddUnorderedNonce(ctx types.Context, sender []byt } // TryAddUnorderedNonce indicates an expected call of TryAddUnorderedNonce. -func (mr *MockAccountKeeperMockRecorder) TryAddUnorderedNonce(ctx, sender, timestamp interface{}) *gomock.Call { +func (mr *MockAccountKeeperMockRecorder) TryAddUnorderedNonce(ctx, sender, timestamp any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryAddUnorderedNonce", reflect.TypeOf((*MockAccountKeeper)(nil).TryAddUnorderedNonce), ctx, sender, timestamp) } @@ -202,6 +222,7 @@ func (mr *MockAccountKeeperMockRecorder) UnorderedTransactionsEnabled() *gomock. type MockBankKeeper struct { ctrl *gomock.Controller recorder *MockBankKeeperMockRecorder + isgomock struct{} } // MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. @@ -230,7 +251,7 @@ func (m *MockBankKeeper) BurnCoins(ctx context.Context, moduleName string, amt t } // BurnCoins indicates an expected call of BurnCoins. -func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) BurnCoins(ctx, moduleName, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankKeeper)(nil).BurnCoins), ctx, moduleName, amt) } @@ -244,7 +265,7 @@ func (m *MockBankKeeper) GetBalance(ctx context.Context, addr types.AccAddress, } // GetBalance indicates an expected call of GetBalance. -func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) GetBalance(ctx, addr, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockBankKeeper)(nil).GetBalance), ctx, addr, denom) } @@ -259,7 +280,7 @@ func (m *MockBankKeeper) GetDenomMetaData(ctx context.Context, denom string) (ty } // GetDenomMetaData indicates an expected call of GetDenomMetaData. -func (mr *MockBankKeeperMockRecorder) GetDenomMetaData(ctx, denom interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) GetDenomMetaData(ctx, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDenomMetaData", reflect.TypeOf((*MockBankKeeper)(nil).GetDenomMetaData), ctx, denom) } @@ -273,7 +294,7 @@ func (m *MockBankKeeper) GetSupply(ctx context.Context, denom string) types.Coin } // GetSupply indicates an expected call of GetSupply. -func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*MockBankKeeper)(nil).GetSupply), ctx, denom) } @@ -281,7 +302,7 @@ func (mr *MockBankKeeperMockRecorder) GetSupply(ctx, denom interface{}) *gomock. // IsSendEnabledCoins mocks base method. func (m *MockBankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coin) error { m.ctrl.T.Helper() - varargs := []interface{}{ctx} + varargs := []any{ctx} for _, a := range coins { varargs = append(varargs, a) } @@ -291,9 +312,9 @@ func (m *MockBankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types. } // IsSendEnabledCoins indicates an expected call of IsSendEnabledCoins. -func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoins(ctx any, coins ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, coins...) + varargs := append([]any{ctx}, coins...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoins", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledCoins), varargs...) } @@ -304,7 +325,7 @@ func (m *MockBankKeeper) IterateAccountBalances(ctx context.Context, account typ } // IterateAccountBalances indicates an expected call of IterateAccountBalances. -func (mr *MockBankKeeperMockRecorder) IterateAccountBalances(ctx, account, cb interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) IterateAccountBalances(ctx, account, cb any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAccountBalances", reflect.TypeOf((*MockBankKeeper)(nil).IterateAccountBalances), ctx, account, cb) } @@ -316,7 +337,7 @@ func (m *MockBankKeeper) IterateTotalSupply(ctx context.Context, cb func(types.C } // IterateTotalSupply indicates an expected call of IterateTotalSupply. -func (mr *MockBankKeeperMockRecorder) IterateTotalSupply(ctx, cb interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) IterateTotalSupply(ctx, cb any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateTotalSupply", reflect.TypeOf((*MockBankKeeper)(nil).IterateTotalSupply), ctx, cb) } @@ -330,7 +351,7 @@ func (m *MockBankKeeper) MintCoins(ctx context.Context, moduleName string, amt t } // MintCoins indicates an expected call of MintCoins. -func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) MintCoins(ctx, moduleName, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintCoins", reflect.TypeOf((*MockBankKeeper)(nil).MintCoins), ctx, moduleName, amt) } @@ -344,7 +365,7 @@ func (m *MockBankKeeper) SendCoins(ctx context.Context, from, to types.AccAddres } // SendCoins indicates an expected call of SendCoins. -func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, from, to, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, from, to, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, from, to, amt) } @@ -358,7 +379,7 @@ func (m *MockBankKeeper) SendCoinsFromAccountToModule(ctx context.Context, sende } // SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule. -func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } @@ -372,7 +393,7 @@ func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, sende } // SendCoinsFromModuleToAccount indicates an expected call of SendCoinsFromModuleToAccount. -func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } @@ -384,15 +405,30 @@ func (m *MockBankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData typ } // SetDenomMetaData indicates an expected call of SetDenomMetaData. -func (mr *MockBankKeeperMockRecorder) SetDenomMetaData(ctx, denomMetaData interface{}) *gomock.Call { +func (mr *MockBankKeeperMockRecorder) SetDenomMetaData(ctx, denomMetaData any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDenomMetaData", reflect.TypeOf((*MockBankKeeper)(nil).SetDenomMetaData), ctx, denomMetaData) } +// SpendableCoin mocks base method. +func (m *MockBankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, denom string) types.Coin { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SpendableCoin", ctx, addr, denom) + ret0, _ := ret[0].(types.Coin) + return ret0 +} + +// SpendableCoin indicates an expected call of SpendableCoin. +func (mr *MockBankKeeperMockRecorder) SpendableCoin(ctx, addr, denom any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoin), ctx, addr, denom) +} + // MockStakingKeeper is a mock of StakingKeeper interface. type MockStakingKeeper struct { ctrl *gomock.Controller recorder *MockStakingKeeperMockRecorder + isgomock struct{} } // MockStakingKeeperMockRecorder is the mock recorder for MockStakingKeeper. @@ -422,7 +458,7 @@ func (m *MockStakingKeeper) GetHistoricalInfo(ctx context.Context, height int64) } // GetHistoricalInfo indicates an expected call of GetHistoricalInfo. -func (mr *MockStakingKeeperMockRecorder) GetHistoricalInfo(ctx, height interface{}) *gomock.Call { +func (mr *MockStakingKeeperMockRecorder) GetHistoricalInfo(ctx, height any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHistoricalInfo", reflect.TypeOf((*MockStakingKeeper)(nil).GetHistoricalInfo), ctx, height) } @@ -437,7 +473,7 @@ func (m *MockStakingKeeper) GetValidatorByConsAddr(ctx context.Context, consAddr } // GetValidatorByConsAddr indicates an expected call of GetValidatorByConsAddr. -func (mr *MockStakingKeeperMockRecorder) GetValidatorByConsAddr(ctx, consAddr interface{}) *gomock.Call { +func (mr *MockStakingKeeperMockRecorder) GetValidatorByConsAddr(ctx, consAddr any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatorByConsAddr", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidatorByConsAddr), ctx, consAddr) } @@ -460,6 +496,7 @@ func (mr *MockStakingKeeperMockRecorder) ValidatorAddressCodec() *gomock.Call { type MockFeeMarketKeeper struct { ctrl *gomock.Controller recorder *MockFeeMarketKeeperMockRecorder + isgomock struct{} } // MockFeeMarketKeeperMockRecorder is the mock recorder for MockFeeMarketKeeper. @@ -488,7 +525,7 @@ func (m *MockFeeMarketKeeper) CalculateBaseFee(ctx types.Context) math.LegacyDec } // CalculateBaseFee indicates an expected call of CalculateBaseFee. -func (mr *MockFeeMarketKeeperMockRecorder) CalculateBaseFee(ctx interface{}) *gomock.Call { +func (mr *MockFeeMarketKeeperMockRecorder) CalculateBaseFee(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalculateBaseFee", reflect.TypeOf((*MockFeeMarketKeeper)(nil).CalculateBaseFee), ctx) } @@ -502,7 +539,7 @@ func (m *MockFeeMarketKeeper) GetBaseFee(ctx types.Context) math.LegacyDec { } // GetBaseFee indicates an expected call of GetBaseFee. -func (mr *MockFeeMarketKeeperMockRecorder) GetBaseFee(ctx interface{}) *gomock.Call { +func (mr *MockFeeMarketKeeperMockRecorder) GetBaseFee(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBaseFee", reflect.TypeOf((*MockFeeMarketKeeper)(nil).GetBaseFee), ctx) } @@ -516,7 +553,7 @@ func (m *MockFeeMarketKeeper) GetParams(ctx types.Context) types3.Params { } // GetParams indicates an expected call of GetParams. -func (mr *MockFeeMarketKeeperMockRecorder) GetParams(ctx interface{}) *gomock.Call { +func (mr *MockFeeMarketKeeperMockRecorder) GetParams(ctx any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParams", reflect.TypeOf((*MockFeeMarketKeeper)(nil).GetParams), ctx) } @@ -525,6 +562,7 @@ func (mr *MockFeeMarketKeeperMockRecorder) GetParams(ctx interface{}) *gomock.Ca type MockErc20Keeper struct { ctrl *gomock.Controller recorder *MockErc20KeeperMockRecorder + isgomock struct{} } // MockErc20KeeperMockRecorder is the mock recorder for MockErc20Keeper. @@ -545,9 +583,9 @@ func (m *MockErc20Keeper) EXPECT() *MockErc20KeeperMockRecorder { } // GetERC20PrecompileInstance mocks base method. -func (m *MockErc20Keeper) GetERC20PrecompileInstance(ctx types.Context, address common.Address) (vm.PrecompiledContract, bool, error) { +func (m *MockErc20Keeper) GetERC20PrecompileInstance(ctx types.Context, arg1 common.Address) (vm.PrecompiledContract, bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetERC20PrecompileInstance", ctx, address) + ret := m.ctrl.Call(m, "GetERC20PrecompileInstance", ctx, arg1) ret0, _ := ret[0].(vm.PrecompiledContract) ret1, _ := ret[1].(bool) ret2, _ := ret[2].(error) @@ -555,15 +593,16 @@ func (m *MockErc20Keeper) GetERC20PrecompileInstance(ctx types.Context, address } // GetERC20PrecompileInstance indicates an expected call of GetERC20PrecompileInstance. -func (mr *MockErc20KeeperMockRecorder) GetERC20PrecompileInstance(ctx, address interface{}) *gomock.Call { +func (mr *MockErc20KeeperMockRecorder) GetERC20PrecompileInstance(ctx, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetERC20PrecompileInstance", reflect.TypeOf((*MockErc20Keeper)(nil).GetERC20PrecompileInstance), ctx, address) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetERC20PrecompileInstance", reflect.TypeOf((*MockErc20Keeper)(nil).GetERC20PrecompileInstance), ctx, arg1) } // MockEvmHooks is a mock of EvmHooks interface. type MockEvmHooks struct { ctrl *gomock.Controller recorder *MockEvmHooksMockRecorder + isgomock struct{} } // MockEvmHooksMockRecorder is the mock recorder for MockEvmHooks. @@ -592,7 +631,7 @@ func (m *MockEvmHooks) PostTxProcessing(ctx types.Context, sender common.Address } // PostTxProcessing indicates an expected call of PostTxProcessing. -func (mr *MockEvmHooksMockRecorder) PostTxProcessing(ctx, sender, msg, receipt interface{}) *gomock.Call { +func (mr *MockEvmHooksMockRecorder) PostTxProcessing(ctx, sender, msg, receipt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostTxProcessing", reflect.TypeOf((*MockEvmHooks)(nil).PostTxProcessing), ctx, sender, msg, receipt) } @@ -601,6 +640,7 @@ func (mr *MockEvmHooksMockRecorder) PostTxProcessing(ctx, sender, msg, receipt i type MockBankWrapper struct { ctrl *gomock.Controller recorder *MockBankWrapperMockRecorder + isgomock struct{} } // MockBankWrapperMockRecorder is the mock recorder for MockBankWrapper. @@ -629,7 +669,7 @@ func (m *MockBankWrapper) BurnAmountFromAccount(ctx context.Context, account typ } // BurnAmountFromAccount indicates an expected call of BurnAmountFromAccount. -func (mr *MockBankWrapperMockRecorder) BurnAmountFromAccount(ctx, account, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) BurnAmountFromAccount(ctx, account, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnAmountFromAccount", reflect.TypeOf((*MockBankWrapper)(nil).BurnAmountFromAccount), ctx, account, amt) } @@ -643,7 +683,7 @@ func (m *MockBankWrapper) BurnCoins(ctx context.Context, moduleName string, amt } // BurnCoins indicates an expected call of BurnCoins. -func (mr *MockBankWrapperMockRecorder) BurnCoins(ctx, moduleName, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) BurnCoins(ctx, moduleName, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BurnCoins", reflect.TypeOf((*MockBankWrapper)(nil).BurnCoins), ctx, moduleName, amt) } @@ -651,15 +691,15 @@ func (mr *MockBankWrapperMockRecorder) BurnCoins(ctx, moduleName, amt interface{ // GetBalance mocks base method. func (m *MockBankWrapper) GetBalance(ctx context.Context, addr types.AccAddress, denom string) types.Coin { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpendableCoin", ctx, addr, denom) + ret := m.ctrl.Call(m, "GetBalance", ctx, addr, denom) ret0, _ := ret[0].(types.Coin) return ret0 } // GetBalance indicates an expected call of GetBalance. -func (mr *MockBankWrapperMockRecorder) GetBalance(ctx, addr, denom interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) GetBalance(ctx, addr, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankWrapper)(nil).GetBalance), ctx, addr, denom) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockBankWrapper)(nil).GetBalance), ctx, addr, denom) } // GetDenomMetaData mocks base method. @@ -672,7 +712,7 @@ func (m *MockBankWrapper) GetDenomMetaData(ctx context.Context, denom string) (t } // GetDenomMetaData indicates an expected call of GetDenomMetaData. -func (mr *MockBankWrapperMockRecorder) GetDenomMetaData(ctx, denom interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) GetDenomMetaData(ctx, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDenomMetaData", reflect.TypeOf((*MockBankWrapper)(nil).GetDenomMetaData), ctx, denom) } @@ -686,7 +726,7 @@ func (m *MockBankWrapper) GetSupply(ctx context.Context, denom string) types.Coi } // GetSupply indicates an expected call of GetSupply. -func (mr *MockBankWrapperMockRecorder) GetSupply(ctx, denom interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) GetSupply(ctx, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupply", reflect.TypeOf((*MockBankWrapper)(nil).GetSupply), ctx, denom) } @@ -694,7 +734,7 @@ func (mr *MockBankWrapperMockRecorder) GetSupply(ctx, denom interface{}) *gomock // IsSendEnabledCoins mocks base method. func (m *MockBankWrapper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coin) error { m.ctrl.T.Helper() - varargs := []interface{}{ctx} + varargs := []any{ctx} for _, a := range coins { varargs = append(varargs, a) } @@ -704,9 +744,9 @@ func (m *MockBankWrapper) IsSendEnabledCoins(ctx context.Context, coins ...types } // IsSendEnabledCoins indicates an expected call of IsSendEnabledCoins. -func (mr *MockBankWrapperMockRecorder) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) IsSendEnabledCoins(ctx any, coins ...any) *gomock.Call { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, coins...) + varargs := append([]any{ctx}, coins...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoins", reflect.TypeOf((*MockBankWrapper)(nil).IsSendEnabledCoins), varargs...) } @@ -717,7 +757,7 @@ func (m *MockBankWrapper) IterateAccountBalances(ctx context.Context, account ty } // IterateAccountBalances indicates an expected call of IterateAccountBalances. -func (mr *MockBankWrapperMockRecorder) IterateAccountBalances(ctx, account, cb interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) IterateAccountBalances(ctx, account, cb any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateAccountBalances", reflect.TypeOf((*MockBankWrapper)(nil).IterateAccountBalances), ctx, account, cb) } @@ -729,7 +769,7 @@ func (m *MockBankWrapper) IterateTotalSupply(ctx context.Context, cb func(types. } // IterateTotalSupply indicates an expected call of IterateTotalSupply. -func (mr *MockBankWrapperMockRecorder) IterateTotalSupply(ctx, cb interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) IterateTotalSupply(ctx, cb any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateTotalSupply", reflect.TypeOf((*MockBankWrapper)(nil).IterateTotalSupply), ctx, cb) } @@ -743,7 +783,7 @@ func (m *MockBankWrapper) MintAmountToAccount(ctx context.Context, recipientAddr } // MintAmountToAccount indicates an expected call of MintAmountToAccount. -func (mr *MockBankWrapperMockRecorder) MintAmountToAccount(ctx, recipientAddr, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) MintAmountToAccount(ctx, recipientAddr, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintAmountToAccount", reflect.TypeOf((*MockBankWrapper)(nil).MintAmountToAccount), ctx, recipientAddr, amt) } @@ -757,7 +797,7 @@ func (m *MockBankWrapper) MintCoins(ctx context.Context, moduleName string, amt } // MintCoins indicates an expected call of MintCoins. -func (mr *MockBankWrapperMockRecorder) MintCoins(ctx, moduleName, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) MintCoins(ctx, moduleName, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MintCoins", reflect.TypeOf((*MockBankWrapper)(nil).MintCoins), ctx, moduleName, amt) } @@ -771,7 +811,7 @@ func (m *MockBankWrapper) SendCoins(ctx context.Context, from, to types.AccAddre } // SendCoins indicates an expected call of SendCoins. -func (mr *MockBankWrapperMockRecorder) SendCoins(ctx, from, to, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) SendCoins(ctx, from, to, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankWrapper)(nil).SendCoins), ctx, from, to, amt) } @@ -785,7 +825,7 @@ func (m *MockBankWrapper) SendCoinsFromAccountToModule(ctx context.Context, send } // SendCoinsFromAccountToModule indicates an expected call of SendCoinsFromAccountToModule. -func (mr *MockBankWrapperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAddr, recipientModule, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } @@ -799,7 +839,7 @@ func (m *MockBankWrapper) SendCoinsFromModuleToAccount(ctx context.Context, send } // SendCoinsFromModuleToAccount indicates an expected call of SendCoinsFromModuleToAccount. -func (mr *MockBankWrapperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderModule, recipientAddr, amt any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } @@ -811,7 +851,7 @@ func (m *MockBankWrapper) SetDenomMetaData(ctx context.Context, denomMetaData ty } // SetDenomMetaData indicates an expected call of SetDenomMetaData. -func (mr *MockBankWrapperMockRecorder) SetDenomMetaData(ctx, denomMetaData interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) SetDenomMetaData(ctx, denomMetaData any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDenomMetaData", reflect.TypeOf((*MockBankWrapper)(nil).SetDenomMetaData), ctx, denomMetaData) } @@ -825,7 +865,7 @@ func (m *MockBankWrapper) SpendableCoin(ctx context.Context, addr types.AccAddre } // SpendableCoin indicates an expected call of SpendableCoin. -func (mr *MockBankWrapperMockRecorder) SpendableCoin(ctx, addr, denom interface{}) *gomock.Call { +func (mr *MockBankWrapperMockRecorder) SpendableCoin(ctx, addr, denom any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankWrapper)(nil).SpendableCoin), ctx, addr, denom) }